LlamaIndex YouTube Transkriptioner: Fråga en uppsättning videor

En LlamaIndex YouTube transkriptionspipeline är tre steg: hämta transkriptioner som Document-objekt, bygga en VectorStoreIndex, ställ frågor över alla videor på en gång. Här är hela saken i ett skript, plus det en chunkings-gotcha som förstör de flesta första försöken.
Hämta transkriptioner som dokument
Jag kör youtube2text.org, ett REST API som returnerar YouTube-transkriptioner som JSON — ingen skrapning från din egen IP, vilket spelar roll det ögonblicket detta körs någonstans annat än din bärbara dator (se varför lokala skrapare blir blockerade om du är nyfiken). En GET per video:
import requests
from llama_index.core import Document, VectorStoreIndex
API_KEY = "yt_your_key_here"
VIDEOS = [
"https://www.youtube.com/watch?v=VIDEO_ID_1",
"https://www.youtube.com/watch?v=VIDEO_ID_2",
"https://www.youtube.com/watch?v=VIDEO_ID_3",
]
def fetch_transcript(url: str) -> dict:
resp = requests.get(
"https://youtube2text.org/api/transcribe",
params={"url": url},
headers={"x-api-key": API_KEY},
timeout=90,
)
resp.raise_for_status()
return resp.json()["result"]
docs = []
for url in VIDEOS:
r = fetch_transcript(url)
docs.append(Document(
text=r["content"],
metadata={"videoId": r["videoId"], "title": r["title"]},
))
För en nyckel, logga in med Google på youtube2text.org/app/keys, eller dra den delade demo-nyckeln från GET https://youtube2text.org/api/demo-key (5 videor/månad per IP — bra för det här tre-video-exemplet, inte för en kanal).
Chunkings-gotchan: auto-bildtexter har ingen skiljetecken
LlamaIndex:s standardnodanalysator är SentenceSplitter, som hittar chunkgränser vid meningslut. Manuellt uppladdade bildtexter har dessa. Automatiskt genererade bildtexter gör ofta inte — du får fyrtio minuter med gemener utan perioder, SentenceSplitter hittar ingenting att dela på, och du slutar med tjocka, besvärliga chunks.
Tokenbaserad delning förbigår problemet helt:
from llama_index.core.node_parser import TokenTextSplitter
splitter = TokenTextSplitter(chunk_size=512, chunk_overlap=64)
512 tokens med 64 överlappning har varit den söta punkten i mitt testande: tillräckligt stor så att en chunk bär en komplett tanke, tillräckligt liten så att hämtningen förblir exakt.
Bygga indexet och fråga det
index = VectorStoreIndex.from_documents(docs, transformations=[splitter])
query_engine = index.as_query_engine(similarity_top_k=4)
response = query_engine.query("What did they say about pricing changes?")
print(response)
for node in response.source_nodes:
meta = node.metadata
print(f'- {meta["title"]} (https://www.youtube.com/watch?v={meta["videoId"]})')
För varje Document bär videoId och title i metadata, varje hämtad chunk vet vilken video den kom från — source_nodes ger dig arbetande länkar tillbaka till källorna. Detta använder vilken inbäddningsmodell och LLM som helst du har konfigurerat i Settings; standardinställningen OpenAI-inställningen fungerar direkt från lådan om OPENAI_API_KEY är inställd.
Begränsningen du bör veta om
API:t returnerar transkriptioner som vanlig text utan tidsstämplar, så dina citat löser sig till en video, inte ett ögonblick inuti den. "Det här påståndet kom från Q3-resultatsammanfattningen video" är möjligt; "på 14:32" är det inte. För de flesta Q&A-användningsfall är videonivåattribut nog, och ärligt talat, chunktext plus en videolänk får en människa till rätt plats på under en minut.
Notera även de två felkoder värda att hantera i hämtningsloopen: TRANSCRIPT_UNAVAILABLE (404, videon har inga bildtexter — hoppa den) och RATE_LIMIT_EXCEEDED (429, kommer med retryAfterSeconds i felkroppen).
Skalning förbi en handfull videor
Tre videor är en demo. För en hel kanal vill du RSS-feeden för videoupptäckt, kvotmedveten hämtning och ett beständigt vektorlager — jag täcker den pipelinen i RAG över en YouTube-kanal. LangChain-användare i stället? Samma laddarmönster, olika ramverk.
Gratis nivå täcker 5 videor per månad; pro-planen gör 500 för $9,99, som bekvämt indexerar de flesta kanaler. Nycklar på youtube2text.org/app/keys.