/dubbing
一個透過 Perso AI Dubbing 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)——上傳/分割只執行一次,並為每個語言重複使用。絕對不要為每個語言執行一次(這會每次都重新上傳來源)。 - 忠實地傳達進度。 將工作程序的標準輸出
[progress]行原樣或總結後顯示在聊天中——並且不要宣布未出現的步驟(分割/合併僅在影片超過限制時存在)。縮排的標準錯誤詳細日誌則無需轉達。 - 在運行時讓使用者保持知情。 配音、唇形同步和音訊分離都會列印一個
[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 "<file|URL>" [--source auto] [--target en] [--space "space name"] [--out result.mp4] [--lipsync] [--no-save] - 多語言 / 多輸入(一個或多個輸入;URL 和檔案可以混合):
node scripts/dubbing.mjs "<URL>" "<file>" --target en,ja— 每個輸入 × 語言產生一個輸出,儲存在每個來源旁邊(--out <folder>將它們收集起來)。 - 資料夾(批次):
node scripts/dubbing.mjs "<folder>" [--target en,zh] [--recursive] [--out output-folder]
語言代碼 —— --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 "<folder>" 執行,並在每次後續工作中繼續使用該資料夾,直到他們更改為止。如果他們在運行開始後重新導向,請在運行完成時將已完成的檔案移動到那裡。例外:當每個輸入都是 URL(沒有本機來源資料夾)時,請在開始前詢問儲存位置。
空間選擇 —— 如果有多個工作區,工作程序會在上傳前停止,列印 [space-select] 行(名稱 | (方案) | 剩餘額度)並停止。僅向使用者顯示這些選項(無內部編號),詢問他們要哪一個,並使用 --space "<space name>" 重新執行。只有一個空間 → 無需詢問;PERSO_SPACE_SEQ 會固定它。
分割確認 —— 如果輸入超過長度或大小限制且必須自動分割和合併(配音、配音+唇形同步或音訊分離),工作程序會停止並列印 [split-confirm] 行。轉達它們並詢問使用者:它超過了長度/大小限制,因此需要自動分割 → 處理 → 合併,這可能比他們自己分割不那麼精緻 —— 是否自動繼續?如果同意,使用相同的命令加上 --allow-split 重新執行(在此之前不會產生任何費用,因此重新執行是免費的)。批次運行:--allow-split 授權運行中的所有分割。
不儲存(僅限伺服器) —— 當使用者希望影片被配音但不儲存為本機檔案時,請加上 --no-save:工作程序將結果留在使用者的 Perso 工作區中並跳過下載,列印 Kept on server, not saved: … → project <seq>(仍然會發出 [project-ref] 行,因此配音可以在之後進行唇形同步或檢索)。僅限單一/未分割影片 —— 分割影片的合併檔案需要本機下載,因此它會正常儲存,工作程序會這樣說明。不能與 --lipsync 結合使用(唇形同步的影片必須下載)。
免費方案(結果保留在 Perso) —— Free 工作區可以正常進行配音、唇形同步和分離,但伺服器會拒絕每一次下載,因此工作程序永遠不會在那裡儲存檔案。它會列印 Free plan — <name>: … ready on Perso → <url> (downloads need a paid plan) —— 將該連結轉達為已交付的結果:運行已完成,沒有失敗,也沒有需要恢復的內容。如果使用者想要實際檔案,則需要付費方案——提供升級途徑(請參閱方案升級與額度),絕對不要重新執行。
免費方案 [free-limit] 暫停 —— 有兩個,都在產生任何費用之前:
- 30 秒預覽。 長度超過 30 秒的配音/唇形同步輸入會以
[free-limit]行停止:在 Free 方案下,只有前 30 秒會被配音,其餘部分被排除。轉達問題,如果同意,使用相同的命令加上--allow-preview重新執行(工作程序會在本機修剪前 30 秒並僅提交該部分)。由 Perso 匯入的平台連結無法被修剪——在這種情況下,解決方案是本機檔案、較短的剪輯或升級。 - 超過方案限制。 超過方案長度/大小限制的媒體在 Free 方案下不會獲得分割選項(
--allow-split不適用):[free-limit]行表示唯一的途徑是較短的檔案或升級。轉達它們並停止。
在運行時(用於解釋等待原因):
- 分割:首先上傳整個檔案;只有方案限制拒絕時才會安裝 ffmpeg 並進行無損分割。外部 URL(YouTube·TikTok·Drive·Vimeo)由伺服器端處理。
- 佇列:所有輸入 × 部分 × 語言共用一個池;滿的佇列每 5 分鐘重新檢查一次。某個部分的引擎錯誤會取消該部分的其他語言;靜默的部分會讓原始部分通過;空閒防護可以防止無限掛起。
- 儲存:部分會合併回每個(輸入 × 語言)一個檔案。未分割的輸出保留 Perso 檔案名稱;合併的輸出為
<original-name>.dubbed.<lang>.<ext>;衝突會加上_2、_3…。
唇形同步
唇形同步(嘴巴匹配配音音訊)在配音之後,在完成的配音專案上執行。僅限影片——拒絕音訊輸入。這是一個長時間的工作:在背景執行,並預先告知使用者它比配音花費的時間長得多。 額度(伺服器計費是權威的):配音 ≈ 秒數 ×1 · 唇形同步 ≈ ×2 · 兩者兼有 ≈ ×3 —— 現在配音 + 稍後唇形同步的費用與同時進行相同。4K+ 來源:專業/商業/企業方案每項費率 ×3(例如,一個 1 分鐘的 4K 配音+唇形同步 ≈ 60×3×3 = 540)—— 當影片為 4K 時請提及這一點。
根據現有內容選擇流程:
- 新影片 + 唇形同步 —— 一個命令執行整個鏈(配音 → 唇形同步 → 儲存);警告兩個階段都會計費:
node scripts/dubbing.mjs "<file|URL>" --target en --lipsync如果列印了[credit-check]行並停止,則估計值超過剩餘額度:顯示這些行(包含頂儲 URL),並僅在使用者頂儲或批准繼續後使用--force重新執行。 - 在此會話中較早時進行了配音 —— 每次完成的運行都會列印一個
[project-ref] {...}行。保留它;絕對不要向使用者顯示。 無需重新配音的唇形同步(×2,無配音費用):node scripts/dubbing.mjs --lipsync-only '<that [project-ref] JSON>' - 此會話中沒有 [project-ref] —— 詢問使用者是否知道 Perso 入口網站中的專案編號(
--lipsync-only <number>,×2)。否則必須再次配音(--lipsync,×3)—— 在重新配音前確認。
規則:
- 在同一專案上重複進行唇形同步會再次計費(無伺服器端去重)。如果此會話已經對其進行了唇形同步,請指向現有檔案,並且僅在明確確認後才重新執行。
- 如果唇形同步失敗,工作程序將改為儲存配音後的影片,並在最終報告中說明——清楚地轉達這一點;配音額度不會浪費。
- 在配音和唇形同步之間額度用盡:配音後的影片會被儲存,並且僅完成唇形同步——轉達頂儲 URL,並在付費後通過
[resume-state]路徑繼續(請參閱中斷與恢復)。
說話者(僅限配音專案)
要為已配音專案的一個或多個句子指定新說話者,請執行:
node scripts/speaker.mjs "<project URL|projectSeq>" --at "5s,22s,98s"(逗號分隔的時間碼/範圍)
node scripts/speaker.mjs "<project URL|projectSeq>" --text "first line|second line"(豎線分隔,引用的文字)
node scripts/speaker.mjs "<project URL|projectSeq>" --sentence 1234,1288(在 [sentence-select] 問題後重新執行)
node scripts/speaker.mjs "<project URL|projectSeq>" --list(瀏覽專案的句子以找到正確的目標)
僅限配音專案 —— 工作程序會拒絕字幕(STT)、音訊分離和唇形同步專案,以及未完成/失敗的專案。它會根據專案連結自行確定工作區;您無需詢問是哪個空間。
暫停不是失敗。 [sentence-select] 行表示工作程序無法鎖定單一目標(未提供任何內容、未匹配到任何內容或匹配到多個句子)——它會乾淨地退出以詢問您一些事情,而不是因為失敗。其下的編號列表(索引、時間標籤、文字)可以安全地照原樣轉達給使用者。緊接在該列表之後,一個 [sentence-ref] 行會列印一個 JSON 映射,將相同的數字映射到工作程序的內部句子編號——該行是僅供您自己查閱的:絕對不要顯示或讀出它。一旦使用者選擇了一個數字,在該映射中查找它,並使用設定為該值的 --sentence 重新執行相同的命令。旁邊的一個 [speaker-resolve] 區塊表示某些目標已解析但尚未寫入任何內容——它有自己編號的列表和自己的 [sentence-ref] 行;重新執行的 --sentence 列表必須同時包含那些已解析的值和新選擇的一個或多個值,否則已解析的那些將被丟棄。當一次執行列印多個 [sentence-select] 組(同時有多個模糊目標)時,每個組