HomeBlogTranscribePlansAPI Keys

RAG över en YouTube-kanal: från RSS till svar med källhänvisningar

Pipeline från en YouTube-kanals RSS-flöde via transkriptioner och embeddings till svar med källhänvisningar

Att bygga RAG över en YouTube-kanal innebär att kunna svara på "vad har den här kreatören sagt om X, och i vilken video?" — över allt de har publicerat. Pipelinen består av fyra steg: upptäck videor via RSS, hämta transkriptioner, chunka och skapa embeddings, svara med attribution. Här är varje steg i körbar Python, inklusive delarna de flesta genomgångar hoppar över: kvothantering och hur källhänvisningar ärligt talat ser ut utan tidsstämplar.

Steg 1: video-ID:n från kanalens RSS-flöde

YouTube levererar fortfarande ett riktigt RSS-flöde per kanal, ingen API-nyckel krävs:

import requests
import xml.etree.ElementTree as ET

CHANNEL_ID = "UCxxxxxxxxxxxxxxxxxxxxxx"
NS = "{http://www.youtube.com/xml/schemas/2015}"

feed = requests.get(
    f"https://www.youtube.com/feeds/videos.xml?channel_id={CHANNEL_ID}",
    timeout=30,
).text
video_ids = [el.text for el in ET.fromstring(feed).iter(f"{NS}videoId")]

Brasklapp: flödet returnerar bara de ~15 senaste uppladdningarna. För en aktiv kanal, kör det här enligt schema och ackumulera ID:n i en fil eller tabell; bakkatalogen bortom det kräver YouTube Data API eller en manuell engångslista. Men för att hålla ett index färskt är RSS perfekt — det är också ryggraden i pipelinen från kanal till nyhetsbrev.

Steg 2: hämta transkriptioner, respektera kvoten

import time

API_KEY = "yt_your_key_here"

def fetch(video_id: str) -> dict | None:
    resp = requests.get(
        "https://youtube2text.org/api/transcribe",
        params={"url": f"https://www.youtube.com/watch?v={video_id}"},
        headers={"x-api-key": API_KEY},
        timeout=90,
    )
    if resp.status_code == 404:
        return None  # TRANSCRIPT_UNAVAILABLE — no captions, skip
    if resp.status_code == 429:
        time.sleep(resp.json()["error"].get("retryAfterSeconds", 30))
        return fetch(video_id)
    resp.raise_for_status()
    return resp.json()["result"]

transcripts = [t for vid in video_ids if (t := fetch(vid))]

Räkna på din plan innan du loopar över en kanal: gratisnivån är 5 videor i månaden, vilket täcker ett proof of concept och inget mer. Basic (5,99 USD) ger 50, pro (9,99 USD) ger 500 — pro är det realistiska golvet för att indexera en kanal plus dess löpande uppladdningar.

Steg 3: chunka och skapa embeddings

Vilken vektordatabas som helst fungerar; Chroma håller exemplet kort. Auto-undertexter saknar ofta interpunktion, så jag chunkar efter antal ord i stället för meningar:

import chromadb

def chunk(text: str, size: int = 300, overlap: int = 50):
    words = text.split()
    for i in range(0, len(words), size - overlap):
        yield " ".join(words[i:i + size])

client = chromadb.PersistentClient(path="./channel_index")
col = client.get_or_create_collection("channel")

for t in transcripts:
    for i, piece in enumerate(chunk(t["content"])):
        col.add(
            ids=[f'{t["videoId"]}-{i}'],
            documents=[piece],
            metadatas=[{"videoId": t["videoId"], "title": t["title"]}],
        )

Steg 4: svara med källhänvisningar — den ärliga versionen

API:et returnerar ren text utan tidsstämplar, så jag ska vara rak: du kan inte citera "vid 23:41" från den här datan. Vad du kan göra — och vad som oftast räcker — är videoattribution på chunknivå: varje hämtad chunk känner till sitt videoId och sin title, så svaren anger vilken video som sa det, med en fungerande länk.

hits = col.query(query_texts=["what's their take on electric trucks?"], n_results=5)

context = "\n\n".join(
    f'[{m["title"]}] (https://www.youtube.com/watch?v={m["videoId"]})\n{doc}'
    for doc, m in zip(hits["documents"][0], hits["metadatas"][0])
)
prompt = (
    "Answer using only the excerpts below. After each claim, "
    f"cite the video title in brackets.\n\n{context}\n\nQuestion: ..."
)

Mata prompt till valfri LLM — en lokal modell fungerar utmärkt här, samma upplägg som i Ollama-sammanfattningspipen.

Monteringsanvisningar

Ramverksfolk: det här mappar ett-till-ett mot LlamaIndex eller LangChain om du hellre slipper handrulla chunkningen. Oavsett vilket är transkriptionslagret identiskt, och det är den enda delen med en mätare på sig — hämta en nyckel på youtube2text.org/app/keys och börja med gratisnivån för att validera pipelinen innan du riktar den mot 300 videor.