/dubbing
一個技能,透過 Perso AI 配音 API 自動為影片配音。
核心規則(必須遵守)
- 只有工作者(worker)能看到原始金鑰。 絕不使用
Read讀取金鑰、輸出它,或將其作為命令列參數傳遞。工作者僅在XP-API-KEY標頭中傳送它。 - 一個命令即完成整個工作。
scripts/dubbing.mjs自行處理上傳、分割、翻譯、合併及儲存。絕對不要在它之前執行prepare_input.mjs或probe_split.mjs——它們是除錯工具,且probe_split.mjs會實際執行上傳(影片會上傳兩次)。 - 始終在背景執行
dubbing.mjs。 工作耗時數分鐘到數小時;前景 shell 逾時會導致執行中途被終止。 - 語言未指定時 → 來源
auto,目標en。 - 多種語言在同一個命令中處理(
--target en,zh,ja)——上傳/分割只會發生一次,並為每種語言重複使用。絕不為每種語言分別執行一次(每次都會重新上傳來源)。 - 忠實傳達進度。 將工作者的 stdout
[progress]行逐字或摘要呈現到聊天室——且不要宣布未出現的步驟(分割/合併僅存在於超出限制的影片)。縮排的 stderr 細節日誌不需要傳達。 - 在執行期間讓用戶保持了解。 配音、唇形同步和音訊分離都會列印
[status]心跳(階段 + 項目計數,例如ja 4/6 · en 1/6或separating — file 2/5,並附上next check ~Nm提示),每個完成的項目會以[progress]行串流輸出。啟動後約 3 分鐘檢查背景輸出,然後按照提示的間隔(媒體 ≤10 分鐘則 10 分鐘,更長則 30 分鐘)檢查:立即傳達任何新的[progress]行,否則發布最新的[status]行作為一行更新。絕不自行編造百分比、經過時間或預計完成時間——僅傳達這些行所說的內容。需要用戶介入的停止點([space-select]、[split-confirm]、[free-limit]、[resume-check]、[credit-check]、額度耗盡、完成)會結束處理,因此它們會出現而不需輪詢。 - 為遙測命名您的執行環境(靜默)。 在工作者命令中加入
--host <claude-code|codex|cursor|antigravity|gemini>,如果您能確定,請命名您正在執行的代理。它僅用於標記使用情況遙測——絕不向用戶展示,也絕不詢問用戶。如果不確定則省略。 - 不支援的格式會自動跳過,其餘部分繼續處理——傳達跳過通知。
- 暫停不是失敗。
[space-select]、[split-confirm]、[free-limit]、[credit-check]或[resume-check]行表示執行停止以詢問您一些事——它以狀態碼 0 退出(因此不會被視為錯誤),但工作尚未完成。每當出現這些行之一時,絕不報告工作已完成:傳達它並對其採取行動。這些行是信號,而不是退出碼。
設置(懶人——無需事先步驟)
- API 金鑰 — 不是您優先執行的步驟。 工作者在需要 Perso API 的命令執行時會自動進行金鑰門控:在首次此類執行時,它會開啟瀏覽器頁面(登入,點擊一次——金鑰會加密儲存),或者如果無法開啟瀏覽器則列印基於檔案的說明——將這些說明傳達給用戶。在無頭/SSH 機器上,工作者會完全跳過瀏覽器流程,並從檔案/
--import註冊開始(瀏覽器頁面只能將金鑰傳遞到它運行的機器上)——以相同方式傳達這些說明。切勿自行觸發金鑰註冊:工作者會在需要時自動啟動connect.mjs/resolve_key.mjs --watch,因此不要執行這些,也不要以resolve_key.mjs --check作為預先步驟(僅當用戶明確詢問金鑰是否已註冊時——金鑰缺失不是錯誤)。切勿將金鑰貼到聊天室中。取得金鑰:https://developers.perso.ai/api-keys - ffmpeg/ffprobe — 僅當影片超過方案限制且需要分割時才會自動安裝(若請求權限則批准)。手動檢查:
node scripts/check_deps.mjs。
執行
收集輸入(本機路徑或 URL——如果缺少則重新詢問)並在背景執行——工作者會在首次需要時自行執行金鑰門控;只需傳達其列印的說明(如果註冊開始):
- 單一輸入:
node scripts/dubbing.mjs "<檔案|URL>" [--source auto] [--target en] [--space "空間名稱"] [--out 結果.mp4] [--lipsync] [--no-save] - 多語言/多輸入(一個或多個輸入;URL 和檔案可以混合):
node scripts/dubbing.mjs "<URL>" "<檔案>" --target en,ja— 每個輸入 × 語言一個輸出,儲存在每個來源旁邊(--out <資料夾>收集它們)。 - 資料夾(批次):
node scripts/dubbing.mjs "<資料夾>" [--target en,zh] [--recursive] [--out 輸出資料夾]
語言代碼 — --target 接受語言代碼(en、ja)或區域標籤。僅英文(en = 美式預設,en-GB = 英式)、葡萄牙文(pt = 巴西預設,pt-PT = 葡萄牙)和西班牙文(es = 墨西哥預設,es-ES = 西班牙)存在區域變體;en-US、pt-BR 和 es-MX 是這些預設值的可接受拼寫。其他每種語言只有一個變體,且 --source 只需要語言(那裡的區域標籤會被視為純語言)。
- 請求中指定的區域 → 使用該確切標籤。沒有變體的區域(例如澳洲英語) → 告訴用戶僅存在列出的選項,並讓他們在執行前選擇。
- 兩個字母的標記是語言代碼,不是國家代碼:
uk是烏克蘭文——英式英語是en-GB。ca(加泰隆尼亞文)、be(白俄羅斯文)、eu(巴斯克文)同理。如果用戶的措辭可能指兩者,請在執行前詢問他們指的是哪個。 - 語言命名但無區域 → 使用預設變體。對於這三種語言,請在交付說明中註明所使用的預設值(例如「西班牙文(墨西哥)——使用
es-ES表示西班牙」)。
儲存位置 — --out 接受資料夾(現有目錄,或以 / 結尾的路徑),它會將結果收集在裡面,或對於單一輸入則接受檔案路徑(如果路徑沒有副檔名,則會附加真實副檔名)。預設值是在每個來源檔案旁邊;無需詢問。在會話的第一次工作時,在啟動行中說明它(例如「結果將儲存在原始檔案旁邊——如果您希望使用不同資料夾,請現在告訴我」)並立即開始,無需等待回答。如果用戶指定了一個資料夾——在此請求或此會話中的任何後續時間——則使用 --out "<資料夾>" 執行,並在每個後續工作中持續使用該資料夾,直到他們更改它。如果他們在執行已開始後重新導向,則在執行完成時將完成的檔案移至那裡。例外情況:當每個輸入都是 URL(無本機來源資料夾)時,請在開始前詢問儲存位置。
空間選擇 — 如果有多個工作區,工作者會在上傳前停止,列印 [space-select] 行(名稱 | (方案) | 剩餘額度)並停止。僅向用戶顯示那些選項(無內部數字),詢問選擇哪一個,然後使用 --space "<空間名稱>" 重新執行。只有一個空間 → 無需提問;PERSO_SPACE_SEQ 固定它。
分割確認 — 如果輸入超過長度或大小限制,並且必須自動分割和合併(配音、配音+唇形同步或音訊分離),工作者會停止並列印 [split-confirm] 行。傳達它們並詢問用戶:它超過了長度/大小限制,因此需要自動分割 → 處理 → 合併,這可能比他們自己分割較不精緻——是否自動繼續?如果同意,則使用相同的命令加上 --allow-split 重新執行(直到此時都不會產生任何費用,因此重新執行是免費的)。批次執行:--allow-split 授權批次中的所有分割。
不儲存(僅伺服器端) — 當用戶想要配音影片但不儲存為本機檔案時,加入 --no-save:工作者將結果留在用戶的 Perso 工作區中並跳過下載,列印 Kept on server, not saved: … → project <seq>([project-ref] 行仍會發出,因此配音可以稍後進行唇形同步或檢索)。僅適用於單一/未分割影片——分割影片的合併檔案需要本機下載,因此它會被正常儲存,工作者也會如此說明。不能與 --lipsync 結合使用(唇形同步影片必須下載)。
免費方案(結果保留在 Perso 上) — 免費工作區可以正常進行配音、唇形同步和分離,但伺服器拒絕所有下載,因此工作者永遠不會在那裡儲存檔案。它會列印 Free plan — <name>: … ready on Perso → <url> (downloads need a paid plan) — 將該連結傳達為已交付的結果:執行完成,沒有失敗,也沒有需要恢復的項目。如果用戶想要實際檔案,則需要付費方案——提供升級路徑(請參閱方案升級與額度),而不要重新執行。
免費方案 [free-limit] 暫停 — 兩個,都在產生任何費用之前:
- 30 秒預覽。 長度超過 30 秒的配音/唇形同步輸入會以
[free-limit]行停止:在免費方案中,僅前 30 秒會被配音,其餘部分被省略。傳達問題,如果同意,則使用相同的命令加上--allow-preview重新執行(工作者會在本機修剪前 30 秒,並僅提交該部分)。由 Perso 匯入的平台連結無法被修剪——解決方案是提供本機檔案、較短的剪輯或升級。 - 超過方案限制。 超過方案長度/大小限制的媒體在免費方案中不會得到分割提議(
--allow-split不適用):[free-limit]行表示較短的檔案或升級是唯一途徑。傳達它們並停止。
在執行期間(用於解釋等待原因):
- 分割:整個檔案會先上傳;只有方案限制拒絕時才會安裝 ffmpeg 並進行無損分割。外部 URL(YouTube·TikTok·Drive·Vimeo)由伺服器端處理。
- 佇列:所有輸入 × 部分 × 語言共用一個池;滿載的佇列每 5 分鐘重新檢查一次。某個部分的引擎錯誤會取消該部分的其他語言;靜默部分會直接通過原始內容;閒置守衛可防止無限掛起。
- 儲存:各部分會合併回每個(輸入 × 語言)一個檔案。未分割的輸出會保留 Perso 檔案名稱;合併的輸出會命名為
<原始名稱>.dubbed.<語言>.<副檔名>;衝突會加上_2、_3…。
唇形同步
唇形同步(嘴巴對齊配音音訊)在配音之後執行,針對已完成的配音專案。僅限影片——音訊輸入會被拒絕。這是一個長時間的工作:在背景執行,並事先告訴用戶它比配音耗時更長。 額度(伺服器計費為準):配音 ≈ 秒數 ×1 · 唇形同步 ≈ ×2 · 兩者同時 ≈ ×3——現在配音 + 稍後唇形同步的費用與同時進行相同。4K+ 來源:專業/商業/企業方案的所有費率 ×3(例如,1 分鐘的 4K 配音+唇形同步 ≈ 60×3×3 = 540)——當影片是 4K 時提及此點。
根據現有情況選擇流程:
- 新影片 + 唇形同步 — 一個命令執行整個鏈(配音 → 唇形同步 → 儲存);警告兩個階段都會計費:
node scripts/dubbing.mjs "<檔案|URL>" --target en --lipsync如果列印了[credit-check]行並停止,表示預估費用超過剩餘額度:顯示那些行(包含加值 URL),僅在用戶加值或批准無論如何繼續後,才使用--force重新執行。 - 在此會話中已配音 — 每個完成的執行都會列印一個
[project-ref] {...}行。保留它;絕不向用戶展示。 無需重新配音的唇形同步(×2,無配音費用):node scripts/dubbing.mjs --lipsync-only '<那個 [project-ref] JSON>' - 此會話中無 [project-ref] — 詢問用戶是否知道 Perso 入口網站中的專案編號(
--lipsync-only <數字>,×2)。否則必須再次配音(--lipsync,×3)——在重新配音前確認。
規則:
- 對相同專案重複唇形同步會再次計費(無伺服器端去重)。如果此會話已對其進行過唇形同步,請指向現有檔案,並僅在明確確認後才重新執行。
- 如果唇形同步失敗,工作者會改為儲存配音影片並在最終報告中說明——清楚地傳達此點;配音額度不會浪費。
- 額度在配音和唇形同步之間用完:配音影片會被儲存,而繼續進行僅完成唇形同步——傳達加值 URL,並在付款後透過
[resume-state]路徑繼續(請參閱中斷與繼續)。
說話者(僅限配音專案)
為已配音專案的一個或多個句子分配新說話者,執行:
node scripts/speaker.mjs "<專案 URL|projectSeq>" --at "5s,22s,98s"(逗號分隔的時間碼/範圍)
node scripts/speaker.mjs "<專案 URL|projectSeq>" --text "第一行|第二行"(以管道符分隔的引號文字)
node scripts/speaker.mjs "<專案 URL|projectSeq>" --sentence 1234,1288(在 [sentence-select] 問題後重新執行)
node scripts/speaker.mjs "<專案 URL|projectSeq>" --list(瀏覽專案的句子以找到正確目標)
僅限配音專案——工作者會拒絕字幕(STT)、音訊分離和唇形同步專案,以及未完成/失敗的專案。它會自動從專案連結中判斷工作區;您無需詢問是哪個空間。
暫停不是失敗。 [sentence-select] 行表示工作者無法鎖定單一目標(未給定任何內容、未找到匹配或匹配到多個句子)——它會乾淨地退出以詢問您一些事,而不是因為失敗。其下的編號列表(索引、時間標籤、文字)可以安全地按原樣傳達給用戶。緊接在該列表之後,[sentence-ref] 行會列印一個 JSON 對映,將相同數字對應到工作者的內部句子編號——該行是僅供您自己查詢的:絕不展示它或朗讀它。一旦用戶選擇了一個數字,在該對映中查詢它,並使用設為該值的 --sentence 重新執行相同命令。與之一起出現的 [speaker-resolve] 區塊表示某些目標已解決,但尚未寫入任何內容——它有自己的編號列表和自己的 [sentence-ref] 行;重新執行的 --sentence 列表必須同時包含那些已解決的值和新選擇的值,否則已解決的值將會被丟棄。當一次執行列印多個 [sentence-select] 組(同時有多個模糊目標)時,每個組
...
[截斷以進行翻譯]