AI・機械学習
フレーム選択がすべて:LLMに動画を見させるための考察
Frame selection is the whole game: notes on making LLMs watch video (leoaido.com)
要約
LLMが動画を理解するには、限られたトークン予算内で最も重要なフレームを選択することが鍵となります。単なる一定間隔でのサンプリングでは、情報が欠落したり冗長になったりするため、シーン検出、グローバルな変化、局所的な状態変化を捉えるための多段階のデデュープリケーション手法が提案されています。これにより、動画の内容とトランスクリプトを統合し、ローカル環境でLLMが動画を「視聴」できるようにするパイプラインが構築されます。
全文翻訳
LLMは動画あたり約150枚の画像しか処理できません。どの150枚を選ぶかで、モデルが動画を視聴したのか、それとも単なるスライドショーを見ただけなのかが決まります。これらは、MITライセンスのローカルパイプラインであるclaude-real-videoを構築する際に、何度も間違えながら得た私の考察です。
動画は動画についての記事ではない
同じ内容の記事を書くのにトークンがはるかに少なく済むのに、なぜLLMに動画をフィードするのでしょうか?それは、記事がイベントの誰かによる圧縮だからです。人間がそれを視聴し、何が重要かを決定し、残りを捨てました。フレーム、タイミング、画面上の関連がないと判断されたもの。LLMが記事を読むとき、それはその著者の選択の中で学びます。カットされたものを回復することはできず、見たことのない選択に同意することもできません。
モデルに動画を与えれば、圧縮ステップはモデルに移ります。デモが実際にはどう見えたか、レビューアがどう言ったかではなく、デモが実際に見えたものをモデルが見ます。チュートリアルで一瞬表示されたエラーメッセージに気づいたり、誰も書き起こさなかった「簡単なセットアップ」に11回のカットがあったことを捉えたりします。同じ主題でも、証言を読むのと証人になるのとでは、立場が大きく異なります。だからこそ、トークンコストを支払う価値があり、この記事の残りはそれを賢く使う方法についてです。
予算の問題
今日の「動画理解」のほとんどは、トランスクリプトとタイマーでサンプリングされたフレームの組み合わせです。1秒ごと、または10秒ごとのフレーム。均一なサンプリングは、両方の方向で同時に失敗します。話している人の顔のほとんど同じフレームでモデルを埋め尽くし、実際に何かが起こった1秒をスキップしてしまいます。どちらの場合も根本原因は同じです。サンプラーは何が変わったのか全く分かっていません。
すべてを形作る制約は、トークン予算です。画像は、コンテキストウィンドウに入れられる最も高価なものです。「動画あたり約100〜150フレーム、期間」を受け入れると、抽出は問題ではなくなります。選択が問題なのです。保持されるすべてのフレームは、そのスロットを稼ぐ必要があります。
シーン検出、そしてなぜ固定閾値では不十分なのか
最初のパスは標準的です。ffmpegのシーンスコア。シーン変更ごとにフレームを取得し、長いカットがない場合でも何かが出力されるように低い密度フロアを設定します。すべてを時系列で1つのパスで行います。なぜなら、後で重複排除する際に実際の隣接フレームを比較する必要があるからです。
固定閾値は、アニメーションやゆっくりとしたカメラワークのような特定の種類のコンテンツでは機能しません。漫画のキャラクターが潰れたり伸びたりする動きや、ゆっくりとしたパンは絶えず変化しますが、決してシャープではありません。スコアは線を超えず、サンプラーはその間ずっとスリープ状態になります。
修正は退屈ですが、機能します。メタデータのみのパスでフレームごとのシーンスコアを計算し、そのスコアがローリング平均の倍数を上回ったときにフレームを保持します。動きの多い映像はハードルを上げ、静かな映像はハードルを下げます。誰も調整する必要はありません。
重複排除:1つのチャンネルが3つになった
デデュープは1つのコンパレーターから始まり、実際の映像がそれを恥ずかしい思いをさせるたびにチャンネルが増えました。
1. グローバルチャンネル
16x16 RGBシグネチャにダウンサンプリングし、いずれかのチャンネルで25/255以上変化したセルの数を数え、約8%未満しか変化しなかった場合はフレームをドロップします。RGB、グレースケールではありません。なぜなら、同じ輝度を持つ赤から緑へのカットは、グレースケールコンパレーターでは同一に見えるからです。そして、前のフレームだけでなく、直近4つの保持されたフレームのスライディングウィンドウと比較します。そうでなければ、A-B-Aカット(インタビューショット、リアクションショット、インタビューに戻る)は、異なるフレームが間にあったという理由だけで、モデルがすでに見たショットを再認識してしまいます。
2. アクションチャンネル
パーセンテージ閾値は、小さな被写体に対して構造的に盲目です。広角ショットの0.5%を占める人物は、何をしていてもピクセルの8%を変化させることはできません。そのため、重要だった1秒間が重複排除されてしまいます。これはベンチマークで見つけたものではありません。ユーザーがツールを2,181本の実際の動画に適用した後で見つけました。パッチ:32x32グリッドで、たとえ数個のセルがハードに変化(45/255以上)した場合でも、パーセンテージに関係なくフレームは新しいとカウントされます。小さな被写体、シャープな変化、保持。
3. 安定チャンネル
グローバルチャンネルは、小さな局所的な状態変化(キャプションの切り替え、ホワイトボードにインクの線が現れる、UI要素の更新)を見ることもできません。それらは16x16では0.0%を測定します。そのため、3番目のチャンネルは192x192のシグネチャで動作し、保持ウィンドウ内のすべてのフレームと強く異なるピクセルを探します。フィルムの揺れ、センサーのジッター、グレインがそうでないとすべて変化として登録されるのを防ぐために、ピクセルの一致でプラスマイナス1ピクセルのシフトを許可します。検出器よりもガードの方が重要です。動きは他のチャンネルの仕事なので、シーンが静止している場合にのみ実行されます。候補ピクセルは、2番目の、より厳しい許容パスを生き残る必要があります。これにより、煙が消散するようなソフトコントラストのドリフトは排除されますが、インクやテキストはハードコアを維持して生き残ります。そして、トリガーされた各キープは、減衰するクールダウンでゲートを上げます。そのため、毎秒「安定」するフラグは毎回フレームを掴むことはできませんが、単一の新しいテキストカードはベースゲートで通過します。クールダウンがないと、この1つのチャンネルだけで、1つの揺れる旗にフレーム予算全体を消費してしまいます。
トランスクリプトとのフレームの融合
テキストは、動画に埋め込まれている場合は字幕から、そうでなければローカルのWhisperから取得します。2つの詳細は実際のデバッグ時間を要しました。Whisperは、音楽のみのオーディオで動画の終盤を時々幻覚します。セグメントのタイムスタンプを信頼するタイムラインを構築し、架空のラインがそれを飲み込みます。そのため、すべてがメディアの期間にクランプされ、プラス1秒の許容誤差が追加されます。なぜなら、期間はしばしば上流で整数に切り捨てられるからです。
モデルにトランスクリプトとフレームの山を与え、「タイムスタンプで」結合させることは、短い動画ではうまく機能しますが、長い動画では静かにずれが生じます。フレームが間違った文に対して引用されます。そのため、結合は事前に計算されます。各トランスクリプトセグメントは、その中に収まるフレームのリストを持ち、1.5秒を超える無音期間はフレームのみの期間になります。1つのクロックです。読者が結合する必要のあるものは何も残っていません。
すべてがプレーンファイルとして提供されます。JPEG、テキストトランスクリプト、そしてモデルにパッケージの読み方を指示するマニフェストです。出力は意図的に退屈です。それがモデル間でポータブルになる理由です。
MCPでの提供
最新のインターフェースはMCPサーバーです。pip install "claude-real-video[mcp]"、次にcrv-mcpを実行します。任意のMCPクライアント(Claude Desktop、Claude Code、Cursor)は、watch_videoをURLまたはファイルで呼び出し、融合された結果を取得できます。2つの予算決定はそのまま引き継がれました。フレームは、コンテキストをゼロの視覚的利益のために燃焼させるため、インラインに戻る前に長い辺で768pxにリサイズされます。そして、分析はソースごとにキャッシュされるため、同じ動画に関する後続の質問は、何も再ダウンロードまたは再抽出することはありません。
試してみる
上記のすべては、無料のMITライセンスツールに出荷されます。コマンドを1つ入力すると、プレーンファイルが出力されます。
# Python 3.10+ と ffmpeg が必要
pip install "claude-real-video[whisper]"
crv "https://youtube.com/watch?v=..."
# またはローカルファイル
→ frames/*.jpg
# 選択されたキーフレーム
→ transcript.txt
# タイムスタンプ付き、フレームと融合
→ MANIFEST.txt
# 任意のLLMにパッケージの読み方を指示
出力をビジョン対応モデルにドラッグするか、MCPクライアントにcrv-mcp経由でパイプライン全体を自分で駆動させます。
まだキャプチャされていないもの
キーフレームと融合されたトランスクリプトは、モデルに画面上のものと話されたことを伝えます。それらはカメラの動き、カットのリズム、または声のトーンを運びません。それは別の知覚の問題であり、この投稿の範囲外です。しかし、「モデルに回答する前に実際にこのものを見させる」という日常的なケースでは、選択と融合は驚くほど多くの範囲をカバーし、すべて自分のマシンで行われます。
コード(上記すべてを含む):github.com/HUANGCHIHHUNGLeo/claude-real-video (MIT)。
leoaido.com · Leo Huang (黃志弘) 著