말한 내용으로 YouTube 동영상을 검색 가능하게 만들기: 점프 링크에 대한 타임스탬프 기록(Python)
Make YouTube Videos Searchable by What Was Said: Timestamped Transcripts to Jump Links (Python)
여러분은 40개의 연차 대회 말씀 중 하나에서 어떤 말씀을 설명하는 연사가 기억나지만, 어떤 말씀을, 어디서 말씀했는지는 기억하지 못합니다.
핵심 요약
자동 요약- 1여러분은 40개의 연차 대회 말씀 중 하나에서 어떤 말씀을 설명하는 연사가 기억나지만, 어떤 말씀을, 어디서 말씀했는지는 기억하지 못합니다.
- 2YouTube 자체 검색으로는 동영상 내의 문구를 찾을 수 없습니다.
- 3성적표는 그대로 유지되며 타임스탬프를 유지하면 정확한 초에 연결할 수 있습니다.
원문 본문
출처 · dev.toYou remember a speaker explaining something in one of forty conference talks, but not which talk or where. YouTube's own search won't find a phrase inside a video. Transcripts will, and if you keep the timestamps, you can link to the exact second.
This post builds a small "search inside videos" tool:
- getting captions yourself, and why that breaks,
- pulling timestamped captions in bulk with a hosted Actor, with real output,
- building a phrase search that returns
&t=jump links, plus cost and caveats.
The DIY version
Open-source transcript libraries call YouTube's internal caption endpoints. They work on a laptop, then start failing from cloud servers when requests get blocked, and they break when YouTube changes its page. The official Data API only lets you download captions for videos you own.
The hosted version
YouTube Transcript API: Captions with Timestamps returns the captions that already exist on public videos, whether creator-uploaded or YouTube auto-generated. Disclosure: I build this Actor at SteadyScrape. It doesn't do AI or speech-to-text transcription. If a video has no captions, you get a no_captions row with no transcript charge.
Input matching the current schema:
{ "videos": [ "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "https://youtu.be/9bZkp7q19f0" ], "includeSegments": true } videos accepts watch, youtu.be, shorts, embed and live links, or plain 11-character IDs, up to 200 per run. Duplicates are removed.
Real output from a verified run (trimmed):
{ "videoId": "dQw4w9WgXcQ", "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "status": "ok", "language": null, "requestedLanguage": "en", "chars": 2089, "segmentCount": 61, "durationSec": 211.32, "segments": [ {"start": 1.36, "end": 3.04, "text": "[♪♪♪]"}, {"start": 18.64, "end": 21.88, "text": "♪ We're no strangers to love ♪"} ], "chargeEvent": "transcript" } language is deliberately null: the data source doesn't reliably report which caption track it returned, so the Actor doesn't guess.
Phrase search with jump links
import os from apify_client import ApifyClient VIDEOS = open("talks.txt").read().split() # one URL or ID per line client = ApifyClient(os.environ["APIFY_TOKEN"]) run = client.actor("steady-scrape/youtube-transcripts").call( run_input={"videos": VIDEOS, "includeSegments": True}) segments, skipped = [], [] for row in client.dataset(run["defaultDatasetId"]).iterate_items(): if row["status"] != "ok": skipped.append((row.get("input"), row["status"])) continue for s in row["segments"]: segments.append((row["videoId"], s["start"], s["text"])) def search(phrase): phrase = phrase.lower() for vid, start, text in segments: if phrase in text.lower(): yield f"https://www.youtube.com/watch?v={vid}&t={int(start)}s {text}" for hit in search("rate limit"): print(hit) print("no transcript:", skipped) Caption lines are short, so a phrase can be split across two segments. For better recall, join each segment with its neighbour before matching, or embed windows of about 30 seconds for semantic search in a RAG index. Store videoId and start with every chunk so each answer can cite a timestamp.
What it costs
From the Store pricing:
- $0.005 per transcript returned (status
ok) - $0.003 per run, only if the run returned at least one transcript
- Apify's standard $0.00005 start event
So 40 talks that all return captions cost $0.20305 in one run (40 × $0.005 + $0.003 + $0.00005). Videos without captions, unavailable or invalid videos, timeouts and skipped videos incur no transcript charge, and a run with no transcripts doesn't pay the $0.003 run fee; Apify's $0.00005 start event still applies to every run.
Caveats
- Captions only. Auto-generated captions contain recognition errors and usually no punctuation, so quote carefully.
-
no_captionsis ambiguous. The data source often can't tell a video without captions from a deleted, private or mistyped ID. None of those incur a transcript charge. - No translation in this version.
- Public videos only: no logins, cookies, or private or members-only videos.
- Videos still pending after 5 minutes come back as
timeout(no transcript charge) so you can retry them. The free Apify plan allows up to 10 videos per run.
Integrations
Run it via the Apify API, on a schedule (for example, new uploads from a channel list), or from Make, Zapier or n8n through Apify's integrations. AI agents can call it through the Apify MCP server.
SteadyScrape (steady-scrape) builds small, pay-per-result data tools on Apify.
이 글은 dev.to 의 원문을 정제해 보여드립니다. 저작권은 원저작자에게 있습니다.
전체 내용이 궁금하다면
dev.to 원문에서 이어 읽기





