ナレーション付き動画
ユーザーはストーリーボードに沿って一台撮りのナレーションを収録します。エージェントがそのテイクを編集し、実際の製品スクリーンショットを動画に合わせてアニメーションします。すべてのシーンの開始、クリック、検索のタイピングが、それを示す単語が発話される瞬間に行われます。動画全体はコード(HyperFrames構成と編集リスト)で表現されるため、新しいテイク、画面の変更、順序の入れ替えは、再編集ではなく再実行で対応できます。
動画は常にナレーションに合わせて調整され、逆はありません。ユーザーは味付けを指示し、エージェントはカットを作成し、フレームを表示し、質問をします。
セットアップ
ffmpegがPATHに存在すること、uv、Node 20+ でnpxが使用可能であること(HyperFrames 0.8.62はnpx経由で実行)、PlaywrightとChromiumがキャプチャ用にインストールされていること。macOS、Linux、Windowsで動作します。- Whisperはローカルで実行されます:Apple Siliconではmlx-whisper、その他の環境ではfaster-whisper。
uv runで適切なものがインストールされます。 SK=<このスキルのディレクトリ>/scripts。すべてのツールはuv run $SK/<tool>.pyとして実行され、各ツールが自身の依存関係を宣言します。- リポジトリの追跡ファイルの外にある作業用フォルダ(gitignoreされた
.logs/<video>/フォルダ、またはスクラッチフォルダ)で作業します:
<work>/
assets/ キャプチャ画像、背景、エンドカード
storyboard.json シーン -> storyboard/index.html
takes/<name>/ 収録テイクごとのフォルダ:プローブ出力、文字起こし、edit.json、カットされたナレーションとウェブカム
video.py 構成スクリプト -> comp/ (index.html, renders/)
NOTES.md すべての決定事項:カットとその理由、シーンの開始、再構築コマンド
1. ブリーフィング
短いやり取りで確認し、デフォルト値を提案します:
- フォーマット:ローンチ動画、機能デモ、またはチュートリアル(references/formats.md)。ローンチ動画はエンドカードを含めて2:00以内に収めます。
- 視聴者、動画で伝えるべき3〜4つのポイント、およびコールトゥアクション。
- デモに適したサンプルデータ:この視聴者にとって一目でわかるサンプルビジネスや検索語。
- ブランド:背景画像(またはデフォルトのグラデーション)、エンドカード(製品のOG画像が適しています)、ウィンドウのタイトルバーに表示するURL。
2. キャプチャ
$SK/capture.mjs をベースにしたPlaywrightスクリプトを使用して、実行中の製品の実際のスクリーンショットを1440x900、2倍の解像度で取得します:画面でタイピングされるすべてのキーストロークフレーム、クリックされるものの前後の状態、スクロールされるものの縦長ショット、ポインター用に測定されたクリックターゲット。アプリにサインインが必要な場合は、login を渡すと最初の実行時にブラウザウィンドウが開き、ユーザーが一度だけサインインします。UIを描画したりピクセルを編集したりしないでください。キャプチャは使用前に必ず確認してください。詳細とプライバシーポリシーについては references/capture.md を参照してください。
3. ストーリーボード
storyboard.json を作成します。シーンごとに1カード:スクリーンショット、画面に表示されているもの、言うべき3〜6個の箇条書き(短文、完全な文ではない)、おおよその秒数。作成して表示します:
uv run $SK/storyboard.py storyboard.json storyboard/
これはシンプルなページで、シーンごとにセクションがあります。ハーネスがページを公開できる場合は storyboard/(index.htmlと frames/)を公開し、そうでなければローカルで開きます。ユーザーが録音の準備ができるまで繰り返し、references/storyboard-and-recording.md の録音ノートを渡します。ユーザーが録音を始めたら、断りなくストーリーボードを変更しないでください。
4. 収録
ユーザーは一台撮りで、ウェブカムと音声を1つのファイル(QuickTime、Photo Booth、Windows Camera、OBSなどのウェブカムレコーダー)に収録し、シーンに沿って話します。言い間違えは問題ありません:文を言い直してそのまま続けます。複数のテイクも問題なく、各テイクにフォルダが作成されます。
5. テイクの編集
uv run $SK/probe.py <recording> takes/<name> # take.wav, cam.mp4, take.json;still.jpg を確認し、必要なら --crop で再実行
uv run $SK/transcribe.py takes/<name> # 2パス:通常の文字起こしと、フィラーを書き出すもの
uv run $SK/analyze.py takes/<name> # 候補:長いポーズ(カット候補)、フィラー、言い直し、ノイズ
uv run $SK/trace.py takes/<name> <a>:<b> # 各カットをエネルギートレース上に配置(--fine で5ミリ秒行)
uv run $SK/splicetest.py takes/<name> c1=<a>:<cut start>,<cut end>:<b> # カットを聞く:意図した文として聞こえる必要がある
uv run $SK/jump.py takes/<name> <cut start>:<cut end> --slide 0.3 # ウェブカムバブル内でのカットの見え方
# takes/<name>/edit.json を書き込んだ後:
uv run $SK/edit.py takes/<name> # edl.json;編集後のナレーションと保持されたフィラーを表示:すべて読む
uv run $SK/build.py takes/<name> # narration-edit.wav, cam-edit.mp4(各カットでクロスフェードとウェブカムディゾルブ)
uv run $SK/master.py takes/<name> # narration.wav を -16 LUFS で出力
2レベルの編集があります(references/editing.md):
- ライト編集(デフォルト):言い直しや誤った開始をカットし、無音部分をトリミング(約1.1秒以上のポーズは0.7秒に、シーンチェンジでは0.9秒に短縮)。すべての「えーっと」や短いためらいはそのまま残します。
- フィラー削減版(要求時):フレーズ間で単独で現れるほとんどの「えーっと」を削除し、約0.8秒以上のポーズを約0.55秒にトリミング。隣接する単語に結合されたフィラーはそのまま残します。
- 各カットはトレース上でルームトーンに配置され、採用前にスプライステストに合格する必要があります。言い直しのカットは可能な限りシーンチェンジに配置し、ピクチャーカットでバブルのジャンプを隠します。
6. 言葉に合わせて構成
uv run $SK/cues.py takes/<name> # words.json、キューテーブル(最終ナレーションのクリップレベルの文字起こし)
NV_SCRIPTS=$SK ASSETS=assets uv run --with numpy python video.py # 構成スクリプト -> comp/;すべてのキューをコンテキスト付きで表示
uv run $SK/render.py comp lint
uv run $SK/render.py comp snapshot 1,14.2,22.5,40.1
video.py をサンプル examples/openseo-launch/video.py から作成します:キューテーブルからのシーン開始時間とキュー時間、キャプチャの上に配置されるカメラレイヤー、単語に同期したコレオグラフィ。サンプルのキュー位置はその編集にのみ適合します:すべてのキューを再アンカーし、編集を変更するたびに出力されるキューテーブルを読んでください。タイミングルールは references/composition.md にあります。最も重要なもの:
- シーンは最初の単語の0.3秒前、またはその前のポーズ内のカットのタイミングで開始します。
- 各アクションはそれを示す単語のタイミングで発生します:「コピー」という単語でのクリック、検索が話されるのと同時のタイピング、数字が言われると同時のズーム、各項目が名前で呼ばれると同時のポインター表示。
- 最初のフレームはポスター:アプリ全体、フェードインなし。すべてのフレームで何かが動いています。
- 各ポイントに1つの短いラベル。すべてのシーン開始、クリック、ラベルのスナップショットを撮り、レンダリング前に確認してください。
7. レンダリングと検証
uv run $SK/render.py comp render
uv run $SK/composite.py comp takes/<name> comp/renders/<video>-1080p.mp4
uv run $SK/check.py comp/renders/<video>-1080p.mp4 comp takes/<name>
uv run $SK/filmstrip.py comp/renders/<video>-1080p.mp4 comp/renders/filmstrip.png
チェックで、すべてのフレームにウィンドウが表示され、すべてのウェブカムポイントがフレームオフセット0にあり、オーディオのメディアンが0ミリ秒、約-16 LUFSであることが確認され、かつ文字起こしを読み、フィルムストリップを確認するまでは、ユーザーに動画を渡さないでください(references/verification.md)。
8. レビューと反復
- ユーザーにmp4のパス、カットした内容、注意して聞くべき点を伝えます。
NOTES.mdを最新に保ちます:すべてのカットとその理由、シーンの開始、再構築コマンド。複数ラウンドを想定します。- バリエーションは簡単に作成できます:別のテイク、ライト編集とフィラー削減版、異なるシーン順序。それぞれがテイクフォルダまたは構成スクリプトになります。サブエージェントを使用する場合は、競合を避けるため別々のファイル名で並行してビルドします。
ハードルール
- 実際のスクリーンショットのみ使用。ストーリーに関係のないもの(バナー、クッキー通知)は非表示にし、ピクセルを塗りつぶさないでください。
- キャプチャと録音に秘密情報や個人データ(APIキー、他人のメールアドレスや名前、顧客データ、localhost URL)がないかをレンダリング前に確認し、該当する部分を枠で囲むか再キャプチャし、画面上に表示されたキーはすべて失効させてください。アプリ内のユーザー自身の名前やメールアドレスは、ユーザーが確認すれば問題ありません。
- ユーザーの録音とサインインセッションはユーザーのマシン上に残ります。要求されない限り何も公開しないでください。
よくある失敗例:references/gotchas.md。