Answers
How do I build a RAG chatbot over YouTube video transcripts?
Short answer
Search YouTube for the videos you want ($0.004 per page of about 20), fetch each transcript with timestamps ($0.004 a video), cut the segments into time windows and embed them in any vector store. A 200-video knowledge base costs about $0.84 to collect, and every answer can link to the exact second it came from.
A fitness coaching company has 200 long videos of its own coaches answering questions, plus the best talks from others in the field. They want a chatbot that answers "how should I warm up for heavy squats?" with two sentences and a link that jumps to 14:32 in the right video. That is a RAG pipeline with one twist: keep the timestamps all the way through, because a link to the moment is worth more than a summary.
The pipeline
- Collect video IDs. Use YouTube video search with topic keywords, or with a channel's name plus a topic. There is no endpoint that lists every upload of a channel, so for your own channel copy the IDs from YouTube Studio.
- Fetch transcripts. YouTube video transcript takes an 11-character video ID and an optional
lang, and returnssegments(start, end, text) plus the fulltext. - Chunk by time. Merge segments into windows of about 60 to 90 seconds. Keep
video_id, title and the window's start second on every chunk. - Embed and store with whatever you already use: LlamaIndex, LangChain, pgvector, Qdrant.
- Answer with citations. Build
https://youtu.be/<id>?t=<start>from the chunk metadata and make the model cite it.
Steps 1 to 3 in Python
import json, os, requests
API = "https://api.okdata.online"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
def get(path, **params):
body = requests.get(API + path, headers=H, params=params, timeout=90).json()
if body["code"] != "ok":
raise RuntimeError(f"{body['code']}: {body['message']}")
return body["data"]
videos = get("/v1/youtube/videos/search", query="squat warm up coaching",
fields="id,title,url")["items"]
with open("chunks.jsonl", "w", encoding="utf-8") as out:
for v in videos:
try:
tr = get("/v1/youtube/videos/transcript/get", id=v["id"], lang="en")["item"]
except RuntimeError as err: # no captions, private, removed: not charged
print("skip", v["id"], err)
continue
window, start = [], None
for seg in tr["segments"]:
start = seg["start"] if start is None else start
window.append(seg["text"])
if seg["end"] - start >= 75:
out.write(json.dumps({"video_id": v["id"], "title": v["title"], "start": int(start),
"text": " ".join(window)}, ensure_ascii=False) + "\n")
window, start = [], None
if window:
out.write(json.dumps({"video_id": v["id"], "title": v["title"], "start": int(start),
"text": " ".join(window)}, ensure_ascii=False) + "\n")
Each line of chunks.jsonl is ready to embed.
What collection costs
| Knowledge base | Calls | Cost |
|---|---|---|
| 50 videos | 3 searches + 50 transcripts | {{cost:youtube.videos.search3+youtube.videos.transcript.get50}} |
| 200 videos | 10 searches + 200 transcripts | {{cost:youtube.videos.search10+youtube.videos.transcript.get200}} |
| 1,000 videos | 50 searches + 1,000 transcripts | {{cost:youtube.videos.search50+youtube.videos.transcript.get1000}} |
Updating is cheaper than building: once a month, fetch transcripts only for IDs you have not stored yet.
Things that bite
- Auto-generated captions misspell names and jargon. Add a glossary to your answer prompt, or fix terms before embedding.
- Videos without captions fail and are not charged. If they matter, transcribe their audio separately.
- Ask for the language you embed in with
lang; mixing languages in one index hurts retrieval. - The transcripts belong to their creators. Answering questions internally is one thing; republishing them is another.
Alternatives
LlamaIndex's YoutubeTranscriptReader and LangChain's YoutubeLoader are free and build on youtube-transcript-api. They work well from a laptop, while their issue trackers have many reports of them failing from cloud and serverless IPs. For your own channel, YouTube Studio and the YouTube Data API give you the captions you uploaded. Whisper on the audio covers videos with no captions at all, at the cost of downloading and compute. More on this job on the transcripts page.
Updated