Communitygithub.com

上船示範片

用一份腳本把網頁應用拍成有旁白的產品示範:配音、字幕和清晰的介面截取,素材來自建好的倉庫或線上地址,並按各平台的畫幅出片。

上船示範片 是什麼?

把一個網頁應用收成成品示範片。一份腳本驅動聲音、字幕和高清介面,涵蓋 Reels、Shorts 和橫幅,倉庫本地建置或線上頁面都可以拍。

相容平台~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/himohitmehta/shipdemo/tree/HEAD

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

上船示範片 是做什麼的?

scripts/demo 拍攝網頁應用程式,並將其語料庫寫入 ~/demo-reels-out/<workspace>/(DEMO_OUT_ROOT 可變更父目錄,DEMO_OUT 則指定單次執行的目錄名稱):每個場景都會產出包含旁白的 mp4、海報、視網膜螢幕截圖,以及 full-tour.mp4、manifest.json 和 index.html。所有檔案均在本地產生。引擎從此技能執行;不會在待拍攝的應用程式中安裝任何內容。

不可妥協的事項

以下每一項都可能耗費一次執行或使用者的耐心。

  1. 固定建置版本,絕不使用開發伺服器。 開發伺服器的模組圖譜屬於正在編輯原始碼的人。請將建置版本複製到私人位置,並透過讀取 bundle 來驗證其 API 基礎位址。沒有對應儲存庫的網址屬於 site 模式;位於 localhost 的網址則是開發伺服器,絕不進行拍攝。
  2. 在 build 模式下,於行程內模擬所有請求,並鎖定時鐘。 語料庫會被發布,而真實帳號會發布真實使用者的地址。site 模式則明確放棄這兩者:僅限公開頁面。
  3. 自行管理連接埠與輸出目錄。 工作室拒絕採用非其啟動的伺服器。絕不透過模式比對執行 pkill。
  4. 1080p60 的影片,2 倍大小的螢幕截圖。 這是兩個不同的設定。4K 影片會出現抖動,因為吞吐量有固定的每秒像素預算。
  5. 先執行動作,然後在推近到結果上時進行旁白。 每行只描述一個主體。在主體出現之前絕不進行旁白。如果應用程式本身有計時器(例如復原視窗、提示訊息),則動作應在計時器內執行,旁白則在之後進行,否則影片會顯示一個實際上無法運作的功能。
  6. 拍攝一個場景,然後停下來詢問(步驟 8)。這項做法在拍攝另外二十六個場景之前,就已捕捉到四個缺陷。
  7. 每次都要檢查 PNG 檔案。 一個場景雖然通過,但卻框錯了目標,這就是失敗;而只有仔細檢視螢幕截圖才能發現這個問題。
  8. 在使用者確認之前,沒有任何內容是最終版本。 任何關於用詞、構圖、節奏、涵蓋範圍或配音的意見,都是需要重新拍攝,而不是協商:修改後再拍一次。使用者無法看到你所看到的內容,因此「太長了」、「再放大一點」和「不要放那麼大」都是完整的指示,而一個場景重拍兩次的成本很低。

工作流程

  1. 根據你取得的資訊選擇模式,不要詢問。 位於公開主機上的 http(s) 網址是 site 模式,工作區為 ~/.shipdemo/<host>/。位於 localhost 或私人位址的網址則是開發伺服器:找出其背後的儲存庫,並將該請求視為該儲存庫。沒有網址則表示你目前所在的儲存庫,因此請向上層目錄尋找網頁應用程式(包含建置腳本的 package.json,且旁邊有 Vite、React Router、Next、Astro、SvelteKit 或 Remix 設定檔)。如果只有一個,則為 build 模式;如果有多個,請詢問要使用哪一個;如果沒有,請要求提供網址或路徑。工作區的 .origin 檔案中若已記錄此儲存庫名稱,則會重複使用,不會重新建立。用一行話說明模式和工作區路徑,然後繼續。
  2. 執行 scripts/doctor.sh,然後在使用者提出任何其他要求之前,先設定好你自己的環境。 使用者安裝了一個技能,他們並不是為了要執行三個腳本。用一行話說明缺少什麼,接著說明你建議安裝的項目及其大約大小,然後在使用者同意後執行一次。scripts/install.sh 涵蓋引擎和 Chromium(約 250MB),並在套件管理員允許的情況下同時安裝 ffmpeg;scripts/install-voice.sh 則負責安裝語音(約 350MB),如果使用者不願意安裝,也可以選擇拍攝無聲版。未經同意絕不安裝任何東西,也絕不把 doctor 報告丟給使用者自行解讀。有兩件事它不會做,你也不該做:升級他們的 Node(因為哪個工具擁有 Node 的管轄權,使用者自己最清楚),以及執行 sudo(因為在無人觀看的腳本中出現密碼提示只會導致程式卡住)。在這些情況下,腳本會印出一條指令,由你轉達給使用者。
  3. 探索,但不寫入任何內容。 site 模式:開啟網址並閱讀,了解頁面的用途、三個值得展現的重點,以及哪些部分足夠穩定可以指出。如果頁面停留在登入畫面,就停止:需要登入的應用程式應從其儲存庫拍攝,因此請要求提供儲存庫或公開網址。build 模式:從 package.json 中逐字複製的建置指令;從框架設定檔中取得的輸出目錄;在 .env* 檔案中找到的任何絕對 API 主機(將其放入 build.forbid 中);主題啟動腳本讀取的 key;任何現有的 fixture API 或 MSW 處理器;data-testid 的使用密度;無需憑證即可存取的路由。
  4. 執行 scripts/scaffold.mjs <appRoot>,或 scripts/scaffold.mjs --site <url>。兩者都不會對應用程式寫入任何內容。
  5. 填寫工作區的 demo.config.ts。 如果仍有未知的必要欄位,表示探索尚未完成。config.md
  6. 僅限 build 模式:撰寫 mock.ts 和 seed/。 如果儲存庫有自己的資料 fixture,請重複使用它們,但絕不能使用會匯入 @playwright/test 的檔案:在一次執行中出現兩個副本是 Playwright 會拒絕的錯誤,而且這會導致整個語料庫失敗,而不僅僅是觸發該錯誤的那個場景。然後執行 DEMO_VOICE=0 scripts/demo --grep smoke。如果儲存庫有 fixture API,請重複使用(mocking.md)。閱讀螢幕截圖:確認已登入、資料已種子化、主題正確、且非登入頁面。閱讀捕捉行。修正直到兩者都正確,然後撰寫 demo/ui.ts,只包含煙霧測試證明過的內容。
  7. 先撰寫腳本。 填寫工作區的 profile.json(複製 template/profile.json;包含產品、目標受眾、結尾語、禁用詞彙),然後根據 script.md 撰寫每一行:開頭鉤子、步驟、成果、結尾。開頭鉤子也要放入 hooks.json 中以供後續變體使用。按照使用者要求的範圍,拍攝他們指定的功能。 一個命名的功能就是一個場景:撰寫它、拍攝它、交付它。不要用一個包含十個場景的提案來回應「錄製首頁的搜尋功能」,也不要因為產品包含更多功能就悄悄擴大需求。只有在要求的是整個產品時,你才提議 6 到 10 個場景,每個場景都有一個標題和一行簡介(依導覽順序),並詢問要先拍攝哪一個。
  8. 停下來。 拍攝那一個場景(含語音)。確認口語計數與 say 呼叫次數相符、沒有超時、速率保持穩定。閱讀每一張螢幕截圖。將 mp4 路徑提供給使用者,並詢問他們對於腳本的語氣、縮放比例、節奏和配音的意見。在使用者回答之前,不要撰寫任何其他內容。
  9. 然後透過 --grep 以三到四個場景為一批次進行拍攝;manifest 會自動合併。每批次後都要閱讀螢幕截圖。在迭代場景時,使用 DEMO_BUILD=0 scripts/demo 可以跳過重新建置,只需二十秒而非四分鐘;但在產生最終語料庫的執行中則應使用完整建置。
  10. 使用 DEMO_CAPTIONS=1 DEMO_TRACE_FRAMES=1 進行完整執行,然後執行 scripts/check.mjs <out> 並開啟 <out>/index.html。報告捕捉表格、任何慢速片段以及檢查報告中的每個標記。
  11. 變體。 詢問使用者需要哪些變體,除非他們已經指定:reel、wide-phone、wide-laptop、wide-laptop-zoom、web 或 all(scripts/variants.mjs --list 會描述每個變體)。然後執行 scripts/variants.mjs <out> --only <list>。手機預設使用直向錄製,筆記型電腦預設使用橫向錄製,因此如果使用者兩者都需要,請分別拍攝兩種尺寸。在交付前,請閱讀每個變體的海報。

一個場景

scene('tasks', { title: '你的待辦事項,就在日曆旁邊', blurb: '...' },
  async ({ actor, page, shot }) => {
    await actor.click(page.getByRole('radio', { name: '今天' }));
    await actor.settle();
    await actor.spotlight(
      row('給 Sam 傳送回饋'),
      '而這個是昨天的,我一直沒處理到,所以被標記了。',
      { scale: 1.8, stay: true }
    );
    await shot('逾期');
    await actor.unfocus();
  });

spotlight 會取得旁白標記,然後將相機和游標移到該行開頭文字的上方。縮放比例取決於主體:面板約 1.4,行約 1.7,單一控制項約 2。描述整個畫面的行則只需使用 say,不需要縮放。unfocus 與其說是移動,不如說是一個提示:相機只有在需要廣角時才會拉遠,因此連續描述同一區域的節奏會平順滑動,而不是跳來跳去。scenes.md · narration.md

絕不

使用雲端 TTS(因為影片包含私人資料)。 使用 Playwright 的 recordVideo(無法控制速率、大小或起點;已由錄製器取代)。 以 4K 為預設值。 使用音樂、開場卡片或交叉淡出。 從路由爬蟲產生場景:場景是具有明確目的編排。 重試:重試的場景是另一部不同的影片。

字幕、檢查與變體

任何預計要發布的內容都會有字幕(DEMO_CAPTIONS=1):.srt、.vtt、.lines.json 和一個 .captioned.mp4,這些都是從腳本本身剪輯出來的,因此會與配音逐字相符。內嵌字幕位於底部,且會避開播放器控制項(可使用 DEMO_CAPTION_MARGIN 覆寫;絕不放在頂部)。

scripts/check.mjs 執行三項檢查:語音(每行旁白都會被轉錄並與腳本比對)、畫面(每半秒掃描一次,檢查是否有設定檔中 neverOnScreen 指定的詞彙,以及任何以紅色繪製的內容)和影格(檢查是否有長時間停頓)。如果缺少某個工具,會顯示該工具的安裝指令(scripts/install-checks.sh)。如果畫面中的紅色是設計的一部分,例如逾期標籤,也會被列出:請閱讀清單,不要將其計入錯誤。

scripts/variants.mjs 會讀取 variants/presets.json。新增變體就是在其中新增一個條目:畫布尺寸、應用程式的擺放位置、鉤子和字幕的放置位置,以及如果需要在重點處推近時使用的 zoom 設定。所有變體都不需要重新拍攝;原始檔案不會被修改。

其他

DEMO_VOICE_VARIANTS=am_michael,bf_emma 會以更多種語音混合相同的錄製內容(<scene>.<voice>.mp4),用於在不重新拍攝的情況下試聽不同的語音。

在變更任何捕捉數值之前,請先參閱 capture.md。 關於建置、隔離和 manifest 的資訊,請參閱 runs.md。 當執行失敗或畫面看起來不對時,請參閱 troubleshooting.md。 引擎從此技能執行,因此對 engine/ 的修復會同時影響機器上的所有專案:直接在那裡編輯即可,無需進行任何傳播。

相關技能