アクティベーション契約
ユーザーが、機能を説明したりバグを再現する音声付きビデオを必要とするとき、またはスクリーンショットだけではフロー(タイミング、シーケンス、状態変化)を示せないときにロードします。単一の静的状態であれば、スクリーンショットで十分です。録画しないでください。
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 コールアウトに配置します |
実行手順
- 作業ディレクトリに該当するテンプレートをコピーし(Trip2:
pr-assets/<name>.json)、title、baseUrl、シーン、セレクタを記入します。 node bin/narrate.mjs validate <file>を実行し、報告されたすべてのパスを修正します。- アプリがセッションを必要とする場合:
playwrightでは、ユーザーにnode bin/narrate.mjs login <url> --save pr-assets/state.jsonを実行してもらい、browser.storageStateを設定します。gdigrabでは、ユーザーは事前に ego でアプリにサインインします(Trip2 のパス:baseUrl= ローカルTrip2 URL、recorder: "gdigrab"、短いシーン、callなし)。 node bin/narrate.mjs run <file>を実行します(またはtts、record、assembleを個別に実行。assemble単独では録画せずに再レンダリングします)。- 結果を確認します:
ffmpeg -ss <t> -frames:v 1でシーンの開始時点のフレームを抽出し(scenes.json)、目視確認します。volumedetectで音声を確認します。evidence.jsonを読みます(gdigrab では空)。gdigrab の場合、フレームにページだけが表示され(デスクトップ、タスクバー、他のウィンドウが重なっていない)ことを確認します。 <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)を備えた完全な動作例。