Velxio プロモ動画パイプライン
3つのフェーズで構成され、すべてこのリポジトリ(velxio_docs;開発環境では /home/dave/velxio_docs)内で実行します:
- 録画 —
scripts/promo-record.mjsが実際の製品をステージング環境でエンドツーエンドで操作します(空のプロジェクト → ESP32の選択 → 220R + LEDの追加 → 抵抗の回転 → ピンクリックで配線 → スケッチの記述 → Run → LED点滅)。注入された可視カーソルとクリックリップルが含まれます。各ビートは{t, x, y, label}をscripts/promo-events.jsonに記録し、生の動画はscripts/promo-raw.webmに出力されます。 - ビートグリッド —
scripts/detect-beats.py(librosa)がサウンドトラックを解析し、promo/src/beats.json(BPM、ビート、キック、スネア)を生成します。 - ポストプロダクション —
promo/はRemotionプロジェクトです。prepare.mjsが録画をコピーし、モーダル前の起動部分をトリミングし、コンパイル待機時間を除去してsrc/data.jsonを出力します。src/Promo.tsxがカメラをレンダリングします(各ビートを中心にズームイン、各パンチは0.34秒以内の最も近い音楽ビートにスナップ)、キャプションピル、無地のイントロカード、velxio.devのアウトロ、フェードイン/アウト付きの音楽トラック。
コマンド
cd /home/dave/velxio_docs
VELXIO_SHOTS_EMAIL='[email protected]' VELXIO_SHOTS_PASSWORD='<see memory vstaging-test-user>' \
node scripts/promo-record.mjs # 録画(コンパイル含め約2〜4分)
python3 scripts/detect-beats.py promo/public/soundtrack.mp3 --fps 30 \
--out promo/src/beats.json # トラックを変更したときのみ実行
cd promo && node prepare.mjs
CHROME=$(ls -d $HOME/.cache/ms-playwright/chromium-*/chrome-linux*/chrome | sort | tail -1)
npx remotion render src/index.ts promo out/velxio-demo.mp4 --codec h264 --browser-executable "$CHROME"
GitHubで表示するための公開コピー:media/velxio-demo.mp4(コミット済み;上書き+プッシュで同じURLを更新)。promo/out/ はgitignoreされています。
レビュー手順(省略しないでください)
promo/src/data.json のビート時刻(ctフィールド)でのサンプルフレームを確認します。推測した時刻ではなく、ビートはテイク間で移動します:
ffmpeg -y -ss <ct> -i out/velxio-demo.mp4 -vframes 1 /tmp/beat.png
確認項目:イントロが読みやすい、各ズームで対象が切り取られずに表示されている、キャプションが画面上の内容と一致している、カーソルが重要な部分を覆っていない、最終的なLEDが点灯している。
ギャラリーデモ動画(基本モード)
ギャラリーの各サンプルにつき1本の短い動画 — 開いて、実行して、動作を撮影 — 分割イントロカード(左側にロゴ+タイトル+ボード、右側に回路全体)、下部3分の1、アウトロ、サウンドトラックを含みます。
node scripts/gallery-scan.mjs # 406サンプルのインデックスを更新
node scripts/gallery-record.mjs [slug ...] # 1080p録画(完了済みはスキップ)
node scripts/gallery-bbox.mjs [slug ...] # 回路の位置を計測
node scripts/gallery-render.mjs [slug ...] # テイクごとに1つのmp4をレンダリング
- キュレーションされたデモセットは
gallery-record.mjsの先頭にあるGALLERYにあります;スラッグはscripts/gallery-index.jsonから取得します(サムネイルファイル名 = スラッグ)。 - 静止画は
deviceScaleFactor: 2でキャプチャされ、回路のバウンディングボックスにクロップされます:1080pフレームの半分を埋めるのに十分なシャープさ。小さな回路を拡大するためにアプリをズームしないでください — キャンバスのズームはその中心に固定され、回路が画面外にずれます;代わりにビューをリセットしてください。 - バウンディングボックスパスはサンプルごとに新しいコンテキストが必要です:エディタを2回クライアントサイドで読み込むとキャンバスが空になり、何も測定できません。
- ボードのないサンプル(Digital / Analogカテゴリ)はコンパイルされません:Runは無効のままで、SPICEエンジンが最初から駆動します。
- バックエンドQEMUボード(STM32、Raspberry Pi)は「in-browser」コンソール行を出力しません。STM32はさらにステージングではまったく動作しません(libqemu-armはオプションアセットであり、そこにはデプロイされていません)— コンパイルは3秒で完了しますが、起動しません。
- 生の録画(
promo/public/gallery/*.webm、各約3MB)はgitignoreされています;回路の静止画とテイクごとのJSONはコミットされているため、再レンダリングには録画のみが必要です。
音楽
promo/public/soundtrack.mp3 = Mixkit「House Vibez」by Lily J
(assets.mixkit.co/music/745/745.mp3)、Mixkit Stock Music Free License — 商用利用無料、クレジット不要。123 BPM。ファイルを交換して detect-beats.py を再実行するとトラックを変更できます;promo/public/ATTRIBUTION.md のライセンス表記を最新に保ってください。
トラックは約8秒のイントロで始まります:Promo.tsx の AUDIO_START は最初に検出されたビートであるため、オーディオはそこから開始され、コンポジションt=0はダウンビートに着地します。音量は0.55で、0.9秒のフェードインと2.2秒のフェードアウトがアウトロにかかります。
スタイルルール(Davidのレビューから — 守ってください)
- 動画はエディタで、ボードテンプレートモーダルがすでに開き、AIチャットがすでに最小化された状態から始まります。ホームページ、読み込み、表示される最小化クリックはありません(レコーダーはプログラム的に開始前に行います;prepare.mjsは
startマークまでトリミングします)。 - イントロタイトルは無地のダークカード上 — UIの上に半透明にしないでください。
- ズームは対象を中央に配置する必要があります:エッジクランプ付きのtranslate+scale(
Promo.tsx)、transformOrigin-at-pointは使用しないでください(対象が境界に置かれ、切り取られるため、例:ESP32カード)。 - パーツ追加のビートは短いホールド(約0.5秒)を使用し、ズームがパーツの着地場所を確認できるように十分早く解除します。
- コードのビートはエディタペイン全体を中央に配置します(fx/fyオーバーライド357,280)— コードが記述されている間にエディタが切り取られないようにします。
- Runをクリックした後、カーソルを遠ざけます(レコーダーは700,620に移動)ので、ボタンのスピナーが見えるようになります;Runビートはコンパイル/実行クラスターを中程度の倍率(1.8)でズームします。
- 抵抗器を配置後に水平に回転します(垂直のデフォルトはカメラ上で自身のワイヤーと重なります)。
- ポインタはmacOSスタイルの矢印であり、ドットではありません。ホットスポットの計算(saas-product-demoスキルから):チップは24x24のviewBoxの(4,3)に位置するため、レンダリング幅Wで要素は(-4W/24, -3W/24)だけオフセットされます — これがないと、すべてのクリックが対象から約6〜8ピクセルずれます。
- ズームパンチは音楽ビートに合わせます(上記「音楽」を参照);パンチがビートに合わせるためだけにクリックから約0.3秒以上ずれないようにしてください。
- モーダルがクリックで閉じるビート(choose-blank、add-*)には
lead: 0.45が必要です:ピークはクリック前に来る必要があり、フレームにカードがまだ開いている状態を表示し、解除時にパーツの着地場所が明らかになります。クリック自体にピークを合わせると、すでに閉じたダイアログにズームが留まります。
トラップ(それぞれがテイクの破損につながります — すべてスクリプトで処理済み)
/はログイン中でもマーケティングランディングです;エディタは/editorです。ページ内でfetch POST/api/auth/loginを使用して最初にサインインします。- 新しい
/editorでは「Start a new project」オーバーレイが自動的に開き(.new-project-overlay)、外部からのポインタクリックをすべてインターセプトします。最初にそれを操作するか、プログラム的なクリックをディスパッチします。 - ピッカーの検索入力は前回のクエリを保持します — 入力する前にCtrl+A+Backspaceでクリアしないと「esp32led」と検索します。
- ピッカーカード:
.component-picker-modal .card-nameに対して正確なタイトルを照合します(汎用テキストエンジンはモーダルの背後にあるMonacoトークンにヒットします)。結果はデバウンスされています — 最大5秒間ポーリングします。カード名は正確です(「Resistor 220 Ω」はU+2126スタイルの文字を含み、「Resistor」ではありません;/components-metadata.jsonを確認)。 - ボードは本体からドラッグしません — ピッカーがドロップした場所(キャンバスの右端近く)にボードを置き、小さなパーツはそのライブバウンディングボックスに対して左側のスペースがある場所に配置します。
- ピンクリック:アプリ自身の
[data-pin-overlay="true"][title=<pin>]divを使用し、ホスト要素に最も近い候補を選択します(タイトルが衝突します:ボードピン「2」と抵抗ピン「2」)。pinInfoオフセットからの計算は回転したパーツで壊れます。ESP32ピンの名前は「2」、「4」、「GND」です(D2ではない)。 - 各ワイヤーが着地したことを確認するには、
path[stroke="#1a1a1a"]をカウントします(すべてのワイヤーのアウトラインパス;ワイヤーにはクラス/データ属性がありません)。失敗した場合は、Escape + 再クリックで1回リトライします。 - 回路検証機能は、直列抵抗のないLEDに対してRunをブロックします(3.9e12 Aエラー)。デモではGPIO2 -> 220R -> LED A、GND -> LED Cと配線する必要があります。「Run anyway」が必要なテイクを出荷しないでください。
- 空白のテンプレートにはデフォルトのスケッチが含まれています — カメラに表示するコメントを入力する前にCtrl+Aを押し、
monaco.editor.getModels()[0].setValue(...)で完全なスケッチを設定します(リテラルなタイピングはMonacoの自動閉じ括弧と競合します)。 - 「Enjoying Velxio? / Star on GitHub」トーストは約5分以上のテイクに写り込みます — 注入されたクリーナーが毎秒それを削除します。
- PlaywrightはOSカーソルを記録しません:注入された
#vx-cursordiv + mousedownリップル(context.addInitScript)が表示ポインタです。 - コンパイル待機は実際の時間がかかります(ウォーム30秒 - コールド5分):レコーダーは
runとsim-startedを記録し、prepare.mjsがその間隔を除去します。シミュレーション開始は「in-browser」コンソール行で検出されます;「guest crashed」= 中断。 - Remotionは
--browser-executableを使用してPlaywrightのchromiumでレンダリングします(このボックスにはバンドルされたブラウザのダウンロードはありません)。
参考リポジトリ(2026-08-15 調査)
同じジャンルの2つのClaude-Codeスキルで、異なるアプローチ:スクリーンショット/回路図UIから合成カーソルでフィルムを構成します — 私たちは実際の製品を録画します。レベルアップするときにクローンしてください:
github.com/noamdorr/saas-product-demo-video— 20〜45秒のビート同期マーケティングフィルム in Remotion。学ぶべき点:サウンドトラックのビート同期(librosadetect-beats.py:スネアでシーンチェンジ、キックでシーン内イベント — 私たちの動画は無音なので、音楽を追加してズームビートを合わせることが利用可能な最大のアップグレードです)、カーソルホットスポット計算(SVG矢印の先端は24ボックスの4,3にあります — ドットカーソルを矢印に交換する場合に重要)、タイピング予算チェック、反復プレイブック。github.com/Vincentwei1021/video-shotcraft— デモソース+ギャラリー付き152のショットレシピカード(vincentwei1021.github.io/video-shotcraft)、認定テンプレート(Ink Press)、2.5Dカメラ移動、サウンドデザイン、3つの動作モード(テンプレート/自律/共創)。学ぶべき点:ディレクターズショット語彙と最終レビューチェックリスト;完全な映画的作品が必要な場合、プラグインとしてもインストールできます。
関連
- スクリーンショットパイプライン:
scripts/shots.mjs(同じリポジトリ)— AIパネルが対象でない限り最小化されたシーン。 - GIF:セグメントを録画(Playwright recordVideo)し、ffmpegの2パスパレットで変換;ズーム+クロップパターンについては
scripts/weather-media.mjsを参照(クロップ領域は要素のboundingBoxから取得)。 - ステージングテストユーザー:memory
vstaging-test-user(s3-tester、pro)。 - 壊れたショーケースプロジェクト(ウェザーステーション)は
project/docs-portal-2026-08/STATUS.mdで追跡されています(velxio-prod内)。