Communitygithub.com

delacournz/demo-video

実際のシミュレーターで駆動する製品デモビデオ(warden またはサンプルアプリ)を作成します。端末の横にタイピング端末を表示。ドキュメントやX用のデモ動画、機能クリップ、UI変更後の再録画、`*.demo.ts` 定義の追加・編集に使用します。

demo-video とは?

このスキルは、実際のiOSシミュレーター上で動作する製品デモビデオを生成するためのツールチェーンです。`bun run demo` コマンドを使用して、シミュレーターの録画と同時に、実行中のwardenコマンドを入力する端末画面を合成した1920x1080のビデオを作成します。録画からコンタクトシート作成、レンダリングまでのループを自動化し、フレームの偽造や未実行コマンドの表示を禁止する正直ルールを厳守します。Xへのエクスポート仕様やドキュメントへの埋め込みもサポートしており、UI変更後の再録画は常にmp4を新規作成し、編集は行いません。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/delacournz/warden/tree/HEAD/.claude/skills/demo-video

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

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

ドキュメント

demo-video は何をしますか?

bun run demo <feature>/<clip> は、リースしたiOSシミュレーターでテイクを録画し、1920x1080のビデオをレンダリングします。タイトルは左、各 warden コマンドを実際に入力しステップ終了時に出力を表示する端末は中央、電話画面は右(角丸、3pxのリング)に配置されます。キット: scripts/demo/(demo.ts CLI、record.ts、render.py、timeline.ts、demo.types.ts)。定義ファイル: apps/example/demos/<feature>/<clip>.demo.ts(name は <feature>/<clip> と一致する必要があります)。アセット: apps/docs/public/demos/<feature>/<clip>.mp4|jpg。フィーチャーごとに1フォルダ(biometrics、network、location、clock)、小文字、ハイフン区切り。内部用: changeset不要。

1. 作成するタイミング

  • 画面上で効果が視覚的に確認でき、数秒で完了する機能(biometrics、アラート、ジェスチャー)。ログ、パフォーマンス数値、表で表示した方が良いものには利用しません。
  • アプリUIやコマンドの動作が変更された後: mp4を編集せず、必ず再録画します。
  • クリップあたり1つのストーリー、10〜25秒、3〜6のキャプション付きステップ。

ffmpeg、ffprobe、uv(brew install ffmpeg uv)、Xcode、および node_modules/@expo-google-fonts のフォント(bun install)が必要です。

2. 定義を書く

demo: DemoDefinition(scripts/demo/demo.types.ts)をエクスポートします。apps/example/demos/biometrics/faceid.demo.ts をコピーしてください。

フィールド意味
title / subtitle / terminalTitle / footer静的テキスト;titleは主張、subtitleは1行
phoneCaption電話画面の下の行、デフォルトは real simulator · not an animation;"" で非表示
claim{ biometrics?, profile? } -> warden claim ios --json --label demo-<feature>-<clip> --ttl 30m [--biometrics]
appbundleId、kind(デフォルトは simulator)、project(リポジトリ相対のcwd)、deepLink(--settle 付きで開く)、appearance(light/dark、リースされたudidに simctl ui で設定し、後に復元)
setupアプリ起動後、ディープリンク前にカメラオフで実行される warden のargv;["ui","network","set","online","--relaunch"] はiOS dylib起動ネットワーク/クロックステップに必要なもの。エントリはargvまたは { argv, optional: true }:オプションのステップが非ゼロで終了してもログに記録されるだけで(optional setup warden … -> <code>)、テイクは失敗しません(表示されない可能性のある許可プロンプト)
readyディープリンク後、ビデオ開始前に通過しなければならない warden ui wait セレクター(例: id=bio-screen);マウントされていない画面をステップが押すことはありません
leadInMs / tailHoldMsステップ1前のアイドル時間 / 最終フレームの保持時間、レンダラーによってパディングされます(テイクの末尾は1秒)
steps[]argv(warden の後;レコーダーが --udid を追加)、output(ok はベクターチェックを描画、plain はミュート、lines は複数のミュート行を表示)、pauseAfterMs、shown?、hidden?、quote?
outro最後の出力後にタイプされる # comment 行

output: { kind: "lines", text: [...] } は、ファイルから表示するコードやテキストのために、エントリごとに1行のミュート行を表示します(約6行までに抑えてください;最初の1行を超えるごとにレイアウトのエントリピッチの0.4を消費します)。quote: { file }(app.project からの相対パス)とペアにします:ステップ後、レコーダーは印刷された各行(トリム済み)がそのファイルに存在することを確認し、存在しない場合は quoted line not in <file>: <line> で例外をスローするため、引用行が捏造されることはありません。行は依然として maskSecrets を通過します。

時間は手動で記述しません:レコーダーが各ステップの開始と終了をビデオクロックに対して計測し、出力行はステップの終了時に表示されます。

3. ループ

bun run demo <feature>/<clip> --record-only      # クレーム、9:41のステータスバー、起動、録画、IDで解放
bun run demo <feature>/<clip> --render-only --sheet   # mp4 + jpgをビルド、<work>/sheet.jpg を書き込み
bun run demo <feature>/<clip>          # 両方

作業ディレクトリ: $TMPDIR/warden-demo/<feature>/<clip>(--out dir):take.mp4、steps.json、plan.json、sheet.jpg;テイク失敗時は failure-snapshot.txt(エラー + ui snapshot -i)。ここにあるものはコミットしません。

  1. 録画。
  2. sheet.jpg(4x4タイル、1秒あたり1枚、ptsが焼き付けられている)を読み取ります。ログと照合:各出力行は、電話画面が視覚的に反応するタイミングで配置されています;無関係なアラート、キーボード、赤枠、間違ったステータスバーを表示するフレームはありません;最終フレームは終了状態を示しています。
  3. より詳細に確認するには:ffmpeg -ss 7 -i take.mp4 -frames:v 1 f.png でフレームを抽出し、Read します。
  4. 定義で修正し(pauseAfterMs、ステップの削除/非表示、shown)、--render-only を実行;テイク自体が間違っていた場合のみ再録画します。バッチ修正:ラウンドごとに1回の録画。
  5. apps/docs/public/demos/<feature>/ に mp4 + jpg をコミットします。

4. 正直ルール

  • 表示されるすべてのコマンドは、実際のアプリに対して実行されました。argv と意味が異なる shown はありません(フラグ(--timeout など)のみをトリミングします)。
  • 出力テキストは、電話画面が実行した内容であり、コマンドが出力した内容ではありません。プレス操作に視覚的な効果がない場合(シートの開始アニメーション中にドロップされた、何も変更されなかった)、キャプションを付けないでください:hidden: true、または前の pauseAfterMs を長くしてタイミングを修正します。
  • 初回実行時の許可アラートは、クリーンインストール時にのみ表示されます;クレームはウォームビルドを再利用するため、テイクでアラートが表示されない限り、キャプションを付けないでください。
  • アプリ側のバイパスやモックプロンプトは禁止:タイトル内のクレームはテイク上で真実でなければなりません。
  • シークレット:maskSecrets は key=value、ghp_/sk- スタイルのトークン、および長いhex/base64を印刷行で隠します。それでも電話画面でトークン、メール、デバイス名がないか確認してください。
  • 実際のシミュレーター、実際のiOS UI。決して偽のフレームを合成しないでください。

5. 注意点(キットにエンコード済み)

  • simctl video はVFRで、アイドルテイルをドロップします:レンダラーは fps で正規化し、最後のフレームを計画長にパディングします(tpad)。
  • ビデオ時間はコマンドログと約0.5秒以内で一致します;レコーダーは video start の直後にクロックを開始します。
  • Martian Mono にはチェックグリフがありません:render.py がベクターとして描画します。
  • フレームはドキュメントの Device Hub ダークパレット(Mona Sans + Martian Mono)です;app.appearance: "dark" を設定して電話画面を合わせます。レコーダーは後にシミュレーターの外観を復元します。
  • 端末オーバーフロー:computeTerminalLayout はピッチとフォントを17pxに縮小し、最も古いエントリをスクロールアウトします。
  • デバイスビデオ制限3分;それでもテイクは40秒未満に抑えてください。
  • ステータスバー:リースされたudidでは xcrun simctl status_bar <udid> override が許可されています;レコーダーは後にそれをクリアします。

6. X エクスポート

1920x1080、H.264 High、yuv420p、30 fps、+faststart、音声なし、2分20秒以下、小さなファイル(キットはCRFラダー24..36で2 MB以下を目標)。確認:

ffprobe -v error -show_entries stream=codec_name,profile,width,height,r_frame_rate -show_entries format=duration,size apps/docs/public/demos/<feature>/<clip>.mp4

7. アセットとドキュメントへの埋め込み

出力:apps/docs/public/demos/<feature>/<clip>.mp4 + <clip>.jpg(ポスター = 最終フレーム)、/demos/<feature>/<clip>.mp4(Vite public/)で提供。DemoClip MDXコンポーネント(apps/docs/src/components/demo-clip.tsx)で埋め込み:自動再生、ミュート、ループ、モーション軽減設定時はポスターで静止。src に拡張子はありません;label はクリップの内容を示します(キャプションと一致)。生の <video> は apps/docs/src/lib/source.test.ts に失敗します。

<DemoClip src="/demos/<feature>/<clip>" label="warden ui … がリースされたシミュレーターで … を実行中" />

コマンドを記載したキャプション文を追加します。バッチリール apps/docs/public/demos/e2e/batch.*(<DemoReel> で埋め込み)は別のパイプラインです(bun run demo:compose)。

8. warden dev リール(dev/hero)

3番目のパイプライン:wardenの実際の開発ダッシュボード(左、端末カード内)がシミュレーター(右)の横に表示されます。warden dev はそれ自身をクレームします。タイピングや偽装は一切ありません:dev-take.ts は PTY(Bun.spawn({ terminal }))で warden dev ios --label demo-dev-<clip> --headless --no-shutdown を生成し、@xterm/headless にミラーリング(フレーム読み取りで待機)、すべてのPTYチャンクを tui.cast に書き込みます;クロックの原点は生成時です。warden ls --json でラベル付きデバイスリースをポーリングし、ダーク + 9:41 を設定、アプリをアンインストールして ui screen video を開始します(それまでは電話画面は黒です)。開発子プロセスは独自の WARDEN_SESSION_ID を取得します:warden dev は呼び出し元のセッションが保持するデバイスリースを採用し、すべてのチームメイトエージェントがそれを共有するため、これがないとテイクが他の人のシミュレーターを操作する可能性があります。

bun run demo:dev dev/hero --record-only        # クレーム、アプリをアンインストール、9:41 + ダーク、録画、IDで解放
bun run demo:dev dev/hero --render-only --sheet # agg + ffmpeg -> apps/docs/public/demos/dev/hero.{mp4,webm,jpg}、<work>/sheet.jpg
bun run demo:dev dev/hero                      # 両方
  • キット:dev-demo.ts(CLI)、dev-take.ts(レコーダー、runBeats)、dev-render.ts(agg + 合成、DEV_LAYOUT)、dev-frame.py(カード、リング、マスク)、dev-timeline.ts(キャストテキスト、ランプセグメント、キャプション)。型:DevDemoDefinition / DevBeat in demo.types.ts。定義:apps/example/demos/dev/<clip>.demo.ts;作業ディレクトリ $TMPDIR/warden-demo/dev/<clip>(take.mp4、tui.cast、dev.json、sheet.jpg、failure-frame.txt)。
  • ビート = waitScreen(TUIフレームの正規表現)+ waitPhone(ui wait セレクター)-> アクション(TUIへの keys、および/またはリポジトリファイルの実際の edit)-> afterPhone セレクター(ホットリロード着地)-> pauseAfterMs。dev.json はビデオクロック上の各ビートの開始/準備/終了を保持し、キャプションはビートのアクションから次のビートのアクションまで実行されます。
  • 編集は実際のソース編集です(welcome.tsx 本文文字列)、finally でバイト単位で元に戻されます;テイク後に git diff apps/example/src が空であることを確認します。
  • uninstallFirst はリースされたシミュレーターからアプリを削除し、warden dev がキャッシュから開発ビルドをカメラ上にインストールするようにします。指紋認証の最初のテイクはローカルビルド(数分、dev build 行がコンパイル)です:キャッシュをウォームアップするために1回録画し、その後再録画します。warden app ensure --kind dev は warden dev が読み取るキャッシュをウォームアップしません。
  • スピードランプ:DevBeat.ramp: N はそのビートの待機をN倍に高速化し(先頭1.2秒と末尾1秒は実速度を維持)、リールは × N speed タグを描画します。開発クライアントの待機が遅いウォームテイクはそれをランプします。キー操作とホットリロードは常にリアルタイムです。
  • 正直さ:<DemoReel> キャプション内の事実は、テイクのTUI行(dev build 3.5s、Metro 3.9s、dev client 161ms)および dev.json(編集 -> ui wait が新しいテキストを確認:0.76秒)から取得されます。再録画のたびに再読み取りしてください;変更される可能性があります。
  • 制限:ダッシュボードには個別のクレーム行はありません(preparing the ios dev build 内にあります);--headless によりDevice Hubウィンドウは開きません;100x26 PTY(100列はHUDの最小値)。stopVideoFirst を持つビートは、アクションの前にビデオを停止します(q でリースが終了し、warden ui はその後拒否します)。q の後、テイクは warden ls がセッションのリースを保持していないことを確認します(それ以外の場合は失敗)、キャストはダッシュボードがalt画面を離れる場所でカットされるため、リールは最後のフレームで終了します。Dev Launcherの白いローディング画面と青い Refreshing… バナーは実際のアプリです;Metroのリロードは別のエージェントが apps/example/src を編集したことによる場合もあります。
  • ランプ:ramp は、待機時間から先頭1.2秒と末尾1秒を差し引いた残りが少なくとも6秒(RAMP_MIN_S)の場合にのみ適用されます。ヒーローは開発クライアントの待機を3倍(タグ付き)でランプします。
  • devEnv は warden dev 子プロセスに環境変数を追加します;ヒーローは EXPO_NO_DEPENDENCY_VALIDATION=1(@expo/cli checkDependenciesOnStart)を設定して、MetroペインからExpoの「利用可能なアップデート」警告を削除します。ノイズ対策にのみ使用し、動作には決して使用しないでください。
  • <DemoReel src="/demos/dev/hero" command="warden dev ios" facts="…" label="…" /> で埋め込みます(ランディングヒーロー、sims/dev.mdx、getting-started/quickstart.mdx)。ポスター = posterBeat アクションフレーム + 1秒(HUD表示、すべての行完了、アプリ実行中)。

9. 端末中心のクリップ(VID-6)

すべて実際のコマンド;各リールは実行されたものだけを表示します。一度に1クリップ、ラベルで解放。

クリップパイプラインコマンド
e2e/parallelbatch-take.ts:warden e2e <suite> --count N --record --headless -> <work>/rec、各リースされたシミュレーターを起動時にダーク + 9:41 にスタイリング、その後 compose.ts --height 1080bun run demo:batch e2e/parallel --suite example --specs devtools,gestures,onboarding,sign-in,todo-detail --count 2(--record-only / --compose-only;ヘッダーは仕様数を表示;カウンターは N/total shards done を読み取る、仕様がジョブと異なる場合)
dev/worktreesLanesDemoDefinition:recordDev 1つをレーンごとに並行、下にシェルストリップ(warden ls)bun run demo:lanes dev/worktrees(lanes.ts、lanes-frame.py、lanes-demo.ts;レーンは DevTake.startedAtS を介して1つのクロックを共有)
golden/cloneDevDemoDefinition.script:シェルスクリプトが warden dev の代わりにPTYで実行bun run demo:dev golden/clone
debug/failurescript + rawVideobun run demo:dev debug/failure --sheet
  • scriptモード:アンインストールなし、解放チェックなし;テイクは release --mine --label L --shutdown と sims delete <udid> --yes で終了します。waitBoot を持つビートは simctl io screenshot をポーリングし、PNGが100 KB(HOME_SCREEN_MIN_BYTES)を超えるまで待機します:新しくクローンされたヘッドレスシミュレーターは claim が戻った後も10秒以上Appleロゴを表示します。その待機をランプします(3倍、タグ付き)。
  • rawVideo:simctl io recordVideo(SIGINTで停止)で録画します。これは、wardenの ui screen video ヘルパーが warden e2e と1つのデバイスで競合するためです。
  • --record は開始時に存在するデバイスのみを録画します;後から参加するものにはビデオがありません。ホスト容量ゲートが収容可能数を設定するため、開始時に起動されているシミュレーター以上を要求しないでください(ここでは最大2)。
  • debug/failure の使い捨て仕様は apps/example/e2e/debug-demo.e2e.ts に書き込まれ、シェルトラップによって削除されます;その後 git status を確認してください(強制終了されたテイクが残す可能性があります)。
  • <DemoReel src="/demos/<feature>/<clip>" command="…" facts="…" label="…" /> で埋め込みます;事実はテイクから取得され、再録画のたびに再読み取りされます。
  • demo:batch はポーラー(styleWhenBooted:warden ls --json でラベルを検索、simctl list でBootedを検索、その後 ui appearance dark + status_bar override 9:41)を使用してシミュレーターをスタイリングします。これは warden e2e にデバイスごとのフックがないためです;finally で --mine --label demo-<feature>-<clip> --shutdown を解放します。クリーンなシミュレーターで合格する仕様を使用してください(perf、settings、todos は確実に合格しません);compose --height 1080 フラグは16:9のレイアウトを提供します(端末)

…

[翻訳のため一部省略]

関連スキル