オレンジ色のケーブルが接続されたパッチパネル
ニュース深掘り

YouTube動画をRAGで検索可能にする方法 15,285セグメントの実例

目次を見る

社内勉強会やカンファレンスの録画が大量に溜まっているものの、検索できずに埋もれているという状況に心当たりはないでしょうか。本記事では、YouTubeチャンネル全体の字幕データを取得し、タイムスタンプ付きで検索できる仕組みをどう組み立てるかを整理します。RAG(Retrieval-Augmented Generation、検索で得た情報をもとにLLMに回答させる手法)をフロントエンドやプロダクトに組み込みたいエンジニアの判断材料になれば幸いです。

題材になっている事例は、Andrej Karpathy氏(元Tesla AI責任者で教育系動画で知られる人物)のチャンネルから直近3本の動画を取得し、検索インデックスを作るというものです。3本合計で約10時間、15,285件の字幕セグメント、598件の1分単位チャンクという規模感が示されています。「flash attentionとは何か」という質問に対して、該当動画の7241秒地点へのリンク(&t=7241s)を返すところまでをPython約60行で実現している点が技術的に興味深いところです。

なぜYouTube字幕の一括取得は面倒なのか

単一動画であれば、YouTubeの字幕パネルを開いてコピーすれば済みます。しかしチャンネル全体となると話は変わります。

選択肢は主に3つに整理できます。1つ目はYouTube Data API(Googleが提供する公式API)ですが、字幕のダウンロードは自分が所有する動画に限られます。2つ目はオープンソースの字幕取得ライブラリで、ローカル環境では動くものの、クラウドサーバー上で実行すると動作しなくなるという報告が多いとされています。3つ目がホスト型のスクレイパー(Webサイトから機械的にデータを収集するツール)で、チャンネルやプレイリストを渡すと字幕をJSON形式で返してくれるというものです。

今回の事例ではApify(クラウド上でスクレイピングや自動化処理を実行できるプラットフォーム)上のYouTube Transcript Scraperという3つ目の方式が使われています。YouTubeアカウントもGoogleのAPIキーもCookieも不要で、RAGパイプラインが動くサーバー環境にそのまま乗せられる点が選定理由として挙げられています。

技術的な仕組みを段階的に見る

ステップ1 字幕の取得

入力はチャンネルのハンドル名(@AndrejKarpathyのような形式)と、取得する動画数の上限(maxVideos)を指定する形式です。transcriptFormat: "both"を指定すると、タイムスタンプ付きのセグメントと、結合済みのプレーンテキストの両方が返ってきます。

RAGで使うのは前者のセグメントです。各行が開始時刻(start)を持っているため、検索結果からそのまま動画内の該当秒数へのリンクを組み立てられるからです。実際の出力例では、1本の動画だけで6,049セグメント、約22万3000文字のテキストが含まれていたと報告されています。

また字幕にはisAutoGeneratedというフラグがあり、自動生成字幕かどうかを判定できます。今回の3本はすべて自動生成字幕で、句読点がなく誤認識(「ChatGPT」が「chpd」と表記されるなど)も含まれています。埋め込みベクトル(文章を数値ベクトルに変換したもの)による意味検索はこうした揺れに比較的強い一方、単純なキーワード一致検索は影響を受けやすい点は注意が必要です。

ステップ2 チャンク分割は時間単位で行う

一般的なRAGのチュートリアルでは、テキストをトークン数(LLMが処理する単語の最小単位)で区切ることが多いですが、動画の場合は時間で区切る設計が合理的です。各チャンクが最初のセグメントの開始時刻を保持し、その時刻がそのまま引用元へのリンクになるためです。

実装では60秒ウィンドウでテキストを束ねており、これは話し言葉にして150〜200語程度に相当します。埋め込みモデルの入力サイズとしても、LLMに渡すコンテキストとしても扱いやすい分量です。リンクは動画URL + "&t=開始秒数s"という単純な文字列結合で生成できます。

ステップ3 検索

生成したチャンク群に対してキーワード検索または埋め込み検索をかけ、該当箇所の開始時刻を回答に添えるという流れです。ベクトルデータベース(埋め込みベクトルを高速検索するための専用DB)を選定する前に、まずプレーンなPythonで検索ロジックを試せる点が、この設計のとっつきやすさになっています。

既存のRAG構成との比較で見えてくること

テキストドキュメントを対象にしたRAGでは、チャンク分割はトークン数や段落単位で行うのが定石です。しかし動画・音声コンテンツでは「意味の区切り」よりも「時間の区切り」を優先したほうが、ユーザー体験として自然な引用になります。これは検索結果が単なるテキストの切れ端ではなく、再生位置という具体的な行動(動画のその場所を見る)に直結するためです。

フロントエンド視点で見ると、この設計は検索UIの実装にも直接影響します。検索結果の各行に「この回答は動画の何分何秒を根拠にしているか」を表示し、クリックで&t=パラメータ付きのYouTube埋め込みプレーヤーにジャンプさせる、という画面構成が素直に作れます。社内ナレッジ検索や動画マニュアルの検索UIを検討しているなら、参考になる設計パターンです。

今日確認できること

自分のプロジェクトでこの仕組みが使えるかどうかを判断するために、確認しておきたいポイントを挙げます。

  • 対象チャンネルや動画に字幕が存在するか(自動生成字幕でも取得対象になるかを確認)
  • 取得したい言語のキャプションがない場合、YouTube側の自動翻訳が走る挙動(wasTranslatedフラグ)を許容できるか
  • Apifyの無料プランは月5ドル分のクレジットが付与される設計なので、まず小規模(動画数本)で試算してから本番運用の動画本数を見積もる
  • 自前でスクレイパーを実装する場合は、クラウド環境でのブロック対策やレート制限への対応コストを見込む

Apifyを使う場合の最小構成は、ConsoleのSettings→API & Integrationsから取得したAPIトークンと、Python 3のrequestsライブラリだけで動きます。ベクトルDBの選定は後回しにして、まずチャンク化と時間ベースのリンク生成だけを自前のPythonスクリプトで試すのが、仕組みを理解する近道です。

まとめ

動画コンテンツをRAGの対象にする際は、テキストRAGの定石をそのまま持ち込むのではなく、時間軸を一次情報として扱う設計が有効だとわかります。

  • チャンク分割は「トークン数」ではなく「時間(60秒程度)」で行うと、引用リンクが自然に作れる
  • 自動生成字幕は誤字を含むため、キーワード検索より埋め込み検索との相性を優先して検討する
  • まず小規模な動画数本で、Apifyの無料クレジット枠を使って挙動を確認してから本番規模を見積もる

社内の録画資産や公開チャンネルを検索可能にしたい場合、まずは対象動画に字幕があるかどうかの確認から始めてみるとよさそうです。

参考

YouTube Transcripts for RAG - Ask a Whole Channel, Get Answers With Timestamps

この記事について: 本記事は AI を活用して作成し、forva AI 編集部が内容を確認・監修しています。

AI 駆動開発のご相談は forva AI へ。まずはお気軽にどうぞ。