Communitygithub.com

jeider05/narrated-evidence

トリガー:ビデオナレーション、バグのナレーション、機能のナレーション、音声付きビデオ、エビデンスビデオ、デモナレーション。narrate CLI を使って、機能やバグのナレーション付きスクリーンビデオを録画します。

narrated-evidence とは?

このスキルは、`narrate` CLI ツールを使用して、機能説明やバグ再現のためのナレーション付きスクリーンビデオを録画・生成するエージェント機能です。Node.js、ffmpeg、Chrome、Edge-TTS を必要とし、Playwright または gdigrab(Windows ネイティブ)の2つの録画モードをサポートします。まず `narration.json` にスクリプトと操作手順を記述し、ツールが自動で TTS 音声と画面操作を同期して合成します。バグ報告時はテンプレートに従ってコンテキスト→手順→実際の結果→期待結果→エビデンスの構造で映像を生成し、PR デモでは機能の価値→画面遷移→エッジケースをカバーします。重要なルールとして、パスワードを決して入力せず、非決定的なフロー(LLM 応答など)は画面キャプチャで結果を確認し、音声と画面が矛盾する場合は録り直すことを徹底します。また、gdigrab モードではユーザーが別ウィンドウマネージャ ego 上でサインインした状態を利用し、OS ネイティブダイアログや select ポップアップも録画可能です。出力は H.264+AAC の MP4 ビデオと SRT 字幕ファイルです。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/jeider05/ai-video-evidence/tree/HEAD/skills/narrated-evidence

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

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

ドキュメント

アクティベーション契約

ユーザーが、機能を説明したりバグを再現する音声付きビデオを必要とするとき、またはスクリーンショットだけではフロー(タイミング、シーケンス、状態変化)を示せないときにロードします。単一の静的状態であれば、スクリーンショットで十分です。録画しないでください。

CLI は C:\Users\DESARROLLADORES\Documents\personal\ai-video-evidence にあります(node bin/narrate.mjs)。Node 22+、PATH 上の ffmpeg/ffprobe、Google Chrome、および pip install edge-tts が必要です。

ハードルール

  • 最初にスクリプト(narration.json)を書き、検証してから録画します。手動で録画とナレーションを行わないでください。
  • 1シーン=1つのアイデアと1~2文。音声はそのシーンで画面に表示されている内容を説明し、次に何が来るかは決して説明しません。
  • ナレーション言語は対象ユーザーに合わせます(Trip2 PRではスペイン語)。デフォルト音声は es-CO-SalomeNeural、男性は es-CO-GonzaloNeural。
  • パスワードを決して入力しないでください。認証が必要なアプリでは、ユーザーが narrate login <url> を実行してサインインします。browser.storageState を保存されたファイルに設定します。録画後はそのファイルを削除し、git に含めないでください。
  • ユーザーが確認したテストデータのみを使用します。新しいレコードには QA_ プレフィックスを付けます。既存のレコードは編集または削除しないでください。
  • 出力物は git の管理外に置きます(out/、pr-assets/)。
  • 非決定的なフロー(LLM、非同期ジョブ)の場合:録画されたフレームで結果を確認します。アプリがナレーションと異なる動作をした場合は、再度録画します。音声と画面が矛盾するビデオを決して出荷しないでください。

決定ゲート

状況アクション
バグ報告assets/bug-template.json:コンテキスト → 手順 → 実際の結果(赤いコールアウト) → 期待結果(緑) → エビデンス → 影響
機能 / PR デモassets/feature-template.json:何を解決するか → 画面遷移 → エッジケース
バックエンド待ちまたは遅い読み込み独自のシーンにし、"speedup": 4 を設定します。ナレーション後の部分のみ加速されます
ネイティブ <select> ポップアップ、OS ダイアログ、またはアプリがユーザーの実際の ego セッションを必要とする場合(Trip2 ログイン済み)"recorder": "gdigrab"(Windows のみ)。実行前に、ユーザーは ego でアプリにサインインし、モニター1 を空けておき、ランナーが要求したときに ego のタスクスペース narrate-<name> に切り替えられる準備をします(ego は Agent ウィンドウを非表示にし、ランナーは Win32 でそれを前面に表示しますが、ego は選択されたスペースのみを描画します)。無人実行 = playwright を使用
gdigrab スクリプトが call/actionsModule または waitForResponse を使用サポートされていません(検証エラー)。実際のバックエンドまたはローカルサーバー(examples/bug-demo/server.mjs)と、UI 結果に対する waitFor を使用してください
gdigrab の実行が "never became visible on screen" で失敗タスクスペースウィンドウが非表示または隠れていました。ユーザーに ego でスペースを選択して再実行するよう依頼してください。ユーザー自身のスペースやタブを主張したり再利用したりしないでください
モックや複雑な手順が必要エクスポートされた async (page, ctx) 関数を持つ actionsModule を使用し、{ "call": "name" } で呼び出します
バグのエビデンス手順最初の実行から out/<name>/evidence.json(失敗したレスポンス、コンソールエラー)を読み取り、実際のリクエスト/ステータスを evidencia コールアウトに配置します

実行手順

  1. 作業ディレクトリに該当するテンプレートをコピーし(Trip2: pr-assets/<name>.json)、title、baseUrl、シーン、セレクタを記入します。
  2. node bin/narrate.mjs validate <file> を実行し、報告されたすべてのパスを修正します。
  3. アプリがセッションを必要とする場合:playwright では、ユーザーに node bin/narrate.mjs login <url> --save pr-assets/state.json を実行してもらい、browser.storageState を設定します。gdigrab では、ユーザーは事前に ego でアプリにサインインします(Trip2 のパス:baseUrl = ローカルTrip2 URL、recorder: "gdigrab"、短いシーン、call なし)。
  4. node bin/narrate.mjs run <file> を実行します(または tts、record、assemble を個別に実行。assemble 単独では録画せずに再レンダリングします)。
  5. 結果を確認します:ffmpeg -ss <t> -frames:v 1 でシーンの開始時点のフレームを抽出し(scenes.json)、目視確認します。volumedetect で音声を確認します。evidence.json を読みます(gdigrab では空)。gdigrab の場合、フレームにページだけが表示され(デスクトップ、タスクバー、他のウィンドウが重なっていない)ことを確認します。
  6. <name>.mp4(H.264 + AAC + ソフト字幕)と <name>.srt を納品します。Trip2 PR の場合は trip2-pr-delivery に従います:アーティファクトは pr-assets/ に配置し、PR に添付し、説明にリストします。

アクションリファレンス

goto(baseUrl からの相対パス)、click、hover、check(セレクタ)、fill/select {selector, value}、press {key, selector?}、scroll {selector? | y?}、wait(ミリ秒)、waitFor(セレクタまたは {selector, state, timeoutMs})、waitForResponse(URL の部分文字列、シーン内で既に見られたレスポンスも受け付けます)、overlay {kind: actual|expected|info, title?, text | html, durationMs?}、screenshot(名前)、call(actionsModule のエクスポート)。セレクタは Playwright ロケータです(#id、text=Guardar、role=button[name="Guardar"])。recorder: "gdigrab" の場合、セレクタはそのまま ego に渡されます:生の CSS、text=...、loc=role:button[name='Guardar']、@ref。call と waitForResponse は拒否されます。check、scroll {selector}、waitFor は生の CSS セレクタに対して page.evaluate/waitForFunction を使用します。

シーンフィールド:id(スラッグ)、say、chapter {title, description?, durationMs?}、actions、speedup。トップレベル:title、baseUrl、recorder(playwright | gdigrab)、gdigrab {framerate: 25, drawMouse: true, tab: "new"}、viewport(Playwright のみ)、tts {engine: edge|deepgram|sapi, voice, rate, fallback}、browser {channel, headless, locale, storageState}、captions、showActions、gapMs、actionsModule、output。

出力契約

返すもの:ビデオパスと長さ、SRT パス、使用した TTS エンジン(およびフォールバック)、シーンとその開始時間、evidence.json がキャプチャしたもの、および表示できなかったもの(ネイティブポップアップ、不安定な手順)。

参考

  • assets/bug-template.json、assets/feature-template.json — スクリプトのスケルトン。
  • リポジトリ README.md — インストール、コマンド、同期の仕組み。
  • examples/bug-demo/ — モックされたバックエンド(narration.json、Playwright)と gdigrab バリアント(narration-ego.json + server.mjs)を備えた完全な動作例。

関連スキル