Communitygithub.com

learnermaker/project-demo-video-skill

將任何軟體專案、黑客松參賽作品或產品,以程式碼方式製作成附旁白、字幕的 1080p 展示影片(3 分鐘以內),使用 Playwright 和 ffmpeg-static。錄製真實應用、重播終端機輸出、瀏覽原始碼、繪製圖表、加入語音並內嵌字幕。

project-demo-video-skill 是什麼?

此技能讓開發者能將軟體專案的展示影片視為程式碼般建置與版本控管。它使用 Playwright 自動化真實應用,錄製終端機輸出並檢測原始碼,確保影片中呈現的每個元素均為真實運行的項目內容。影片完全透過指令碼驅動,支援 Windows 內建語音或 ElezenLabs 等外部工具生成旁白,並自動產生字幕。主要支援 Claude Code 等代理工具,但 Cursor 或 Codex 等平台也可透過調整使用。建立流程分為十個階段:從需求分析、工作環境設置、試運行除錯、腳本與旁白撰寫、範本調整、證據資料錄製、旁白音頻生成、錄製與合成,最後進行品質檢查與交付。此技能特別適合需要快速反覆驗證或呈現專案進度的開發者,因為任何變更僅需幾分鐘即可重新產生完整的影片。

相容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/learnermaker/project-demo-video-skill/tree/HEAD/skills/project-demo-video

在你喜歡的 AI 中提問

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

說明文件

project-demo-video

將展示影片以程式碼方式建置,以便在每次變更後數分鐘內就能重新渲染。螢幕上的一切都是真實的:運行的應用程式、真實的指令輸出、真實的原始碼檔案。絕無模擬。

此技能的撰寫方式讓能力較弱的編碼代理也能逐步跟著執行。請依序遵循各階段操作。每個階段都有一個完成條件行:在條件滿足之前不要進入下一階段。從 templates/ 複製檔案,而不是重新撰寫。

安裝:將整個資料夾(SKILL.md 和 templates/)複製到代理的技能資料夾中,例如 ~/.claude/skills/project-demo-video/,或直接將代理指向 SKILL.md。

您將產生的內容

輸出檔案說明
<name>-voiced.mp41920x1080, 30 fps, H.264 + AAC,內嵌字幕,含語音
<name>-captions-only.mp4相同畫面,無聲音軌(使用者可選擇此版本或自行錄製語音)
<name>.srt字幕檔案,文字與旁白相同
thumbnail.png1280x720
narration.md, shotlist.md含真實時間戳記的腳本;每個場景及其來源
frames/您實際查看過的 QA 幀
repo/變更或新增的專案檔案,以對應的儲存庫路徑呈現
COPY_LIST.md, README-snippet.md, REPORT.md應複製的內容、README 區段說明、已完成事項與風險

0. 您不得違反的規則

  1. 唯讀原始碼。 絕對不要寫入、提交或推送到使用者的真實儲存庫。在複本中工作(robocopy/cp,排除 node_modules、.git、建置輸出),然後執行 npm ci。將值得保留的變更放在輸出資料夾下,對應儲存庫路徑,加上 COPY_LIST.md。由其他工具或人員處理 git 操作。
  2. 螢幕上要誠實。 任何模擬的內容(設備、連線、付款、模型)必須在影片中標示為「模擬」。絕不暗示不存在的硬體、部署或使用者。複製專案本身的「真實 vs 模擬」表格;如果 README 有誤,請在報告中說明,不要重複該不實陳述。
  3. 螢幕或交付檔案中不得出現機密: 權杖、API 金鑰、.env 內容、私鑰、真實電子郵件。專案文件中的開發權杖(例如 Bearer dev-alice)則可使用。展示程式碼時,應選擇排除機密內容的行數範圍。
  4. 不要在幀、旁白、字幕或交付文件中提及撰寫程式碼的 AI 工具或其供應商 ,除非使用者另有指示。屬於產品設定一部分的執行時模型 ID 可以作為模型名稱出現。完成前請用 grep -ri 檢查。
  5. 遵守競賽規則。 閱讀時間限制(通常為「少於 3:00」;目標設定為 2:50)及必要技術規則。影片必須展示必要技術真正在運作,而不僅是提及。
  6. 免費方案,不部署、不購買。 不要進行部署、建立雲端資源或花錢。如果某個步驟需要憑證或使用者的錄製內容,請清楚詢問一次,然後繼續處理其他所有事項。
  7. 僅向使用者要求 憑證、他們自己的錄製內容,或真正屬於他們的選擇(例如哪種語音)。其他事項由您自行決定,並告知您的決定。

1. 先決條件(檢查,不要假設)

node --version          # 22+(建議 24;.mjs 檔案必須是純 JavaScript,無 TypeScript 轉型)
  • 在專案複本中:必須存在 @playwright/test(已安裝 Chromium)和 ffmpeg-static。檢查方式:node -e "import('@playwright/test').then(async m=>{const b=await m.chromium.launch();console.log(b.version());await b.close()})" 與 node -e "import('ffmpeg-static').then(m=>console.log(m.default))"。如果缺少且專案禁止新增相依套件,請將它們放在單獨的工具資料夾中並指向該資料夾。
  • 語音:Windows PowerShell 搭配 System.Speech(內建)。macOS 使用 say,Linux 使用 espeak-ng;然後您必須調整 templates/lib/tts.mjs(僅 synthAll 和 tts.ps1 為作業系統相依)。
  • ffmpeg-static 未隨附 ffprobe:從 WAV 標頭(templates/lib/tts.mjs 中的 wavSeconds)和錄製器自身的計時來測量持續時間。
  • Windows Shell 注意事項:對於包含反斜線、正規表達式或 $ 的任何檔案,建議使用「寫入」和「編輯」工具。內嵌 python -c/heredoc 重寫 JS 會靜默破壞跳脫字元。前景 sleep 在某些代理中會被封鎖:請使用 until grep -q "done" log; do sleep 10; done 等待。

2. 階段

階段 A:需求與驗證對應表

閱讀規則頁面、README、專案自身的文件以及任何故事大綱。在您的筆記中建立一個表格:

評審必須確信的是影片在哪裡證明它場景
必要技術在程式碼中被呼叫實際呼叫可見:請求日誌、終端機、程式碼摘錄...
體驗能運作應用程式在瀏覽器中運行...
什麼是真實的 vs 模擬的專案自身的表格...

完成條件: 每一列都有一個對應的場景。

階段 B:工作區

  1. 將儲存庫複製到一個暫存資料夾,然後安裝:npm ci。
  2. 將 templates/ 複製到該複本中,命名為 video/(保留結構:video/lib、video/pages、video/scenes、video/final.mjs、video/narration.mjs……)。在 package.json 的腳本中新增:"video:final": "node video/final.mjs"。不要新增任何相依套件。
  3. 在複本的 .gitignore 中新增 video/out/。

階段 C:試運行真實應用並修復錯誤(在錄製任何內容之前執行此步驟)

以評審會使用的方式啟動應用(npm run demo 或 README 中的指令),使用其文件規定的預設連接埠,確保螢幕上顯示的每個指令都是字面上的。使用一個小型的 Playwright 腳本驅動它,在故事的每個步驟後以 1920x1080 解析度截圖,然後查看它們。檢查:

  • 登入、空白面板、紅色錯誤橫幅、主控台錯誤;
  • 故事需要的每個狀態都能正確渲染(參考專案的第一次試運行顯示了登入失敗、空白收件匣和缺少關鍵檢視,這些都被舊的草稿影片隱藏了);
  • 文字重複或被截斷。

在複本中最小程度地修復真實錯誤,執行專案自身的檢查(npm run verify、測試、型別檢查),並記錄每個修復項目於 COPY_LIST.md。如果應用程式沒有顯示網路流量的方式,請新增一個小型可選鉤子(請求日誌),而不是偽造一個。 完成條件: 整個故事連續兩次順利執行,且專案的檢查通過。

階段 D:故事板與旁白

  1. 選擇場景。參考故事(約 2:50):
場景長度展示內容
鉤子12 秒一個變更波及多個承諾(動畫卡片)
啟動6 秒啟動一切的單一指令,真實輸出
模擬(應用程式)60 秒8-10 個節拍;在 2 個節拍中開啟請求日誌
驗證終端機17-30 秒對同一個伺服器執行官方客戶端或 CLI;驗證檢查
程式碼導覽16 秒3-4 個證明必要技術的真實摘錄
架構、雲端堆疊、真實 vs 模擬30 秒圖表、堆疊原始碼、誠實表格、開源卡片
結尾12 秒標語、儲存庫連結、建置資訊、「X 為模擬」頁尾
  1. 撰寫 video/narration.mjs:scenes = [{ id, title, segs: [{ id, text }] }]。每個 seg 是一句口語台詞和一個字幕(text 會照原樣顯示)。規則:每秒約 2.4 個單詞;總口語單詞數 330-380;每行一個想法;螢幕上任何卡片不超過約 12 個單詞;句子大小寫;不誇大。
  2. 在語音引擎的 say 表格中加入發音提示(僅限於口語,例如縮寫拼讀、「Alexa+」唸作「Alexa plus」);絕對不要變更字幕文字。 完成條件: 旁白讀起來像一個陌生人能理解的故事,且驗證對應表中的每一行都有被說出或顯示。

階段 E:調整範本

僅編輯專案特定的部分:

檔案編輯內容
video/narration.mjs您的場景和台詞
video/scenes/sim.mjs您應用程式的步驟:要輸入或點擊的內容、選擇器、鏡頭縮放(lens(...)、zoomWire)
video/scenes/static.mjs終端機指令(CMD)、codeBlocks(檔案 + 第一行的正則表達式 + 行數 + 高亮正則表達式)、鉤子/結束頁面呼叫
video/proofs.mjs、video/proof-auth.mjs證明您主張的真實指令;它們只輸出狀態碼和錯誤名稱
video/pages/*.html文字、顏色、圖塊、圖表方塊、表格列、連結
video/lib/overlay.mjs您應用程式佈局的 SIM_CSS 選擇器(參閱佈局規則)、跑馬燈的資料來源
video/final.mjsLIMIT 常數和場景順序(順序來自 narration.mjs)
video/thumbnail.mjs、video/docs.mjs標題和 SHOT 表格

除非有問題,否則不要編輯 lib/recorder.mjs、lib/director.mjs、lib/tts.*。

階段 F:錄製真實的驗證輸出

node video/proofs.mjs 會啟動一個全新的伺服器,執行真實的指令(官方檢測工具或客戶端 CLI、驗證檢查、安裝/啟動輸出),並將它們輸出的內容儲存到 video/out/proofs.json。終端機場景會重播這個擷取的輸出,呈現在一個可讀大小的 HTML 終端機中。規則:顯示真實的指令文字(僅縮短路徑套件);明顯截斷過長的輸出(以暗淡的「... N 行 ...」行表示),並在標記中寫入「記錄運行」;絕不輸出權杖;如果有的話,以美化格式輸出 JSON 並說明。

階段 G:旁白音訊

預設(無需帳號):node video/final.mjs --rate 2 會使用內建的 Windows 語音(Microsoft Zira)為每一行產生一個 WAV 檔案,並測量每個檔案的長度。速率 1 對參考腳本來說約為 150 秒的語音,速率 2 約為 139 秒,速率 3 太快。選擇能讓整部影片保持在限制內的最慢速率。 選用的人聲語音:參閱附錄 A。以下的所有步驟無論使用哪種語音都相同。

階段 H:錄製與合成

node video/final.mjs --rate 2                   # 全部:tts、驗證、錄製所有場景、合成兩種版本
node video/final.mjs --rate 2 --reuse-proofs    # 跳過重新執行驗證
node video/final.mjs --scenes sim,close --reuse-tts --reuse-proofs   # 僅重新錄製某些場景
node video/final.mjs --assemble-only            # 重新合成(字幕、音訊)而不重新錄製
node video/final.mjs --tts-dir video/out/tts-human --name my_video --single    # 從另一個音訊資料夾建置

完整運行需要 6-10 分鐘;請在背景執行並輪詢日誌。如果總時長達到 180 秒或以上,腳本會失敗。目標設定為 170 秒。 重要:如果您變更了旁白文字或語音,持續時間會改變,因此每個場景都必須重新錄製(標記來自持續時間)。僅變更一個場景的視覺效果,則使用 --scenes <id> --reuse-tts。

階段 I:品質檢查(絕不省略,絕不信任日誌)

  1. 從最終的 MP4 檔案中,取出每個旁白行結束時的幀:ffmpeg -ss <markEnd-0.3> -i final.mp4 -frames:v 1 frame.png(時間線在 video/out/timeline.json 中)。查看它們。檢查在 1080p 下的可讀性、空白區域、裁剪的文字、字幕位置與大小、同步(字幕事件在螢幕上)、無機密、無供應商提及、存在誠實標籤。
  2. ffmpeg -i final.mp4 -af volumedetect -f null -:平均值約 -22 dB,最大值低於 0 dB。
  3. 兩種版本的持續時間均在限制內;兩個檔案都有影片和音訊串流。
  4. grep -ril "<供應商詞彙>" video/pages video/narration.mjs <輸出文件> 除了允許的模型 ID 外,不應返回任何結果。
  5. 再次執行專案的檢查(npm run verify;如果 UI 有變更,則執行 e2e)。
  6. 修復並重新渲染,直到全部通過。

階段 J:交付項目

使用 node video/docs.mjs <outdir> 產生 narration.md 和 shotlist.md(真實時間戳記)。複製 MP4、SRT、縮圖(node video/thumbnail.mjs <png>)、QA 幀以及變更的儲存庫檔案(原始檔案與您的複本之間的所有差異檔案,以對應的儲存庫路徑呈現)。撰寫 COPY_LIST.md(錯誤修復優先,然後是新檔案、建議的提交訊息、「複製後執行建置與驗證」)、README-snippet.md(執行指令、進入點檔案:行號、客戶端檔案:行號、技能檔案、影片連結佔位符)以及 REPORT.md(已完成事項、使用者必須執行的操作、風險)。明確說明您無法檢查的內容(例如,您無法收聽語音)。

3. 管線運作方式(變更前請先閱讀)

錄製器(lib/recorder.mjs)。Playwright 自身的 recordVideo 會限制位元率並模糊小文字,因此這個腳本使用 Chromium 螢幕截取:JPEG 幀(品質 92)在到達時加上時間戳記,寫入磁碟,並以恆定 30 fps 使用 libx264 crf 17 編碼。靜態畫面產生的幀數較少;最後一幀會持續顯示。時間戳記來自同一個時鐘(performance.timeOrigin + performance.now()),也是導演使用的同一個時鐘。

導演(lib/director.mjs)。每個旁白行都是一個片段。d.seg(id, actions, {tail}) 會記錄開始時間,執行螢幕上的動作,然後持續直到該行播放完畢再加上 tail * 0.45 秒(尾音會全域修剪以符合限制)。標記(id、開始、結束、文字)會儲存到 video/out/<scene>.marks.json。因為音訊之後會根據記錄的標記放置,所以畫面和語音不會偏移。關於節拍的規則:在片段內執行動作,並確保動作在旁白結束前完成;如果台詞比動作短,則將其拆分為兩個台詞(這就是為什麼一個故事節拍變成了 sim9 和 sim10)。

音訊(final.mjs)。每個 WAV 會使用 adelay 延遲到其全域開始時間,使用 amix=normalize=0 混合,使用 alimiter 限制,並使用 apad=whole_dur=<total> 補齊(如果沒有補齊,-shortest 會剪掉影片的結尾)。

字幕。 提示是根據旁白文字在句子結尾處拆分(例如「2.0」這樣的小數會被保護),以及在超過 82 個字元時的逗號處拆分,時間按長度比例分配。.srt 檔案會交付。內嵌版本使用一個生成的 ASS 檔案,其中包含 PlayResX: 1920, PlayResY: 1080 和字型大小 36。不要使用 force_style 來內嵌 SRT:libass 會根據 288 像素高的畫布進行縮放,導致文字約為原本大小的四倍。

疊加層(lib/overlay.mjs),僅注入到錄製的應用程式頁面中(應用程式本身未經編輯,因此 Playwright 選擇器保持不變)。疊加層包含:狀態列的 SIM 標記、一個提示錄製正在進行並附有倒數計時的資訊列、一個根據 tickerLines 更新的軟性跑馬燈,以及供導演使用的遠端控制 API(seg、prop、state)。這些 API 呼叫不會出現在影片中。

附錄 A:使用 ElevenLabs 的人聲語音

  1. 從 ElevenLabs 取得一個 API 金鑰。
  2. 設定 ELEVENLABS_API_KEY 環境變數。
  3. 在 video/narration.mjs 的頂端,將 export const TTS = 'elevenlabs'; 設為非註解。
  4. 您可以透過在 video/narration.mjs 中編輯 export const ELEVENLABS_VOICE = '<voice_id>'; 來選擇語音。
  5. ElevenLabs 會將文字轉錄為音訊;它與 templates/lib/tts.* 中的相同邏輯相容。
  6. 使用 node video/final.mjs --rate 2 --elevenlabs 來使用 ElevenLabs 語音。

注意:ElevenLabs 並非免費;您需要一個付費帳號。

附錄 B:疑難排解

  • 「找不到 Chromium」錯誤:npx playwright install chromium
  • 「ffmpeg 未找到」錯誤:檢查 ffmpeg-static 是否已安裝,以及 node -e "import('ffmpeg-static').then(m=>console.log(m.default))" 是否回傳路徑。
  • 語音問題:在 Windows 上,確保 PowerShell 執行原則允許執行 Add-Type -AssemblyName System.Speech。執行 powershell -Command "Add-Type -AssemblyName System.Speech; $s=New-Object System.Speech.Synthesis.SpeechSynthesizer; $s.Speak('test')" 進行測試。
  • 字幕時間偏移:如果字幕與語音不同步,請檢查 video/out/timeline.json 中的 markEnd 值。如果它們與實際的語音持續時間不匹配,請使用 --reuse-tts 重新錄製語音。
  • 影片太長:減少場景長度,或使用更快的語音速率。您也可以透過在 video/narration.mjs 中編輯 seg 物件的 tail 屬性來修剪尾音。
  • 「權杖已洩漏」錯誤:檢查 video/pages/ 和 video/narration.mjs 中的檔案是否有任何機密內容。使用 grep -ri 遍歷 video/ 目錄。

相關技能