展示與解說 是做什麼的?
你負責協調一個完整的流程,將任何網站、一個標誌以及一些使用意圖,轉化為一段 5 分鐘、有旁白且具有品牌風格的示範影片。scripts/ 目錄中的腳本只是單純的管道;你才是指揮者。
此資料夾中的參考文件:docs/SCHEMAS.md(YAML 與動作文法)、docs/GOTCHAS.md(已知問題與解決方法)、docs/CONTEXT.md(「什麼是好的輸出」)、examples/halyard-spme/(完整的標準範例)。請在需要時閱讀這些文件 — 不要預先載入它們。
何時使用此技能
- 使用者想要一個網站的旁白示範影片(包含線上、本機開發或靜態網站)。
- 使用者至少有一些意圖指引(「展示 X、Y、Z」/「示範儀表板流程」)。
- 使用者有標誌或文字商標可以使用。
如果使用者沒有提供意圖筆記或標誌,請拒絕繼續進行。 使用預設品牌的通用示範影片是不好的示範。請要求使用者提供指引,而不是默默地產出品質不佳的影片。
環境偵測(開始前請先閱讀)
在執行任何操作之前,請先判斷 Claude 正在哪個環境中執行:
- Cowork:
mcp__cowork__list_artifacts和mcp__computer-use__screenshot在 Claude 的工具清單中可用。 - Claude Code CLI:這些工具不存在。
這點很重要,因為許多階段在不同環境中會有不同的行為。快速參考:
| 階段 | Claude Code CLI | Cowork |
|---|---|---|
| 工作目錄(階段 5) | ~/demo-videos/<縮寫名稱>/ | request_cowork_directory 輸出路徑 |
| 公開網站探索(階段 2b) | Playwright MCP 工具 | Chrome MCP 工具或無頭模式的 explore_page.py |
| 驗證擷取 OAuth(階段 2a) | 透過 Bash 執行 capture_auth.py | 使用者在本機執行 capture_auth.py |
| 長時間指令(階段 7–9) | 同步執行 | nohup + 輪詢(45 秒 Bash 逾時) |
| 交接(階段 11) | 回報 mp4 路徑 | mp4 路徑 + computer:// 連結 |
階段 1 — 訪談(收集輸入)
一次只問一兩個問題,不要全部同時問。必問項目:
- 目標 URL — 確認可以連線。
- 示範意圖筆記 — 要講述什麼故事?哪些功能很重要?
- 觀眾與語氣 — 內部/外部/投資者;說明性/銷售性/技術性/休閒性。
- 目標長度 — 預設 5 分鐘。
- 標誌 — URL 或路徑。如果只有純文字可用,請標示此限制但接受。
- 品牌顏色 — 主要顏色(墨水色)+ 強調色。如果未指定,使用 PIL 從標誌推斷。
- 需要驗證? — 網站是否需要登入?
- 不需要 → 繼續進行。
- 需要,表單式(網站有自己控制的電子郵件/密碼欄位)→ 在
demo_config.yaml中使用session.pre_session。收集憑證環境變數名稱(不是實際值)以及登入 URL/選擇器。告訴使用者他們必須在執行前將實際憑證放在<工作目錄>/.env中,絕對不要在聊天中提供。請參閱examples/login-flow/。 - 需要,OAuth / SSO / 魔法連結 / 通行金鑰(Google、Microsoft、Okta 等)→ 使用
session.storage_state。使用者不需要執行任何指令。由你為他們在階段 2a 中啟動helpers/capture_auth.py,並且他們只需要在開啟的瀏覽器視窗中互動式地登入。擷取到的auth.json隨後將同時用於階段 2b 的探索和階段 8 的錄製。請參閱examples/oauth-storage-state/。
階段 2a — 驗證擷取(僅限 OAuth)
如果階段 1 的問題 7 確定為「無需驗證」或「表單式」,則完全跳過此階段。對於 OAuth / SSO / 魔法連結 / 通行金鑰,請在現在、網站探索之前就擷取已驗證的會話 — 階段 2b 需要它來檢視已驗證的頁面。
mkdir -p ~/demo-videos/<demo-縮寫名稱>/
uv run helpers/capture_auth.py <登入或起始 URL> \
--out ~/demo-videos/<demo-縮寫名稱>/auth.json \
--viewport <recording.viewport 來自 demo_config.yaml;預設 1440x900>
透過 Bash 工具執行此指令,設定 timeout: 600000(10 分鐘 — 最大值)。此腳本會開啟一個有頭 Chromium 視窗。用通俗的語言告訴使用者:
「我正在為你開啟一個瀏覽器視窗進行登入。完成登入(Google、Microsoft 等,處理雙重驗證),導航到你希望錄製開始的頁面,然後關閉瀏覽器視窗。我會儲存會話並自動繼續。」
此腳本會以原子操作方式寫入 auth.json,權限設為 0600。如果使用者花費超過 10 分鐘(雖然罕見,但如果在另一個房間使用手機進行雙重驗證則可能發生),Bash 逾時會觸發 — 只需重新執行相同的指令。
--viewport 必須與 demo_config.yaml 中的 recording.viewport 相符。某些網站會指紋識別視窗大小;不符可能會在錄製時間或探索時間使擷取的會話失效。
如果 Playwright 的 Chromium 尚未安裝(剛複製技能),腳本會顯示可操作的錯誤。執行一次 uv run --with playwright playwright install chromium。
如果在 Claude Code CLI 中執行: 按上述方法透過 Bash 執行 capture_auth.py。
如果在 Cowork 中執行: Claude 會直接使用 computer-use 和 Chrome 工具處理 — 使用者只需要在瀏覽器開啟時登入。步驟如下:
-
確保已知工作目錄路徑。 如果階段 5 尚未執行,請立即呼叫
mcp__cowork__request_cowork_directory以取得輸出路徑,並將<工作目錄>設定為<輸出路徑>/<demo-縮寫名稱>/。 -
在使用者的桌面上開啟 Chrome:
mcp__computer-use__open_application → "Google Chrome" (或 "Chrome") -
導航到登入 URL。 如果已連線,優先使用 Chrome MCP:
- Chrome 擴充功能可用:
mcp__Claude_in_Chrome__navigate到<登入或起始 URL> - Chrome 擴充功能未連線:使用
mcp__computer-use__*工具點擊網址列並輸入 URL
- Chrome 擴充功能可用:
-
告訴使用者登入 — 用通俗的語言說:
「Chrome 已在登入頁面開啟。請登入(處理任何雙重驗證、SSO 等),然後導航到應該開始錄製的頁面。完成後請告訴我。」
-
等待並觀察。 每約 15 秒使用
mcp__computer-use__screenshot輪詢。當 URL 不再是登入/驗證頁面,且看到儀表板或應用程式頁面時繼續。 -
透過 JavaScript 擷取會話狀態。 使用
mcp__Claude_in_Chrome__javascript_tool執行此片段:(() => { const cookies = document.cookie.split(';').map(c => { const [name, ...rest] = c.trim().split('='); return { name: name.trim(), value: rest.join('='), domain: location.hostname, path: '/', expires: -1, httpOnly: false, secure: location.protocol === 'https:', sameSite: 'Lax' }; }).filter(c => c.name); const ls = {}; for (let i = 0; i < localStorage.length; i++) { const k = localStorage.key(i); ls[k] = localStorage.getItem(k); } const ss = {}; for (let i = 0; i < sessionStorage.length; i++) { const k = sessionStorage.key(i); ss[k] = sessionStorage.getItem(k); } return JSON.stringify({ cookies, origins: [{ origin: location.origin, localStorage: Object.entries(ls).map(([n,v]) => ({name:n,value:v})), sessionStorage: Object.entries(ss).map(([n,v]) => ({name:n,value:v})) }] }, null, 2); })() -
使用 Write 工具將結果寫入
<工作目錄>/auth.json。這是有效的 Playwrightstorage_state格式 —helpers/explore_page.py和record_demo.py都透過browser.new_context(storage_state=…)使用它。 -
HttpOnly Cookie 注意事項。 JavaScript 無法讀取 HttpOnly cookie — 它們對
document.cookie來說是故意不可見的。如果網站的會話 Token 僅為 HttpOnly(在較舊的 Rails/Django 會話 cookie 中常見),則擷取的狀態將會缺少它。告訴使用者:「注意:標記為 HttpOnly 的會話 cookie 無法從 JavaScript 存取,因此我可能沒有擷取到所有驗證 Token。錄製時會嘗試使用已擷取的內容 — 如果階段 8 期間遇到登入牆,我們可以回退到在本機使用
capture_auth.py。」 然後繼續 — 許多現代網站(Google、Microsoft、Okta)會在非 HttpOnly cookie 或 localStorage 中保留足夠的狀態,讓 Playwright 可以運作。
階段 2b — 網站探索
如果階段 2a 已執行(auth.json 存在),請使用 helpers/explore_page.py 來檢視已驗證的頁面 — Playwright MCP 無法載入 storage_state,只會看到登入牆。對於無需驗證的示範,Playwright MCP 就很好用且更具互動性;請像以前一樣使用它。
對於需要驗證的頁面:
mkdir -p ~/demo-videos/<demo-縮寫名稱>/_explore/
uv run helpers/explore_page.py https://target.example.com/dashboard \
--storage-state ~/demo-videos/<demo-縮寫名稱>/auth.json \
--out-dir ~/demo-videos/<demo-縮寫名稱>/_explore/
這會為每個頁面在 _explore/ 目錄中寫入三個檔案:<縮寫名稱>.png(螢幕截圖)、<縮寫名稱>.dom.html(用於選擇器選取的 DOM)、<縮寫名稱>.meta.json(包含 {url_requested、final_url、title、status})。使用 Read 工具讀取 PNG 以查看頁面;對 DOM 進行 grep 以尋找選擇器。如果 meta.json 中的 final_url 指向一個登入頁面,表示會話已過期 — 請重新執行階段 2a。
對於公開頁面(任何示範的登陸頁面、行銷頁面;無需驗證示範的所有內容)— 像以前一樣使用 Playwright MCP 工具(mcp__plugin_playwright_playwright__*):
- 使用
browser_navigate導航到目標 URL,然後導航到使用者意圖提到的 2–5 個頁面。 - 使用
browser_snapshot或browser_take_screenshot查看每個頁面的版面。 - 使用
browser_evaluate讀取 DOM 以取得穩定的選擇器(盡可能偏好語意化選擇器而非nth-of-type)。
如果在 Claude Code CLI 中執行: 按上述方法使用 mcp__plugin_playwright_playwright__* 工具。
如果在 Cowork 中執行: 首先確保 Chromium 可用:
uv run --with playwright playwright install chromium
然後選擇最佳可用方法:
- 如果
mcp__Claude_in_Chrome__navigate可用(Chrome 擴充功能已連線),使用mcp__Claude_in_Chrome__navigate+mcp__Claude_in_Chrome__read_page來互動式探索網站。 - 否則回退到無頭探索:
(公開頁面不需要mkdir -p <工作目錄>/_explore/ uv run helpers/explore_page.py <url> --out-dir <工作目錄>/_explore/--storage-state— 此參數現在是選填的。)
針對每個重要頁面記錄:
- 值得示範的時刻(捲動到功能、點擊以查看詳細資訊、懸停工具提示)。
- 需要的網站適應調整:固定標頭技巧?PDF 深層連結?模態框阻塞?驗證牆?
- 看起來脆弱且可能需要
wait_for_selector防禦機制的選擇器。
不要窮舉爬取。每個頁面 2–5 個動作就足夠了。
階段 3 — 草稿 storyboard.yaml
產生 15–30 個分鏡。每個分鏡 = 一個攝影機動作 + 1–3 句旁白。請參閱 docs/SCHEMAS.md 的動作文法(階段 A 子集:goto、goto_and_scroll、scroll_into_view、scroll_y、hover、click)。
5 分鐘影片在 1.2 倍速下的目標:
- 加速後總時長:約 5:00
- 原始總執行時間:約 6:00
- 每個分鏡平均:約 12 秒,其中約 9–10 秒是旁白
撰寫旁白時的硬性規則:
- 每個事實性陳述必須在此分鏡的畫面上可見。 不要編造數字(例如「代理程式標記了 199 個變更」)。如果你在螢幕截圖上沒看到,就不要說。
- 需要逐字母閱讀的縮寫必須以連字號書寫:
S-P-M-E、K-Y-B、A-P-I。TTS 提示會強制執行此慣例。 - 長度要與視覺內容相符: 捲動分鏡 8–18 秒,點擊分鏡 6–12 秒。
- 語氣要與
branding.yaml的voice.tone欄位相符。
在腦中將分鏡分組為段落(概述 / 功能 A / 功能 B / 結尾),但在 YAML 中寫成平面列表 — 不要有章節標記。
階段 4 — 以通俗英語審閱
使用者不會直接編輯 YAML。 你將草稿以編號列表的形式呈現,並接受自然語言的回饋。請使用此確切格式:
這是我草擬的示範流程。預計時長:5:08(1.2 倍加速後)。
告訴我您想更改什麼。
概述(60 秒)
1. 抵達首頁(10 秒)—「歡迎使用 Acme Cloud,一個專為小型團隊打造的無伺服器平台...」
2. 捲動到功能區(15 秒)—「三個核心功能為平台提供動力...」
3. 捲動到輸出區(8 秒)—「這十個政策領域...」
功能 1 — 儀表板(45 秒)
4. 導航到儀表板(8 秒)—「點擊進入儀表板...」
5. 懸停在即時活動饋送(12 秒)—「每個專案都顯示即時活動饋送...」
...
結尾(20 秒)
27. 回到首頁統計資料(12 秒)—「團隊選擇 Acme 的三個原因...」
28. 結尾(8 秒)
然後:「有什麼要新增、刪除或重新排序的嗎?旁白語氣需要調整嗎?有什麼要跳過的嗎?」
將自然語言的回饋轉換為 YAML 編輯:
- 「跳過分鏡 7」→ 從 YAML 中移除
- 「將分鏡 3 加長」→ 用更多畫面上的細節擴充旁白(如果加長很多,則拆分為兩個分鏡)
- 「在某處提到定價」→ 找出正確的分鏡並加入一句話(確認定價確實在此分鏡的畫面上可見)
- 「語氣太正式」→ 用更輕鬆的措辭重寫旁白
- 「顯示團隊頁面而不是關於頁面」→ 交換 URL 並調整旁白
重新呈現更新後的流程。反覆迭代,直到使用者明確批准。
在 TTS 之前進行執行時間漂移檢查: 將所有分鏡的 len(beat.narration) / 16(以 140wpm 的速度,字元/秒)相加。如果 估計值 * (1 / 速度倍數) 與目標相差超過 30 秒,請提出:「目前加速後的時長約為 6:20,與您 5 分鐘的目標不符。需要我修剪嗎?」
階段 5 — 工作目錄設定
mkdir -p ~/demo-videos/<demo-縮寫名稱>/_assets
cp <標誌路徑> ~/demo-videos/<demo-縮寫名稱>/_assets/<logo>.png
# 從您的草稿寫入 storyboard.yaml、branding.yaml、demo_config.yaml
如果在 Claude Code CLI 中執行: 按上述方法使用 ~/demo-videos/<demo-縮寫名稱>/。
如果在 Cowork 中執行: 呼叫 mcp__cowork__request_cowork_directory 以取得使用者的輸出路徑。將工作目錄設定為 <輸出路徑>/<demo-縮寫名稱>/。在階段 6–11 的所有後續檔案寫入中,均使用此路徑 — 現在就儲存它並在整個會話期間保持一致。在此路徑下建立 _assets/ 子目錄,而不是在 ~/demo-videos/ 下。
如果使用者磁碟上沒有標誌檔案,只有 URL,請使用 curl 下載並將其放在 _assets/ 中。