Velxio 宣傳影片管線
分為三個階段,全部位於此儲存庫(velxio_docs;開發機上的 /home/dave/velxio_docs):
- 錄製 —
scripts/promo-record.mjs驅動真實產品在測試環境上的端到端操作(空白專案 -> 選擇 ESP32 -> 加入 220R + LED -> 旋轉電阻 -> 透過引腳點擊接線 -> 編寫草稿 -> 執行 -> 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='<請參閱記憶區中的 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 亮起。
圖庫展示影片(基本模式)
每個圖庫範例一支短影片——開啟它、執行它、拍攝它運作的過程——並附帶分割片頭卡片(左側為標誌 + 標題 + 開發板,右側為整個電路)、下方三分之一處的標題、片尾以及配樂。
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 ...] # 每個錄製產生一個 mp4
- 精選展示集位於
gallery-record.mjs頂部的GALLERY變數;slug 來自scripts/gallery-index.json(縮圖檔名即 slug)。 - 靜態圖像以
deviceScaleFactor: 2拍攝,並裁剪至電路的邊界框:足夠銳利以填滿 1080p 畫面的半邊。不要為了放大較小的電路而縮放應用程式——畫布的縮放以其中心為錨點,會導致電路偏離畫面;應改為重設視圖。 - 邊界框檢測需要每個範例使用全新的上下文:第二次客戶端載入編輯器會導致畫布空白而無法測量。
- 無開發板的範例(數位/類比類別)永遠無法編譯:執行按鈕保持停用,SPICE 引擎從一開始就驅動它們。
- 後端 QEMU 開發板(STM32、Raspberry Pi)不會輸出「瀏覽器內」的主控台行。STM32 另外無法在測試環境上執行(libqemu-arm 是選用資產,未部署在該環境)——編譯需 3 秒,但永遠不會啟動。
- 原始錄製檔(
promo/public/gallery/*.webm,每個約 3 MB)已加入 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標記)。 - 片頭標題位於純色暗色卡片上——絕不半透明覆蓋在使用者介面上。
- 縮放必須置中其主體:使用 translate+scale 搭配邊緣限制(
Promo.tsx),絕不使用 transformOrigin-at-point(這會使主體位於邊緣並被裁切,例如 ESP32 卡片)。 - 加入元件的節拍使用短暫停留(約 0.5 秒),以便縮放能及時釋放,讓觀眾看到元件放置的位置。
- 程式碼節拍置中整個編輯器窗格(fx/fy 覆寫為 357,280)——絕不在編寫程式碼時裁剪編輯器。
- 點擊執行後,將游標移開(錄製器移動到 700,620),以便按鈕的旋轉圖示可見;執行節拍以中等比例(1.8)縮放編譯/執行區域。
- 放置後將電阻旋轉為水平(垂直預設值在鏡頭中會與其自身的接線重疊)。
- 指標是 macOS 風格的箭頭,而非圓點。熱區數學運算(來自 saas-product-demo 技能):在 24x24 的 viewBox 中,尖端位於 (4,3),因此在渲染寬度 W 下,元素會偏移 (-4W/24, -3W/24)——沒有這個偏移,每次點擊都會偏離目標約 6-8 像素。
- 縮重重拍落在音樂節拍上(請參閱上方音樂章節);切勿為了對齊節拍而讓重拍偏離其點擊時間超過約 0.3 秒。
- 點擊時模態視窗關閉的節拍(選擇空白、加入*)需要
lead: 0.45:峰值必須在點擊之前出現,以便畫面仍顯示卡片開啟,然後釋放時才顯示元件放置的位置。如果峰值與點擊同時發生,縮放就會停留在已經關閉的對話框上。
陷阱(每個都曾導致錄製失敗——已在腳本中處理)
/即使已登入也是行銷登陸頁面;編輯器在/editor。先透過頁面內的 fetch POST/api/auth/login進行登入。- 在全新的
/editor上,「開始新專案」覆蓋層會自動開啟(.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=<引腳>]div,選擇最接近主機元素的候選項(標題會衝突:開發板引腳「2」vs 電阻「2」)。從pinInfo偏移計算座標在旋轉的元件上會失敗。ESP32 引腳命名為 '2'、'4'、'GND'(而非 D2)。 - 透過計算
path[stroke="#1a1a1a"](每條接線的輪廓路徑;接線沒有類別/資料屬性)來驗證每條接線是否確實連接。若失敗則透過 Escape + 重新點擊重試一次。 - 電路驗證器會阻擋執行沒有串聯電阻的 LED(3.9e12 A 錯誤)。展示影片必須接線 GPIO2 -> 220R -> LED A、GND -> LED C。切勿輸出需要「仍要執行」的錄製檔。
- 空白模板出廠時附帶一個預設草稿——在輸入鏡頭中的註解之前先按 Ctrl+A,然後透過
monaco.editor.getModels()[0].setValue(...)設定完整草稿(逐字輸入會與 Monaco 的自動閉合括號功能衝突)。 - 「喜歡 Velxio 嗎?/ 在 GitHub 上給星」的提示訊息會破壞長於約 5 分鐘的錄製——注入的清理器每秒將其移除一次。
- Playwright 不會錄製作業系統的游標:注入的
#vx-cursordiv + 滑鼠按下漣漪效果(context.addInitScript)是可見的指標。 - 編譯等待是真實的(暖機 30 秒 - 冷機 5 分鐘):錄製器會記錄
run和sim-started;prepare.mjs 會移除該時間段。模擬啟動是透過主控台中的「in-browser」行來偵測;「guest crashed」則表示中止。 - Remotion 透過
--browser-executable使用 Playwright 的 Chromium 進行渲染(此機器上未下載捆綁的瀏覽器)。
參考儲存庫(檢查日期:2026-08-15)
兩個相同類型的 Claude-Code 技能,但方法不同:它們從螢幕截圖/示意圖 UI 合成影片,搭配合成游標——我們則是錄製真實產品。在升級時可以複製它們:
github.com/noamdorr/saas-product-demo-video— 20-45 秒節拍同步的行銷影片,使用 Remotion。可借鑒:配樂節拍同步(librosadetect-beats.py:場景切換在小鼓上,場景內事件在大鼓上——我們的影片是無聲的,加入音樂並對齊縮放節拍是最大的單一升級)、游標熱區數學(SVG 箭頭尖端位於 24 方框的 4,3 處——如果我們將圓點游標換成箭頭,這點很重要)、打字預算檢查、迭代操作手冊。github.com/Vincentwei1021/video-shotcraft— 152 張鏡頭配方卡,附帶展示來源與圖庫(vincentwei1021.github.io/video-shotcraft)、一個經批准的模板(Ink Press)、2.5D 攝影機移動、聲音設計,以及三種操作模式(模板 / 自主 / 共同創作)。可借鑒:導演鏡頭詞彙及其最終審查清單;如果需要完整的電影級影片,它也可以作為外掛程式安裝。
相關
- 螢幕截圖管線:
scripts/shots.mjs(相同儲存庫)——場景中 AI 面板已最小化,除非它本身是主題。 - GIF:錄製一段片段(Playwright recordVideo)並使用 ffmpeg 雙通道調色盤進行轉換;有關縮放+裁剪模式,請參閱
scripts/weather-media.mjs(裁剪區域來自元素的 boundingBox)。 - 測試環境測試用戶:記憶區
vstaging-test-user(s3-tester,專業版)。 - 損壞的展示專案(氣象站)記錄在 velxio-prod 的
project/docs-portal-2026-08/STATUS.md中。