HomeBlogTranscribePlansAPI Keys

LangChain YouTube トランスクリプトローダー (本番環境で生き残れるもの)

YouTube ビデオをドキュメントオブジェクトと概要チェーンに変える LangChain パイプライン

すべてのLangChain YouTubeトランスクリプトチュートリアルは同じ3行を示します: YoutubeLoader.from_youtube_url()、ロード、完了。その後、クラウドボックスにデプロイして、静かに何も返しません。以下は、ホストされたAPIから代わりに適切なDocumentオブジェクトを返すローダーです―約20行、プラス、それが終わりまで機能することを証明するための概要チェーン。

組み込み YoutubeLoader がサーバーで失敗する理由

YoutubeLoaderは公式APIを呼び出しません。それはコードが実行されるマシンからYouTubeの内部字幕エンドポイントをスクレイピングします。住宅用IPからはほぼ機能しています。AWS、GCP、またはHetzner IPからはブロックされるか、空のレスポンスが提供されます。YouTubeはデータセンタートラフィックをボットトラフィックとして扱うためです。YouTubeトランスクリプトスクレイピングがクラウドIPで壊れる理由の詳細を書きました―短いバージョンは、エラーが環境的であるため、すべてのローカルテストに合格し、重要なまさにそこで死にます。

youtube2text.orgは自分の側でフェッチを行い、JSONを渡します。これはローダーを素のHTTPコールに変えます。

ローダー

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 はvideoIdtitlepubDatecontentcontentSize、およびtruncatedフラグを返します。トランスクリプトテキストはpage_contentに、他のすべてはメタデータに―下流チェーンとベクトルストアが期待する形状です。

まだキーを持っていないですか? 共有デモキーをつかんでください:

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

月5ビデオあたりIPに制限され、ローダーをテストするのに十分です。

概要チェーン

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はトランスクリプト全体を1つのプロンプトに詰め込み、maxCharsがデフォルトではペイロードを150,000文字でキャップするため、機能しています。小規模なコンテキストモデルの長時間のポッドキャストの場合、ローダーに下位のmaxCharsを渡すか、マップリダクスパターンに切り替えます。

実際のコードで処理する方法

2つの障害モードは明示的にキャッチする価値があります。字幕が無効なビデオは、エラーコードTRANSCRIPT_UNAVAILABLEでHTTP 404を返します―再試行またはライブラリスワップはそれを修正しません。テキストは単に存在しません。RATE_LIMIT_EXCEEDED(429)はエラーJSONにretryAfterSecondsを含むため、それを読んで、ハンマーリングの代わりにバックオフします:

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

1つの正直な制限: contentはタイムスタンプなしのプレーンテキストです。これは要約と検索には問題ありませんが、「12:34にジャンプ」ディープリンクが必要な場合、メタデータのvideoIdを通じてビデオレベルの属性に落ち着く必要があります。

ここから行く場所

同じDocumentオブジェクトはベクトルストアに直接落ちます―YouTube チャネル全体のRAGのフルパイプラインを説明します。スタックがLangChainではなくLlamaIndexの場合、等価なセットアップは短いです。

デモキーの5ビデオが十分でなくなったとき、独自のキーを取得―無料ティアが含まれ、月50ビデオの有料プラン$5.99から。