HomeBlogTranscribePlansAPI Keys

Loader Transkrypcji YouTube LangChain, Który Przetrwa Produkcję

Rurociąg LangChain zamieniający wideo YouTube na obiekty Document i łańcuch podsumowania

Każdy samouczek transkrypcji YouTube LangChain pokazuje te same trzy linie: YoutubeLoader.from_youtube_url(), załaduj, gotowe. Potem wdrażasz do pudełka w chmurze i cicho zwraca nic. Poniżej jest loader zwracający właściwe obiekty Document z hostowanego API zamiast — około 20 linii, plus łańcuch podsumowania, aby udowodnić, że to działa end do end.

Dlaczego wbudowany YoutubeLoader umiera na serwerach

YoutubeLoader nie wymaga oficjalnego API. Skruba YouTube wewnętrzne punkty końcowe napisów z maszyny, która go uruchamia. Z domowego IP to w większości działa. Z AWS, GCP, lub adresu Hetzner to się blokuje lub serwuje puste odpowiedzi, ponieważ YouTube traktuje ruch centrum danych jako ruch botów. Napisałem szczegóły w dlaczego YouTube transkrypcja skrobania przerw na chmurze IPs — krótko: niepowodzenie jest środowiskowe, więc przechodzi każdy test lokalny i umiera dokładnie tam, gdzie ma znaczenie.

youtube2text.org robi pobieranie po jego stronie i przekazuje Ci JSON, które zamienia Twój loader w zwykłe wywołanie HTTP.

Loader

import requests
from langchain_core.documents import Document

API_KEY = "yt_your_key_here"

def load_youtube_transcript(url: str, max_chars: int = 150000) -> Document:
    resp = requests.get(
        "https://youtube2text.org/api/transcribe",
        params={"url": url, "maxChars": max_chars},
        headers={"x-api-key": API_KEY},
        timeout=90,
    )
    resp.raise_for_status()
    r = resp.json()["result"]
    return Document(
        page_content=r["content"],
        metadata={
            "videoId": r["videoId"],
            "title": r["title"],
            "pubDate": r["pubDate"],
            "source": url,
        },
    )

API zwraca videoId, title, pubDate, content, contentSize i flagę truncated. Tekst transkrypcji idzie do page_content, wszystko inne do metadanych — dokładnie kształt, którego oczekują łańcuchy dalsze i magazyny wektorowe.

Brak klucza jeszcze? Weź wspólny klucz demo:

curl https://youtube2text.org/api/demo-key

Jest ograniczony do 5 filmów na miesiąc na IP, co wystarczy do testowania loadera.

Łańcuch podsumowania

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain

llm = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template(
    "Summarize this video transcript in five bullet points:\n\n{context}"
)
chain = create_stuff_documents_chain(llm, prompt)

doc = load_youtube_transcript("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
print(chain.invoke({"context": [doc]}))

create_stuff_documents_chain wkleja całą transkrypcję w jeden prompt, co działa, ponieważ maxChars ogranicza ładunek do 150 000 znaków domyślnie. W przypadku podcastów o godzinach na modelach małego kontekstu, przekaż niższy maxChars do loadera lub przejdź do wzorca mapy redukcji.

Co obsługiwać w rzeczywistym kodzie

Dwa tryby niepowodzenia są godne sprzeciwu jawnie. Film z wyłączonymi napisami zwraca HTTP 404 z kodem błędu TRANSCRIPT_UNAVAILABLE — brak ponownej próby czy wymiany biblioteki to naprawia, tekst po prostu nie istnieje. A RATE_LIMIT_EXCEEDED (429) zawiera retryAfterSeconds w JSON błędu, więc przeczytaj go i cofnij się zamiast młócenia:

if resp.status_code == 429:
    wait = resp.json()["error"].get("retryAfterSeconds", 60)

Jedno szczere ograniczenie: content jest zwykłym tekstem bez znaczników czasowych. To jest w porządku dla podsumowania i pobierania, ale jeśli potrzebujesz linków głębokich "jump to 12:34", będziesz musiał zadowolić się atrybutem poziomu wideo poprzez videoId w metadanych.

Gdzie iść stąd

Te same obiekty Document wpadają bezpośrednio do magazynu wektorowego — przechodzę przez pełny rurociąg w RAG nad całym kanałem YouTube. Jeśli Twój stos to LlamaIndex zamiast LangChain, równoważna konfiguracja jest tak samo krótka.

Gdy klucz demo 5 filmów przestaje być wystarczający, uzyskaj własny klucz — bezpłatny poziom zawarty, płatne plany od 5,99 USD za 50 filmów na miesiąc.