Product Demo Video
SaaSのローンチビデオのように見える製品デモ。スクリーンキャストではありません。
中心となるアイデア:画面を録画しない。Playwrightで高解像度のスクリーンショットと要素の実際の座標をキャプチャし、その後Remotionでその素材をアニメーション化します。これにより、カメラ、リズム、キャプションを完全に制御でき、ユーザーが「もっと速く」、「ズームを大きく」、「このステップを削除」、「10秒バージョンを作って」と言った場合に10秒で再レンダリングできます。再収録は遅く、結果も劣ります。
フロー
- セットアップ (プロジェクトごとに1回)→
node <skill>/scripts/setup.mjs - ロードマップ→
demo.jsonを記述します (references/roteiro.mdを参照) - キャプチャ→
node .demo-video/tools/capture.mjs demo.json capture/(Playwright) - レンダリング→
node .demo-video/tools/render.mjs --capture capture/ --out out/(Remotion) - 納品→
out/<name>.mp4(1080p) +out/<name>.gif(HTMLに埋め込み可能) - 反復→
demo.jsonを編集し、変更したステップだけを実行します
時間/カメラ/キャプションを変更しましたか? レンダリングのみ再実行 (ステップ3、約30秒)。 アプリのフローが変わりましたか? キャプチャも再実行 (ステップ2)。
日本語の依頼からロードマップへ
ユーザーが自然言語でフローを説明します (「エージェントの作成方法を示して」)。それをセレクターに変換するのはあなたの役目であり、アプリを実際に見て行います — 決して推測してはいけません。#submit を推測すると、キャプチャ全体が失敗し、シーン4で停止します。
- ブラウザツールで画面を開き、DOMを読み取ります。
- セレクターを収集します。優先順位は堅牢性の高い順に:
[data-testid=...]>#id> 表示テキスト (text=新しいエージェント) > CSSパス。CSSパスはレイアウトが変わると最初に壊れます。テキストはインターフェースが翻訳されると壊れます。 - キャプチャする前に、ユーザーとフローを確認します — ロードマップを見せて、ステップの順序がこれで合っているか尋ねます。ユーザーは製品を知っています。あなたは知りません。
- アプリにログインが必要な場合は、最初に
auth.mjsを実行するようユーザーに依頼します。
アプリを開くことができない場合 (内部プロダクト、アクセス権限がない場合) は、セレクターまたはHTML付きの画面のプリントを依頼します — 推測するよりも速いです。
ロードマップが唯一の真実の源泉
単一のJSONがPlaywrightとRemotionの両方を制御します。何かをキャプチャする前に、ロードマップを記述してユーザーに提示します — ここで修正するのは安価ですが、後で修正するのは高価です。完全なスキーマは references/roteiro.md にあります。
{
"name": "criar-agente",
"url": "https://app.exemplo.com",
"viewport": { "width": 1600, "height": 900 },
"scenes": [
{ "action": "goto", "value": "/dashboard", "camera": "wide", "caption": "ダッシュボード", "duration": 2 },
{ "action": "click", "target": "[data-testid='new-agent']", "camera": "zoom", "caption": "エージェントを作成", "duration": 2 },
{ "action": "type", "target": "#agent-name", "value": "財務アナリスト", "camera": "focus", "duration": 2.5 },
{ "action": "click", "target": "button[type=submit]", "camera": "zoom", "duration": 1.5 },
{ "action": "wait", "value": 1200, "camera": "wide", "caption": "3クリックで完了", "duration": 2.5 }
]
}
セットアップ (プロジェクト初回)
node "$HOME/.claude/skills/product-demo-video/scripts/setup.mjs"
.demo-video/ (Remotionコンポジション + .demo-video/tools/ のツール) を作成し、依存関係をインストールし、Chromiumをダウンロードします — 約300MB。実行前にユーザーの確認を得てください。その後、キャプチャとレンダリングは数秒で完了します。.demo-video/、capture/、.auth/ を .gitignore に追加することを提案します。
結果をライブで調整するには、cd .demo-video && npx remotion studio でスクラバー付きプレビューを開きます — タイミングを確認するためにレンダリングするよりもはるかに優れています。
カメラワーク
良いデモと悪いデモを分けるのは、エフェクトではなくリズムです。有効なルール:
wideで開いて閉じる。 視聴者はズームの前に状況を把握し、結果を確認する必要があります。映画全体がズームだと疲れ、方向感覚を失います。- 意図ごとに1つのズーム、クリックごとではない。 同じ領域での連続クリック =
zoomの1シーンのみ。クリックごとにズームイン/ズームアウトすると吐き気を催します。 focusは入力時のみ。 テキストフィールドは判読可能である必要があります。ボタンは不要です。- シーンあたり2〜3秒。 1.5秒未満だと誰もキャプションを読めません。4秒を超えるとデッドタイムになります。良いデモは15〜25秒で5〜8シーンです。
- キャプションはラベルであり、文章ではない。 「エージェントを作成」、「データを接続」。最大で約4語、動詞で始め、文末のピリオドは不要。すべてのシーンに必要ではありません。
- デッドタイムは元からカットする。 ローディング、リダイレクト、エントリーアニメーション: シーンで
settleを使用し、ビデオに静止秒数を残さない。
カメラはシーン間で連続 (イージングで補間) されているため、動きは自動的にスムーズになります — ロードマップで余分なシーンを使って補おうとしないでください。
テキストレイヤーがナレーション
オーディオはありません (GIFにはなく、動画はフィードではミュートで再生されます)。ストーリーを伝えるのはタイポグラフィであり、それは階層がある場合にのみ機能します。すべてのテキストの重みが同じ場合、視聴者は何がステップで何が引数かを理解できません。
| スタイル | 役割 | 使用時 |
|---|---|---|
title (シーン) | フル画面の開始/終了。sub を伴う | 最初に1回、場合によっては最後に1回 |
hero | 転換点 — 大きく、中央揃え、グラデーション上に配置 | デモあたり最大1回 |
label | ステップのラベル (デフォルト)。オプションでsubを伴う | ほとんどのシーンで |
stat | 製品を正当化する数字: 「22秒」、「3クリック」 | クロージングで1回 |
note | 二次的な詳細、控えめ | ステップに但し書きが必要な場合 |
残りを支える2つのルール: デモあたり1つのhero (2つあるとどちらも効果がなくなる)、および**statで締める** — 大きな数字は視聴者の頭に最後に残るものです。エグゼクティブデモの場合、典型的なアークは title → label群 → 決定的瞬間の hero → 最後の stat です。
"highlight": true は、シーンの要素以外の画面全体を暗くします。これは最も強力な武器であり、したがって最も台無しにしやすいものです。装飾としてではなく、視聴者がその要素を確実に記憶に留める必要がある場合に使用します。カメラが落ち着いた後に現れ、アクションの瞬間に自動的に消え、結果を隠しません。
認証情報
決して demo.json にパスワードを入れないでください。優先順位に従って2つのオプション:
"auth": { "storageState": ".auth/state.json" }— すでにログイン済みのセッション。node .demo-video/tools/auth.mjs <url>で1回生成 (ブラウザが開き、ユーザーが手動でログイン)。"auth": { "login": { "user": "#email", "pass": "#password", "submit": "button[type=submit]" } }。認証情報は環境変数DEMO_USER/DEMO_PASSに格納。
デモが実際のデータを表示する場合は、ロードマップで "redact": ["selector"] を使用して、キャプチャ前に機密要素をぼかします — PNGですでにぼかされて出力され、復元は不可能です。
出力
| フォーマット | 用途 | 方法 |
|---|---|---|
demo.mp4 1920×1080 | ランディングページ、LinkedIn、YouTube | デフォルト |
demo.gif 960×540 | README、ドキュメント、メール、HTML | --formats mp4,gif (デフォルト) |
demo-square.mp4 1080×1080 | Instagram/フィード | --formats mp4,square |
GIFは重いです。render.mjs はすでにffmpeg (Remotionに内蔵) を介してpalettegen (ビデオ専用パレット) を使用しています — 何もインストールする必要はありません。それでも、960pxで15秒だと約3.5MBになります。READMEの場合は --gif-width 720 --gif-fps 12 を推奨します。これで1.5MB未満に抑えられます。
HTMLに埋め込む場合: <img src="demo.gif" width="720" alt="...">。ユーザーがMP4を許容する場合、<video autoplay loop muted playsinline> は約10分の1の軽さです。
製品に触れずにインストールをテスト
assets/exemplo/ には、ダミーアプリ (app-exemplo.html) とそれに対応するロードマップが含まれており、すべてのアクション (title、shot、click、type、select、hold、redact) を練習できます。これを最初に実行することで、「スキルが壊れている」のか「アプリのセレクターが間違っている」のかを区別でき、最初の実際のデモで何かが失敗した場合の高価な疑問を防げます。
問題が発生した場合
- セレクターが見つからない →
capture.mjsがシーンで失敗し、どのセレクターかを示します。ユーザーにURL/画面を尋ね、別のセレクターを推測する前にブラウザで検査します。 - ズームがぼやける → ロードマップで
scaleを3に増やすか (スクリーンショットを3倍に)、ズームを減らします。 - ビデオがキャプションと同期しない → シーンの
durationが優先されます。そこで調整します。 - 構成、カメラ、カーソル、視覚的なカスタマイズの詳細:
references/remotion.md。
