Communitygithub.com

Video2presentation

セミナー、ウェビナー、カンファレンスの録画を編集可能なスライドデッキに変換します。動画フレームからスライドを抽出し、注釈付きリンク、トランスクリプトの抜粋をスピーカーノートとして追加します。

Video2presentation とは?

このスキルは、セミナーやウェビナー、カンファレンスの録画を、編集可能なGoogleスライドデッキに変換するためのものです。動画フレームから主要なスライドを抽出し、OCRでテキストを認識、QRコードやリンクを検証し、AssemblyAIによる文字起こしからスピーカーノートを生成します。主なユースケースは、話者のスライドやデモを忠実に再現しつつ、リンク一覧や講演者間の相違点を含む統合的なデッキを自動構築することです。Claude Code環境での実行を前提としており、音声認識と一部の画像処理にクラウドAPI(AssemblyAI)を利用しますが、動画自体はユーザーのローカルマシンで処理されるためセキュリティ面でも安心です。高度なカスタマイズとして、話者識別の補正、フレーム抽出の精度調整、ノートの文字数制限への対応など、細かなワークフローを制御できます。

対応✓Claude Code~Codex CLI~Cursor
npx skills add nielssrb/Video2presentation

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Video2presentation: セミナー録画 → プレゼンテーション

決定事項と測定値の詳細な履歴は、Video2presentationフォルダ内のMETHODOLOGY.mdにあります。このスキルとMETHODOLOGY.mdで矛盾がある場合は、このスキルに従ってください。新しい教訓はMETHODOLOGY.mdに追加してください。

常に適用されるルール

  1. 最初に計画と質問。 処理を開始する前に、以下の手順に従った計画をユーザーに伝え、AskUserQuestionを使用して明確化のための質問をしてください(質問リストはステップ0にあります)。回答を得てから作業を開始してください。
  2. ユーザーへの返信。 ユーザーの言語(通常は英語以外)で、正直に、お世辞なしで返信してください。すべての数値はスクリプトで計算してください。情報は表としてフォーマットし、ユーザーが要求した場合のみプレーンテキストを使用してください。更新のたびにプレゼンテーションリンクを提供してください。
  3. セキュリティ。
    • AssemblyAIキーはassemblyai_key.txtファイルからのみ読み取ってください。決して印刷したり、クラウド、ノート、アーティファクトにコピーしたりしないでください。
    • スピーカーがMiroボードを表示している場合でも、MiroやFigmaの統合は使用せず、ビデオフレームからボードを取得してください。
    • 許可なくユーザーのフォルダ内のものを削除しないでください。_work/ワーキングフォルダも含みます。
  4. 正確性。
    • スピーカーを黙って訂正しないでください。矛盾点や数値の不一致は、タイムコード付きでノートに記録してください。
    • スライドの数値はスクリプトで再計算してください。
    • 法的な主張を確認し、スライドに短い注意書きを追加してください。
    • 最終的な要点は、スピーカーのスライドではなく、統合としてマークしてください。
  5. ビデオはクラウドにアップロードしません。 ffmpeg、OpenCV、文字起こしはユーザーのコンピュータ(device_bash)上で実行されます。コンタクトシート、モザイク、個々のフレーム、切り抜きのみがクラウドに送信されます。これらは、確認、認識、またはアーティファクトへのアップロードのために必要なものです。

ファイルの場所

  • スキルとプロジェクトフォルダはVideo2presentationです(Coworkの場合は接続フォルダ$HOME/mnt/Video2presentation、Claude Codeの場合はカレントフォルダ)。そのルートには、スキル自体(SKILL.md)とMETHODOLOGY.mdがあります。
  • pipeline/ — スクリプト:
    • transcribe_assemblyai.py — AssemblyAIを使用した文字起こし;
    • extract_slides.py — 1秒あたり1フレーム、ウェブカムマスク、安定セグメント、重複除去、コンタクトシート;
    • mosaic.py — フレームリストから2×2モザイクを作成;
    • crop_images.py と crops_<日付>[_<スピーカー>].json — 画像の切り抜き;
    • clean_transcript.py — スライドごとにクリーニングされたトランスクリプトの抜粋。
  • assemblyai_key.txt — AssemblyAI APIキー。ファイルがない場合があります。ステップ0とステップ1を参照してください。
  • イベントフォルダ YYYY.MM.DD 名前/: ビデオ、場合によっては説明(html、またはユーザーのメッセージ内のテキスト)、場合によっては既製のトランスクリプト(sentences.json、transcript.txt)が含まれます。中間ファイルは<イベントフォルダ>/_work/に配置してください。
  • スクリプトがない場合は、末尾の「pipeline/ が利用できない場合」を参照してください。

ステップ0. 偵察、計画、質問

  1. イベントフォルダを調査:
    • ビデオ: 解像度、時間、fps(ffprobe); 別の解像度のコピーがあるかどうか;
    • 既製のトランスクリプト;
    • assemblyai_key.txtが存在するかどうか — トランスクリプトを新たに作成する必要がある場合に必要;
    • イベントの説明(オプション): 名前、Telegramハンドル、トークのトピック。ユーザーのメッセージの最後か、htmlファイルにある場合があります。説明がない場合は、録画自体から名前とトピックを取得してください。
  2. 計画を提示し、AskUserQuestionで質問してください。「推奨」オプションは、ユーザーが以前に選択したものです。
    • トランスクリプト: 既製のものがあればそれを使用(推奨)、またはAssemblyAIで新しいものを作成。
    • スライドノート: スライドが表示されている時間の、軽くクリーニングされたトランスクリプト抜粋(推奨)、逐語的な抜粋、またはタイムコード付きの短い要約。
    • 4000文字を超える抜粋(Slidesノートの制限): 「[…]」マークで短くする(前回のユーザーの選択)か、スライドを分割。
    • フォーマット「前回と同じ」(推奨): 詳細でオリジナルに近いもの。質疑応答を含むスライドとしてのトーク内の質問; 広告や組織的な部分はスキップ; 全体的な要点と統合リンクリストを最後に。
    • スピーカーの数 — 説明から明らかでない場合(話者分離に必要)。
  3. 最終検証ステップを含むタスクリストを作成。

ステップ1. トランスクリプト

  • 既製のトランスクリプト: 最初に確認 — スピーカーラベルと単語レベルのタイムスタンプが存在し、時間がビデオと一致すること。すべて揃っていれば、再実行は不要。

  • AssemblyAIキー。 新しいトランスクリプトの前に、assemblyai_key.txtがフォルダルートに存在し、空でないことを確認。ファイルがない場合、このステップを続行せず、ユーザーに伝えてください: assemblyai.comにサインアップし、APIキーを取得して、フォルダルートのassemblyai_key.txtに保存する必要があること(またはキーを送信してもらい、そのファイルに保存し、他の場所には繰り返さないこと)。ステップ0の計画でこれをすぐに伝えるのが最善です。

  • 新しいトランスクリプト。 低解像度コピーから、再エンコードせずに音声を抽出:ffmpeg -i in.mp4 -vn -c:a copy audio.m4a。その後:

    python3 pipeline/transcribe_assemblyai.py audio.m4a <OUT> --key-file assemblyai_key.txt --lang <言語コード> [--speakers --min-speakers N --max-speakers M] --submit-only
    python3 pipeline/transcribe_assemblyai.py - <OUT> --key-file assemblyai_key.txt --fetch --wait 150   # 完了するまで繰り返し
    
    • 英語以外の音声の場合は、録画の言語をサポートするモデルを使用します。2026年10月時点ではuniversal-2です。
    • 話者分離は複数の人が話している場合のみ: 単一の音声では誤ったA/Bラベルが生成されます。
    • ドメインapi.assemblyai.comは許可リスト(設定 → 機能)に含まれている必要があります。プロキシが403を返した場合はユーザーに伝え、回避策を講じないでください。
    • 価格 — 1時間あたり約$0.15 + 話者分離で1時間あたり$0.02。
  • 作業ファイル transcript_sent.txt: 1行 = N [h:mm:ss] LABEL: 文、Nは1から始まる文番号。config.jsonとoverrides.jsonはこれらの番号を参照します。

  • ラベル → 人。 ホストが人々に話しかける方法(「レオニード、あなたが最初ですね?」)、説明、内容によって照合します。典型的な話者分離のエラー:

    • 1人の人物に2つのラベルが割り当てられる;
    • トーク全体が1つの発話になる;
    • 聴衆からの短い質問が隣の人に帰属される。

    修正をconfig.jsonに記述:names(ラベル → 名前)、speaker_by_line(行 → 名前)、drop_lines(削除する行)。

  • トークの境界: タイムコードとして記録 — イントロ、各トークとそのQ&A、クロージング。これがデッキのセクション構造です。

ステップ2. フレーム

  • 解像度。 2つのコピーがある場合: 低解像度コピーで分析(--reduce 2)、テキストと切り抜きは高解像度コピーから(ffmpeg -ss <秒> -i hd.mp4 -frames:v 1 hd/NNNNN.jpg)。1つのコピーの場合: --reduce 4(低解像度の場合は--reduce 2); 大きなテキストはフレームから直接読み取れます。
  • チャンクで抽出。 device_bashには1回の呼び出しで約180秒の制限があり、バックグラウンドプロセスは存続しません。
    python3 pipeline/extract_slides.py video.mp4 <OUT> --chunk 1000
    python3 pipeline/extract_slides.py video.mp4 <OUT> --skip-extract --reduce 4
    
    • ffmpegの速度は大きく変動します: 過去の実行では、実時間の10倍から48倍。最初のチャンクで速度を測定し、0.8 × 制限 × 速度以下のチャンクサイズを選択してください。
    • 呼び出しをtimeoutでラップ; 不完全なチャンクはフレーム番号で完了させてください。
    • 2つのffmpegプロセスを2コアで並行実行しても高速化しません。
    • フレームNNNNN.jpg = 秒数N−1。
  • ウェブカム。 マスクは自動的に検出されます。Google Meetレイアウト(左に画面共有、右にカメラ)では不要です。スピーカーのカメラウィンドウは通常右上隅にあります — 切り抜きとOCRはそれを避けます。
  • レビュー。 すべてのフレームではなく、コンタクトシート(sheets/)を確認: クラウドに移動して開きます。詳細については、2×2モザイクを使用:python3 pipeline/mosaic.py HD_DIR OUT PREFIX 00165 00179 …。
  • アニメーションスライドは選択から外れます: 動く背景は安定セグメントを生成しません。スピーカーのスライド番号(01/16、06/17…)を確認。明示的なフレームリストから作成されたモザイクを使用して、隣接する見つかったスライド間の秒数のギャップを探します。
  • ファイルをクラウドに移動する は接続フォルダからのみ機能: VM作業ディレクトリ(~/w…)から_work/にコピーしてください。

ステップ3. 論理スライド

目標は、ビデオをフレームごとに繰り返すことではなく、プレゼンテーション可能なスライドを取得することです。

  • スピーカーのスライド。 テキストを再入力(OCRは草案のみ); グラフやスクリーンショットを切り抜きとして挿入。エディタ(サムネイルストリップ付き)での同じスライド、ズームまたは一時停止は重複です。全画面のものを採用してください。
  • ボード(Miro、Excalidraw)。 スライド = スピーカーが話しているボードブロック; 同じブロックのパンやズームは重複です。トークの進行に応じてボードが埋まっていく場合は、最後の完全なフレームを取得し、ブロックごとにスライドに分割してください。
  • アプリインターフェース。 結果(テーブル、レポート、ダッシュボード、ボットの返信)が表示された画面を取得し、中間のクリックは取得しないでください。
  • スクロールを伴うライブウェブサイトデモ — フレームとしてではなく、トランスクリプトから再話(「スピーカーの言葉からのスライド」)。
  • 全画面ウェブカム はスライドではありません。その内容はスピーカーの言葉からのスライドに含めます。
  • 質疑応答 — トークの最後に個別のスライド: 質問(質問者の名前付き)と回答の要点。
  • ホストによる広告と組織的な部分: スキップ。スピーカー自身の広告(コース、価格)は参照として簡潔に提供します。ユーザーが別途要求した場合を除きます。
  • デッキ構造:
    • 表紙とアジェンダ;
    • 各トークについて: セクションタイトルスライド、内容、質問、「リンクとサービス」スライド;
    • 全体的な要点 — 「統合」とマークし、スピーカー間の矛盾を含める;
    • 統合リンクリスト。
  • 各スライドについて、トークプレフィックス(l-、v-…)付きのID、ソースフレーム、画面上のインターバルを記録。

ステップ4. 画像

  • 切り抜き座標をフルサイズフレーム上でpipeline/crops_<YYYY-MM-DD>[_<スピーカー>].jsonに保存、フォーマット {"name": ["00556.jpg", x0, y0, x1, y1]}。
  • 切り抜き: python3 pipeline/crop_images.py FRAMES crops.json OUT --scale 2 --jpg(低解像度の場合)、--scale 1 --jpg(高解像度の場合)。
  • フレームやウェビナー資料内の個人データ(名前、連絡先、ログイン情報、通信内容)を確認したり隠したりしないでください。そのまま引き継ぎます。

ステップ5. テキスト、OCR、QR、数値

  • OCR。 ユーザーのコンピュータでは、tesseractは通常英語のみです。他の言語の場合はクラウドを使用: apt-get install tesseract-ocr-<言語コード>、カメラウィンドウを白く塗りつぶし、フレームを1.5倍にアップスケール、tesseract -l <言語コード>+eng。結果をフレームと照合: 名前は歪みます。
  • QRコード: 高解像度フレームでcv2.QRCodeDetector、結果はqr.json。
  • 数値。 スライドからの行の合計、パーセンテージ、「1件あたり約1,700」などの数値をスクリプトで再計算。矛盾を修正せず、次のように記録: 「行の合計は60.3k、スライドには64kとある」。ラベルのないグラフから読み取った値は「≈」でマーク。

ステップ6. リンク

  • ソース: フレーム内のアドレス、QRコード、音声、イベントの説明(Telegramハンドル)。ASRは名前を歪めます(invoice.com → 「インボイシン」、Gwen → Qwen、JLM → GLM)。そのため、正しいスペルはフレームまたは検索から取得してください。
  • 検証。 WebSearchまたはWebFetchですべてのリンクを確認し、確認日をスライドフッターに記載。Product Hunt(producthunt.com)やThere's An AI For That(theresanaiforthat.com)などのカタログは、サービスの公式アドレスと説明をすぐに提供します。
  • 開かなかった場合 — curlやミラーで回避しないでください。t.me は頻繁に429を返します: 再試行せず、「スライドのアドレスですが、ページが開きませんでした」とマーク。
  • 見つからなかった場合 — そのように伝える: 「サービスが見つかりませんでした」、「リンクは後で約束されました」。
  • 配置場所。 各トークの最後のスライド: 1行の注釈付きリンク。そのノートには、より詳細: それが何か、ウェブサイトからの価格、スピーカーがどのように使用しているか、何が見つからなかったか。デッキの最後に — 統合スライド: カテゴリ別のスピーカーとツール。

ステップ7. ノート — トランスクリプト抜粋

  • インターバル。 ranges.json — [["スライドID", 開始秒, 終了秒], …]、録画全体にわたってギャップや重複がないこと。スライド変更フレームと意味によって境界を設定: スピーカーは多くの場合、切り替え前に次のスライドについて話し始めます。
  • 生成: python3 pipeline/clean_transcript.py <イベントフォルダ>/_work はnotes.jsonを作成し、ノートの長さを出力(3700より長い場合は<-- LONG)。
  • 軽いクリーニング:
    • スクリプト内のASRエラー辞書REPL: 一般的な置換は維持し、ウェビナー固有のものを追加;
    • 文頭のフィラーワード(スクリプト内のFILLリスト)は自動的に削除;
    • overrides.jsonで文を1行ずつ修正("行番号": "テキスト" または null)、スピーカーの意味と語順を維持; 不明瞭な部分は「[録音では聞き取れません]」とマーク;
    • オーバーライドのある行は再度クリーニングされません。
  • 生成後の確認: 繰り返し文がないこと(オーバーライドが隣接行を複製する可能性があります)、および失われた行がないこと(インターバル内のすべての行がノート内にあるか、drop_linesで意図的に削除されていること)。
  • ノートのフォーマット(デッキの言語で記述):
    録音抜粋 1:31:02–1:33:05:
    [1:31:02] アルチョム: …
    [1:31:09] スタニスラフ: …
    
    1~2行の備考: ボードのテキスト、数値の不一致、名前の明確化。
    
  • 4000文字制限。 制限を超える場合は、ステップ0でユーザーが決定したように、「[…]」で短縮するか、スライドを分割。

ステップ8. Claude Slidesでの組み立て

  • Slidesタイプ(Artifactクイックスタート、インテントスライド)からアーティファクトを作成し、そのSKILL.mdに従ってください。経験上重要なこと(2026年10月時点のタイプルール):
    • 最初に、完全な順序とセクション(各トークに1セクション)を含むdeck.jsonを作成...

...(以降は翻訳対象外)

関連スキル