HomeBlogTranscribePlansAPI Keys

LangChain YouTube-Transkript-Loader, der die Produktion überlebt

LangChain-Pipeline, die ein YouTube-Video in Document-Objekte und eine Zusammenfassungs-Chain verwandelt

Jeden LangChain YouTube-Transkript-Tutorial zeigt die gleichen drei Zeilen: YoutubeLoader.from_youtube_url(), load, done. Dann bereitest du auf eine Cloud-Box und es gibt stumm nichts zurück. Unten ist ein Loader, der stattdessen richtige Document Objekte von einer gehosteten API zurückgibt — etwa 20 Zeilen, plus eine Zusammenfassungs-Chain zum Beweis, dass es end-to-end funktioniert.

Warum der eingebaute YoutubeLoader auf Servern stirbt

YoutubeLoader ruft keine offizielle API auf. Es kratzt YouTubes interne Untertitel-Endpunkte von der Maschine, auf der dein Code läuft. Von einer Wohn-IP funktioniert das meistens. Von einer AWS-, GCP- oder Hetzner-IP wird es blockiert oder erhält leere Antworten, weil YouTube Rechenzentrum-Traffic als Bot-Traffic behandelt. Ich schrieb die Details in warum YouTube-Transkript-Scraping auf Cloud-IPs bricht — die Kurzversion ist, dass der Fehler umweltbedingt ist, daher besteht es jeden lokalen Test und stirbt genau dort, wo es zählt.

youtube2text.org macht das Abrufen auf seiner Seite und reicht dir JSON, was deinen Loader zu einem einfachen HTTP-Aufruf macht.

Der 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,
        },
    )

Die API gibt videoId, title, pubDate, content, contentSize und ein truncated Flag zurück. Transkript-Text geht in page_content, alles andere in Metadaten — genau die Form, die nachgelagerte Chains und Vector Stores erwarten.

Noch keinen Schlüssel? Grab den gemeinsamen Demo-Schlüssel:

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

Es ist auf 5 Videos pro Monat pro IP begrenzt, das ist genug zum Testen des Loaders.

Eine Zusammenfassungs-Chain

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 stuffs das ganze Transkript in einen Prompt, das funktioniert weil maxChars die Payload standardmäßig bei 150.000 Zeichen begrenzt. Für stundenlange Podcasts auf Small-Context-Modellen, übergeben einen niedrigeren maxChars zum Loader oder schalte zu einem Map-Reduce-Muster.

Was in echtem Code zu handhaben ist

Zwei Fehlermodi lohnen sich explizit zu fangen. Ein Video mit deaktivierten Untertiteln gibt HTTP 404 mit Fehlercode TRANSCRIPT_UNAVAILABLE zurück — kein Retry oder Bibliotheks-Swap behebt das, der Text existiert einfach nicht. Und RATE_LIMIT_EXCEEDED (429) enthält retryAfterSeconds im Fehler-JSON, also lese es und backoff statt zu hämmern:

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

Eine ehrliche Begrenzung: content ist reiner Text ohne Zeitstempel. Das ist fine für Zusammenfassungen und Abruf, aber wenn du "jump zu 12:34" Deep Links brauchst, musst du dich mit Video-Level-Zuschreibung via dem videoId in Metadaten zufrieden geben.

Wohin von hier

Die gleichen Document Objekte tropfen direkt in einen Vector Store — ich gehe durch die ganze Pipeline in RAG über einen ganzen YouTube-Kanal. Wenn dein Stack LlamaIndex statt LangChain ist, ist das equivalent setup genau so kurz.

Wenn des Demo-Keys 5 Videos nicht mehr ausreichen, hole dir deinen eigenen Schlüssel — kostenlose Stufe inbegriffen, bezahlte Pläne ab $5,99 für 50 Videos pro Monat.