video-demo について
video-demo は Web アプリのデモを撮影するスキルで、シーン別動画、ナレーション、ポスター、静止画、ツアーページを生成します。エンジンはスキル内で動作し、ビルドの分離、リクエストのモック、シーンごとの確認を重視します。
主な機能
- 01シーンを撮影して MP4 を生成
- 02ナレーション・ポスター・高解像度静止画の作成
- 03全体ツアーとマニフェストページの出力
- 04ビルドモードと公開サイトモードに対応
- 05映像を確認しシーン単位で反復
活用シーン
- 01単一機能のデモ映像の作成
- 02製品全体のシーン別ツアーの計画
- 03モックデータを使ったビルド版の録画
- 04映像を確認して構図やナレーションを修正
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nilbuild/ video-demo --skill video-demoインストール後、Claude Code で/video-demoを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.gitattributes.gitignoreLICENSEREADME.mdpackage-lock.jsonpackage.jsonengine/serve.mjsrun.mjspin-build.mjsplaywright.demo.tsengine/studio/actor.tsconfig.tsdefine.tspreview.tsrecorder.tsoverlay.tsscene.tsready.tsrun-id.tsstitch.tsstage.tsvoice.tsreferences/mocking.mdnarration.mdconfig.mdcapture.mdscenes.mdruns.mdtroubleshooting.mdscripts/demo詳細
動画デモ
scripts/demo はウェブアプリを撮影し、そのプロジェクトの
ワークスペースに demo-out/ を書き込みます。シーンごとにナレーション付きの mp4、ポスター、
Retina 用静止画を生成し、さらに full-tour.mp4、manifest.json、index.html を出力します。すべてローカルで動作します。エンジンはこのスキルから実行され、撮影対象のアプリには何もインストールされません。
絶対に守ること
以下の各項目に違反すると、再実行が必要になったり、ユーザーを待たせたりします。
- 開発サーバーではなく、ビルドを固定します。 モジュールグラフはソースを編集している人のものです。ビルドを非公開の場所にコピーし、バンドルを読んで API ベースを確認します。背後にリポジトリがない URL は
siteモードです。localhost の URL は開発サーバーであり、撮影には使いません。 buildモードでは、すべてのリクエストをプロセス内でモックし、時刻を固定します。 コーパスを公開することになり、実際のアカウントを使うと、実在する人々の住所を公開することになります。siteモードでは、この両方を承知のうえで諦め、公開ページのみを対象にします。- ポートと出力ディレクトリは自分で管理します。 スタジオは、自分で起動していないサーバーを引き継ぎません。パターン指定で
pkillを実行しないでください。 - 動画は 1080p60、静止画は 2x にします。 これらは別々の設定です。4K 動画は、スループットが 1 秒あたりのピクセル数で固定されているため、カクつきます。
- 操作を行い、結果を拡大してからナレーションします。 1 行につき 1 つの対象にします。対象が表示される前にナレーションを始めないでください。アプリに独自のタイマー(取り消し可能な時間やトーストなど)がある場合は、その間に操作を行い、後から説明します。そうしないと、機能が動作しない様子を撮影することになります。
- 1 シーンだけ撮影したら停止して確認を求めます(手順 8)。これにより、さらに 26 シーンを撮影する前に 4 つの不具合を発見できました。
- 毎回 PNG を確認します。 間違った対象にフレームを合わせたまま撮影を通過しても失敗です。それを見つけられるのは、静止画を目で確認することだけです。
- 相手が承認するまで、何も最終版ではありません。 説明の言葉、フレーム、テンポ、内容、声について指摘があれば、交渉ではなく撮り直しです。変更して、もう一度撮影してください。相手にはあなたが見ているものが見えないため、「長すぎる」「もっとズームインして」「ズームしすぎないで」は、いずれも十分な指示です。シーンは 2 回撮影しても手間はかかりません。
ワークフロー
- 与えられた情報からモードを選びます。質問してはいけません。 公開ホスト上の http(s) URL は
siteで、ワークスペースは~/.video-demo/<host>/です。localhost またはプライベートアドレス上の URL は開発サーバーです。その背後にあるリポジトリを見つけ、リポジトリへの依頼として扱います。URL がなければ、現在いるリポジトリが対象です。上位ディレクトリをたどって、Vite、React Router、Next、Astro、SvelteKit、Remix の設定ファイルと同じ場所にビルドスクリプトを含むpackage.jsonがあるウェブアプリを探します。1つだけならbuild、複数ならどれかを尋ね、1つもなければ URL またはパスを尋ねます。.originにすでにこのリポジトリが記されているワークスペースは再利用し、再度スキャフォールドしてはいけません。モードとワークスペースのパスを1行で伝えて、作業を続けます。 scripts/doctor.shを実行し、それから、ほかのことをユーザーに尋ねる前に環境を整えます。 ユーザーはスキルをインストールしたのであって、3つのスクリプトを自分で実行することに同意したわけではありません。不足しているものを1行で伝え、インストールするものとおおよそのサイズを説明し、同意を得てから実行します。scripts/install.shはエンジンと Chromium(約250MB)を対象とし、パッケージマネージャーが使える場合は ffmpeg もインストールします。scripts/install-voice.shは音声(約350MB)用です。音声なしで撮影するという選択も問題ありません。許可なくインストールしてはいけません。また、doctor のレポートを渡してユーザーに解釈させてはいけません。スクリプトでは実行しないことが2つあり、それは妥当な判断です。Node をアップグレードしないでください。どのツールで管理しているかを知っているのはユーザーだからです。また、sudoも実行しないでください。誰も見ていないスクリプトでパスワード入力を求められると、処理が止まってしまいます。いずれの場合も、スクリプトがコマンドを1つ表示するので、それをユーザーに伝えます。- 何も書き込まずに調査します。
siteの場合:URL を開いて読み、ページの目的、紹介する価値のある3つの要素、安定して指し示せる箇所を確認します。サインイン画面が表示されたら、そこで止めます。サインインが必要なアプリはリポジトリから撮影するため、そのリポジトリか公開 URL を依頼します。buildの場合:package.jsonからそのまま転記したビルドコマンド、フレームワークの設定ファイルに記載された出力ディレクトリ、.env*にある絶対 API ホスト(build.forbidに指定します)、テーマ起動スクリプトが読み込むキー、既存の fixture API または MSW ハンドラー、data-testidの密度、認証情報なしでアクセスできるルートを確認します。 scripts/scaffold.mjs <appRoot>またはscripts/scaffold.mjs --site <url>を実行します。どちらもアプリ内には何も書き込みません。- ワークスペースの
demo.config.tsを設定します。 必須項目に未確認のものが残っている場合、調査は完了していません。設定ファイル buildの場合のみ:mock.tsとseed/を作成します。 リポジトリに独自のデータ fixture があれば再利用します。ただし、@playwright/testをインポートするファイルは使ってはいけません。1回の実行で2つ読み込むと Playwright がエラーとして拒否し、該当のシーンだけでなくコーパス全体が失敗するからです。次にDEMO_VOICE=0 scripts/demo --grep smokeを実行します。fixture API がある場合は再利用します(モック)。静止画を確認します。サインイン済みで、データがシードされ、正しいテーマが適用され、ログインページが表示されていないことを確認します。キャプチャ行も確認します。両方が正しくなるまで修正し、その後、スモークテストの実行で確認できた内容だけをdemo/ui.tsに記述します。- 依頼された範囲で、依頼された内容を撮影します。 名前が指定された機能は1つのシーンです。そのシーンを書き、撮影して、渡します。「ホームページで検索を記録して」という依頼に対して10シーンの案を提示してはいけません。また、製品にほかの機能があるからといって、依頼の範囲をひそかに広げてはいけません。製品全体の依頼である場合に限り、6〜10個のシーンを提案します。各シーンにタイトルと1行の説明を付け、ツアーの順に並べて、どれから撮影するかを尋ねます。
- 停止します。 その1シーンを音声付きで撮影します。音声の数が
sayの呼び出し数と一致していること、時間超過がないこと、速度が一定に保たれていることを確認します。すべての静止画を確認します。mp4 のパスをユーザーに伝え、文章の文体、ズームの倍率、ペース、音声について尋ねます。返答があるまで、ほかには何も書きません。 - その後、
--grepを使って3〜4件ずつ処理します。マニフェストはマージされます。各バッチの後に静止画を確認します。シーンを調整するときはDEMO_BUILD=0 scripts/demoを指定すると、再ビルドを省略できます。4分ではなく20秒で済みます。コーパスを作成する実行では、この指定を外します。 DEMO_TRACE_FRAMES=1を指定して全体を実行し、続けてscripts/gaps.mjsを実行してdemo-out/index.htmlを開きます。キャプチャ表と、時間のかかったクリップを報告します。
あるシーン
scene('tasks', { title: 'Your to-dos, beside your calendar', blurb: '...' },
async ({ actor, page, shot }) => {
await actor.click(page.getByRole('radio', { name: 'Today' }));
await actor.settle();
await actor.spotlight(
row('Send Sam the feedback'),
'And this one is from yesterday that I never got to, so it is flagged.',
{ scale: 1.8, stay: true }
);
await shot('overdue');
await actor.unfocus();
});
spotlight はナレーションマークを受け取り、その行の冒頭の語句にカメラとカーソルを移動します。対象に応じて拡大率を調整します。パネルは約1.4、行は約1.7、単一のコントロールは約2です。画面全体についての行には通常の say を使い、ズームはしません。unfocus は移動ではなくヒントです。カメラが引くのは、広い範囲が必要なときだけなので、同じ領域について続くビートは跳ねることなく滑らかにつながります。
scenes.md · narration.md
決してしないこと
字幕(音声が伝達手段です)。クラウド TTS(映像には非公開データが映るためです)。Playwright の recordVideo(速度、サイズ、開始位置を制御できず、レコーダーが置き換えるためです)。デフォルトでの4K。音楽、イントロカード、クロスフェード。ルートのクロールからシーンを生成すること。シーンとは、意図を持った振り付けです。リトライ。シーンを再試行すると、別の映像になります。
併せて読むもの
キャプチャに関する数値を変更する前に、capture.md を確認してください。
ビルド、分離、マニフェストについては、runs.md を確認してください。
実行が停止したときや、ショットがおかしく見えるときは、troubleshooting.md を確認してください。エンジンはこのスキルから実行されるため、engine/ の修正はマシン上のすべてのプロジェクトに一度に反映されます。そこで編集すれば、ほかに反映する作業は必要ありません。