錄製展示影片
編寫臨時的 Playwright 分鏡腳本,然後從任何工作目錄執行自包含的引擎。
除非使用者要求,否則不要將分鏡腳本加入應用程式儲存庫。
保持分鏡腳本自包含;執行器在 Playwright 載入之前會將該檔案暫存到引擎內部,因此不要使用相對於分鏡腳本的輔助匯入。
<skill-dir> 表示此儲存庫被複製的目錄,例如 ~/.claude/skills/record-demo。
編寫分鏡腳本
使用以下可攜式匯入來匯入 DSL:
import { demo } from "record-demo/storyboard";
執行器在暫存時會將此指定符重寫為引擎的實際路徑,因此分鏡腳本檔案可以放在任何位置。
編輯器對 record-demo/storyboard 的型別解析來自於 engine/tsconfig.json 的 paths - 在儲存庫外部,請將 record-demo/storyboard 對應到絕對路徑 <skill-dir>/engine/lib/storyboard.ts,放在您的 tsconfig paths 中,或將檔案保留在 engine/scripts/ 目錄下。
使用 engine/scripts/example-site.demo.ts 作為參考。優先使用 getByRole 選擇器,使用 d.click(locator) 而不是 locator.click(),使用 d.hold(...) 調整操作節奏,並對最終狀態進行斷言或等待。
demo("storyboard-title", async (d) => {
await d.seed(async (page) => {
await page.getByRole("heading", { name: "Example Domain" }).waitFor();
});
await d.step("Read the page", async (page) => {
const heading = page.getByRole("heading", { name: "Example Domain" });
await d.zoomTo(heading, { padding: 48 });
await d.hold(2_000);
d.zoomOut();
await heading.waitFor({ state: "visible" });
});
});
引擎會使用 --name 或腳本基礎名稱覆寫時間軸名稱,因此傳遞給 demo(...) 的字串不需要與輸出 slug 相符。
預飛檢查(在任何擷取之前)
當對本地提供的 checkout 進行錄製時:在提供服務的 checkout 中執行 git fetch origin 並斷言 HEAD == origin/main(或使用者命名的分支)— 過時的 checkout 會錄製到過時的設計。如果過時,請先重建/重新啟動伺服器。將服務中的 SHA 印製到錄製備註中,以便每個錄製都可以追溯。
錄製
需要 Node >= 22.18(透過 nvm 或系統)、ffmpeg、Xvfb 和 xdpyinfo。在 engine/ 目錄下使用 pnpm install 安裝一次相依套件。
node <skill-dir>/engine/record.mjs \
--script /absolute/or/cwd-relative/demo.demo.ts \
--url https://example.org \
[--name output-slug] [--formats 16x9,1x1,9x16] \
[--chrome none|macos|browser] [--storage-state <path>] [--raw]
使用 --formats 選擇一個或多個構圖預設(預設為 16x9),使用 --chrome 選擇要渲染的視窗框架(預設為 none)。格式按照請求的順序渲染,第一個格式用作主格式來編碼 GIF。
9x16 格式是激進的中心裁切(在廣角鏡頭中,約 44% 的頁面寬度是可見的),因此在為直向創作時,請將動作保持在中心。
使用 --raw 可在乾淨擷取後停止。不使用此參數時,預計會得到以下成品:
engine/out/<name>-raw.mp4engine/out/<name>-<format>.mp4(每個請求的格式)engine/out/<name>.gif(從主格式編碼)
執行器在完成時會印出成品的絕對路徑。將即時網站的可重現性視為目標網站的責任,且永遠不要在分鏡腳本中嵌入真實憑證。
已驗證的網站
僅使用暫存或測試帳戶錄製已驗證的流程;絕不使用正式環境的憑證。代理應先使用自己的工具,透過無頭 Playwright 腳本登入一次。如果登入需要透過電子郵件傳送 OTP 或魔法連結,建議的方法是使用代理自己的郵件存取權限 - 在 Claude Code 上使用已連接的 Gmail 連接器/MCP,或在其他執行環境上使用郵件 CLI - 以便代理自行讀取代碼;否則請要求使用者貼上。登入後,使用 await context.storageState({ path: storageStatePath }) 儲存 Session,其中 storageStatePath 是建立為 storageStatePath="$(mktemp -d)/<account>.storage-state.json" 的一次性臨時路徑。然後使用 --storage-state "$storageStatePath" 執行錄製命令。
Playwright 的 storageState 只會還原 Cookie 和 localStorage。將認證資訊儲存在 IndexedDB 或 sessionStorage 中的應用程式會默默地錄製到登出畫面,因此在擷取前請先驗證已驗證的頁面。storage-state 檔案是機密:永遠不要印出或提交它。錄製器在載入後會立即刪除它;這是一次性交接,因此重新錄製需要重新登入,且磁碟上不會留下任何與認證相關的資訊。一次性登入輔助腳本也包含憑證:請保持其臨時性,且永遠不要提交。
在 Remotion Studio 中編輯錄製的展示影片
錄製後匯出一個自包含的專案,然後安裝並開啟 Studio:
node <skill-dir>/engine/scripts/export-project.mjs <name>
cd <skill-dir>/engine/out/<name>-project
pnpm install
pnpm studio
Studio 的時間軸面板顯示編輯器風格的軌道(螢幕膠片、每個字幕一個命名的剪輯、聚光燈、縮放移動和片尾)- 拖曳播放頭來瀏覽,點擊剪輯的行來找到其事件。使用屬性面板或 fixtures/timeline.json 來編輯字幕、縮放時間(保持縮放移動在 1650ms 底限以上)、聚光燈時間和片尾標題。編輯 remotion/theme.ts 來調整顏色、排版、間距和動畫。使用 pnpm render 渲染完成的 16:9 影片。
動畫和分鏡規則(使剪輯可發布的要素)
- 每個場景一個攝影機移動,而不是每個欄位。 縮放一次到區塊,然後在區塊內操作。每個輸入的縮放讀起來像突兀的剪接。
- 在頁面轉換時保持廣角,在稀疏頁面上保持廣角。 在點擊進行導覽之前
d.zoomOut();永遠不要在幾乎空白的頁面上縮放到一個狀態藥丸。 - 接近頁面底部的區塊:
d.zoomTo([...locators], { scroll: "center", padding: 48 })- 攝影機夾具無法將頁面邊緣的矩形居中;滾動居中可以在根層級修正此問題。Locator[]透過聯合邊界框來框住整個區塊。 d.spotlight([...locators])= Apple 風格的焦點暗化(鏤空 + 光環)。給予充足的holdMs,在步驟結束前明確使用d.spotlightOff()+hold(600)結束。聚光燈矩形必須適合視口(強制執行);縮放矩形依設計可能會溢出。- Seed 等待真實資料,而不僅僅是觸發元素 - 否則影片會在骨架畫面上開啟。等待一個已知的內容節點 + 約 600ms。
- 在結果字幕之前
d.settle(locator)。 提交後重新擷取的檢視會短暫空白;單純的waitFor會在第一次繪製時解析,結果字幕會在空白頁面上觸發。 - 字幕是與游標動作綁定的祈使句;在結束場景中放置一個結果字幕(
d.caption(...)在步驟後期);修剪步驟字幕,使祈使句永遠不會懸掛在已完成的動作之上。 d.outro(title)在最終場景之後,以平靜的結束畫面關閉可發布的剪輯。- 始終對最終狀態進行斷言 - 沒有斷言,管線會渲染一個關於中斷流程的精美影片。
- 永遠不要發布一個包含 localhost URL、內部主機名稱、提供者名稱或真實憑證在螢幕上的剪輯。在 seed 中遮罩僅用於展示的字串(使用 window.open 修補和 MutationObserver 輸入重寫)。
在報告完成前進行驗證
- 在
engine/目錄下執行pnpm typecheck && pnpm test。 node scripts/score-motion.mjs out/timeline.json- FAIL 表示阻斷;WARN 縮放速率約 0.78/s 是可接受的穩定狀態;任何不連續性判定都是攝影機錯誤;dead-air WARN 表示靜態區段 >= 3.5 秒且游標移動少於 40 像素 - 請重新調整節奏或加上字幕。- 引擎變更後執行
node scripts/prove-composition.mjs。 - 觀看實際渲染結果:執行
ffmpeg -i out/<name>-16x9.mp4 -vf fps=1 out/frames/%03d.png並查看各幀。縮放裁剪、字幕延遲、鏤空不同步以及螢幕上的開發網址在綠色的測試執行中是不可見的。
常見問題
| 症狀 | 原因 / 修復方法 |
|---|---|
Invalid demo viewport ... 中止 | 幾何設定偏移 - 修正啟動旗標,永遠不要放鬆斷言。 |
| 游標偏移約 174 像素(垂直方向) | Chrome 以分頁模式執行,而非 --app 模式。 |
| 找不到打板框架 | 偵測器容許誤差為 64(外部擷取平均不夠純淨);如果仍然遺漏,請檢查擷取是否為黑色畫面(Chrome 使用了錯誤的 DISPLAY)。 |
| 字幕/游標在剪輯中漂移 | 打板同步問題 - 不要使用牆鐘時間相減。 |
| 聚光燈鏤空偏離目標 | 矩形與平滑滾動競速 - measureTarget 的穩定性迴圈應能固定此問題;如果再次發生,請提高其超時時間。 |
| 文字在裁切邊緣被切斷 | 對於模態框,使用 zoomTo(locator, { padding: 120 })。 |
| 縮放將內容剪出畫面 | maximumScale 是品味問題(1.45 有效),不是夾具錯誤。 |
驗證引擎變更
從 engine/ 目錄執行:
pnpm typecheck && pnpm test
node scripts/prove-composition.mjs