解說影片
將「解釋這個功能」變成一個簡短的 MP4:真實的應用程式畫面、語音解說、字幕、像真人一樣移動的游標,以及正在討論的控制項周圍的環形醒目標記。由使用者提供簡報並進行審閱。其他一切由你完成。
這項工作中有一個比任何其他環節都重要的審查關卡:使用者在錄製任何內容之前批准旁白敘述。 更改措辭在腳本上只需要幾秒鐘,在影片上則需要幾分鐘;而錯誤的主張在紙上發現的成本遠低於在影片中發現。
你需要什麼
- 應用程式的原始碼,以及一個你可以開啟並登入的實例(本地或開發/測試環境)。千萬不要對正式環境進行錄製:操作會點擊真實的按鈕。
- 應用程式專案中的 Playwright(
node_modules/playwright或@playwright/test)。大多數包含端對端測試的專案都已經有它。如果沒有:npm i -D playwright && npx playwright install chromium。 - 在 PATH 環境變數中可用的
ffmpeg和python3。 - 最終語音的文字轉語音金鑰(Murf 或 ElevenLabs)。如果沒有,
--provider say會使用 macOS 的語音,對於草稿版本來說沒問題。請參閱references/voices.md。
請先檢查這些項目,並清楚地說明缺少了什麼。不要要求使用者將 API 金鑰貼到對話中:而是要求他們將其放入環境變數或被 git 忽略的檔案中,並告訴你金鑰的位置。
工作流程
1. 接受簡報
你需要四項資訊。只詢問請求中尚未說明的部分。
- 目標和觀眾。 「與技術長協調新的權限頁面」產生的影片,與「教導新成員如何發佈應用程式」的影片完全不同。觀眾決定影片長度、詞彙以及需要說明的程度。
- 流程。 要展示的內容及其順序。如果使用者提供了流程,請加以改進並說明你做了哪些更動及原因:更好的順序、遺漏的步驟、或是沒有貢獻的步驟。他們要求的是影片,而不是他們清單的逐字稿。
- 長度。 預設為 60-120 秒,並鎖定一個主題。如果流程需要更長時間,建議製作兩部影片。
- 語音。 如果他們有偏好,請提供供應商和語音。否則使用預設值。
2. 在編寫任何文字前,先在真實應用程式中實際操作流程
執行應用程式,使用示範帳號登入,然後使用 Playwright 或瀏覽器親自執行流程中的每一個步驟。你要確認旁白將要宣稱的每一件事都是真實的。
這個技能的大部分價值來自於此。功能敘述常常是根據記憶或規格書描述的,而實際的應用程式會有些微不同。如果應用程式沒有做到使用者所說的功能,請停下來告訴他們,並附上你觀察到的情況。不要編寫掩蓋問題的旁白,也不要默默跳過該步驟。
在進行時,記下按鈕和選單上的確切標籤。旁白應該使用螢幕上實際顯示的文字。
3. 植入示範資料
在一個空白或不完整的帳號上進行解說看起來像是一個錯誤報告。建立故事所需的資料:一個組織、幾個不同角色的使用者、具有可信名稱的項目。只使用虛構的名稱(Acme、Northwind、example.com):這些影片會被轉發。
記錄你建立或修改的所有內容。你將在第 9 步驟將其恢復。
4. 編寫敘述文字,然後停下來等待審查
將其編寫成一個表格,並儲存在影片將放置的位置旁邊,檔名為 <nn>-<slug>.script.md:
| # | 畫面上 | 旁白 | ~秒 |
|---|---|---|---|
| 1 | 任務列表靜止。列表上出現環形標記。 | 這是團隊任務列表。/ 團隊中的每個人都看到相同的任務。 | 5 |
| 2 | 游標移至 **新增任務**,表單開啟。輸入名稱,點擊 **儲存任務**。 | 要新增任務,請選取新增任務,/ 為它命名,/ 然後儲存。 | 7 |
/ 符號將一個場景的旁白分割成字幕行。在編寫之前請閱讀 references/narrative.md:它涵蓋了節奏、行長度、前/後卡片以及使這些影片難以理解的常見錯誤。
向使用者顯示表格並等待。說出預期的總長度。如果你改變了他們的流程,請在此時說明。只有在他們批准後才繼續進行;如果他們要求修改,請再次送出修改後的表格。
5. 產生語音
將已批准的敘述寫入 scenes.json,每個場景一行,行在 / 符號處分割:
[{ "id": "02", "lines": ["要新增任務,請選取新增任務,", "為它命名,", "然後儲存。"] }]
python3 scripts/tts.py scenes.json --audio-dir work/audio --provider murf
這會為每個場景寫入一個音訊片段以及 durations.json。刻意先處理語音再錄製:每個場景在畫面上的停留時間等於其音訊片段的長度,因此必須先存在片段長度。重新執行只會重新產生文字已變更的場景。
6. 編寫錄製腳本並進行試執行
複製 example/record.cjs 並為這個流程重寫其場景。scripts/walkthrough.cjs 提供了以下輔助函式:
| 輔助函式 | 用途 |
|---|---|
scene(id, async () => {...}) | 一個有旁白的場景。顯示其字幕並等待語音播放完畢。 |
clickAt(locator) | 將游標滑動到元素上,顯示按下動作,然後點擊。使用這個,而不是 locator.click(),否則操作會發生但看不到原因。 |
moveTo(locator) | 指向某個元素但不點擊。 |
typeInto(locator, text) | 點擊一個欄位並以可讀的速度輸入文字。 |
ring(locator) / ring(null) | 標記語音正在討論的內容;當語音移開時移除標記。 |
step('第 2 步,共 4 步 · 儲存') | 在左下角顯示標籤,告訴觀眾他們目前的位置。 |
card({ title, subtitle }) | 全螢幕標題卡片,用於結尾場景。 |
card({ before, after }) | 前/後比較。card(null) 隱藏它。 |
login: async (page) => {...} | record() 的選項。在鏡頭外登入,這樣影片就可以從故事開始的地方開始。 |
優先使用角色和標籤定位器(getByRole、getByLabel)而非 CSS:它們在重新設計樣式後仍然有效,而且是旁白使用的名稱。在執行階段從螢幕上讀取名稱,因為不同環境的資料可能不同。
先用 dry 執行它:
node record.cjs <app-repo> work/rec work/audio/durations.json dry
試執行不會錄製任何內容,也不會等待語音,因此錯誤的選擇器只會浪費幾秒鐘,而不是整個錄製過程。修正直到每個場景都能執行。
7. 錄製和組合
node record.cjs <app-repo> work/rec work/audio/durations.json
python3 scripts/mux.py --rec work/rec --audio-dir work/audio --output walkthrough-videos/<nn>-<slug>.mp4
錄製器會印出每個場景的音訊片段長度以及其動作所花費的時間。如果一個場景在語音結束後被標記有數秒的靜默,表示該場景的動作比旁白時間還多:請修剪動作,或讓旁白說更多話。
mux.py 會寫入 MP4、對應的 .srt 以及 <name>.sheet.jpg。
8. 在使用者之前親自檢查
開啟聯絡表:每個場景一個影格。檢查環形標記是否出現在錯誤的元素上或遺失、字幕是否遮蓋了正在討論的內容、場景是否在錯誤的畫面中、畫面上是否有開發者工具徽章或錯誤提示、以及真實的個人資料。如果聯絡表太小無法判斷,可以使用 ffmpeg 提取單一影格。
然後將影片提供給使用者,並附上:影片長度、與已批准敘述相比的任何變更(如果有的話),以及你無法驗證的任何事項。
當使用者想要修改時,請先回到敘述。 修改表格,展示給他們,獲得同意,然後只重新產生已變更的部分。大多數回饋(「太快了」、「我搞不清楚什麼變了」、「也提一下過濾器」)都是針對腳本的回饋,僅修正錄製內容會產生一個不再符合其腳本的影片。
9. 恢復原狀
使用步驟 3 中的清單以及錄製本身點擊的內容(切換的設定、建立或移除的項目、示範帳號的狀態),撤銷錄製所做的更動。然後告知使用者哪些內容已恢復,以及你刻意保留的內容(例如,他們可能為下一部影片需要的種子資料)。如果某些內容無法恢復,請說明原因。
檔案
交付物應放在使用者可以找到的同一位置,預設為專案中的 walkthrough-videos/:
walkthrough-videos/
03-add-a-task.mp4
03-add-a-task.srt
03-add-a-task.script.md
將工作檔案(scenes.json、音訊、原始錄製檔案、錄製腳本)保存在儲存庫外部或被 git 忽略的資料夾中。這些檔案很大,而且錄製腳本保存的是應用程式生命週期中某個時間點的選擇器。腳本和 .srt 值得保留:它們讓下一次修訂變得很簡單。
可能出錯的情況
- 原生控制項無法錄製。 原生的
<select>下拉式選單、檔案選擇器或瀏覽器對話方塊是由瀏覽器在頁面外部繪製的。使用moveTo指向控制項,使用selectOption/setInputFiles設定值,並讓旁白說明選擇了什麼。 - 疊加層在導航後消失。 疊加層會在每次頁面載入時重新建立,並恢復當前的步驟和字幕。如果頁面完全替換了
document.body,請在頁面穩定後再次呼叫step()。 - 場景在頁面準備好之前開始。 在呼叫
scene()之前(而非在其內部)等待場景所需的元素(await locator.waitFor()),這樣載入時間就不會被旁白覆蓋。 - 前幾秒是空白頁面。
mux.py會修剪第一個場景之前的所有內容。請在呼叫scene('01')之前進行導航和等待。 - 登入過程出現在鏡頭中。 使用
login選項。沒有人需要看到密碼欄位,而且憑證不得出現在共享的影片中。