Transkrypcje YouTube LlamaIndex: Zapytaj Zbiór Filmów

Rurociąg transkrypcji YouTube LlamaIndex to trzy kroki: pobierz transkrypcje jako obiekty Document, zbuduj VectorStoreIndex, zadawaj pytania dotyczące wszystkich filmów naraz. Oto całe to w jednym skrypcie, plus jeden błąd dzielenia się, który niszczy większość pierwszych prób.
Pobierz transkrypcje jako dokumenty
Prowadzę youtube2text.org, REST API zwracający transkrypcje YouTube jako JSON — bez skrobania z Twojego IP, co ma znaczenie w momencie, gdy to uruchamia się gdziekolwiek indziej niż Twój laptop (zobacz dlaczego lokalni scraperzy zostają blokowani, jeśli jesteś ciekawy). Jedno GET na wideo:
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"]},
))
Dla klucza zaloguj się za pomocą Google na youtube2text.org/app/keys, lub weź wspólny klucz demo z GET https://youtube2text.org/api/demo-key (5 filmów/miesiąc na IP — w porządku dla tego przykładu trzech filmów, nie dla kanału).
Błąd dzielenia: napisy autogenerowane nie mają interpunkcji
Domyślny parser węzła LlamaIndex to SentenceSplitter, który znajduje granice fragmentu na końcu zdania. Ręcznie przesłane napisy mają to. Napisy autogenerowane często nie — otrzymujesz czterdzieści minut małych liter tekstu bez okresów, SentenceSplitter nie znajduje nic do podzielenia, i kończyć się z napuchniętymi, niezręcznymi fragmentami.
Dzielenie oparte na tokenach całkowicie ominięcie problemu:
from llama_index.core.node_parser import TokenTextSplitter
splitter = TokenTextSplitter(chunk_size=512, chunk_overlap=64)
512 tokenów z 64 nakładkami było słodkim punktem w moim testowaniu: wystarczająco duży, że fragment niesie kompletną myśl, wystarczająco mały, że pobieranie pozostaje precyzyjne.
Zbuduj indeks i zbadaj go
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"]})')
Ponieważ każdy Document nosi videoId i title w metadanych, każdy pobrany fragment wie, z jakiego wideo pochodzi — source_nodes daje Ci pracujące linki z powrotem do źródeł. To używa niezależnie od modelu osadzającego i LLM, które skonfigurowałeś w Settings; domyślna konfiguracja OpenAI działa od razu, jeśli OPENAI_API_KEY jest ustawiony.
Ograniczenie, o którym powinieneś wiedzieć
API zwraca transkrypcje jako zwykły tekst bez znaczników czasowych, więc cytaty rozwiązują się do wideo, nie do momentu wewnątrz niego. "To twierdzenie pochodzi z wideo rozkładu Q3" jest osiągalne; "o 14:32" nie jest. W większości przypadków Q&A, atrybucja na poziomie wideo jest wystarczająca, i szczerze, tekst fragmentu plus link do wideo dostawia człowieka do właściwego miejsca w mniej niż minutę.
Zwróć także uwagę na dwa kody błędów godne obsługi w pętli pobierania: TRANSCRIPT_UNAVAILABLE (404, film nie ma napisów — pomiń to) i RATE_LIMIT_EXCEEDED (429, comes z retryAfterSeconds w treści błędu).
Skalowanie poza garść filmów
Trzy filmy to demo. Na całym kanale chcesz kanału RSS do odkrywania wideo, pobierania świadomego kwoty i trwałego magazynu wektorowego — pokrywam ten rurociąg w RAG nad kanałem YouTube. Użytkownik LangChain zamiast tego? Ten sam wzorzec loadera, inny framework.
Bezpłatny poziom obejmuje 5 filmów na miesiąc; pro plan robi 500 za 9,99 USD, co wygodnie indeksuje większość kanałów. Klucze na youtube2text.org/app/keys.