Communitygithub.com

evnchn-agentic/本地化影片

在 Apple Silicon Mac 上將外語影片(特別是普通話/日語 talking-head 影片)完全轉換為英語版本,包含同步配音、字幕與螢幕文字翻譯,100% 免費且離線處理。

本地化影片 是什麼?

此技能專為開發者與 AI 代理設計,提供一個完整的本地化影片轉換方案,能將普通話或日語的 talking-head 影片(含投影片或螢幕截圖)轉為英語版本,輸出包含對嘴同步的 AI 配音、燃燒嵌入的英文字幕,以及翻譯後的螢幕文字覆蓋層。整個流程完全在 Apple Silicon Mac 上離線執行,不依賴任何付費 API。技能的核心價值在於提供了經過實戰驗證的參考實作(engine/ 目錄),並詳細揭露了開發者自行實作時容易踩到的陷阱,例如 ffmpeg 缺少 libass 支援、TTS 合成音質不佳、配音時間不同步,以及 ASR 誤判同音笑話等問題。技能支援的管道包含 yt-dlp 下載、Whisper 語音辨識、Kokoro-onnx 神經網路 TTS 合成、ocrmac 螢幕 OCR,以及 ffmpeg-full 最終封裝。特別強調字幕應置於信箱式(letterbox)黑色區域而非畫面上方,以避免與原始影片內建字幕衝突。

相容平台~Claude Code✓Codex CLI✓Cursor✓Antigravity
npx skills add evnchn-agentic/localizing-video

在你喜歡的 AI 中提問

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

說明文件

localizing-video

將外語影片轉換為英語版本 — 同步配音 + 英語字幕 + 翻譯後的螢幕文字 — 在 Apple Silicon 上 100% 離線/免費。一個有能力的代理可以自行推導整個流程(yt-dlp、whisper、ffmpeg、scene-detect、mux);這個技能存在的意義在於工具選擇和那些推導容易踩錯的陷阱,以及經過實證的參考實作。

參考實作(從這裡開始)

此儲存庫提供了可運行的完整管道:engine/ 是通用的可執行引擎(build_dub.py — 以區塊為錨點、無漂移(請參見配音陷阱)、make_ass.py、dense_ocr.py、dedup_spans.py、render_overlay.py、run.sh);example/ 是一個完整的範例資料集。請閱讀 engine/SETUP.md + example/README.md,然後執行引擎 — 不要從頭開始撰寫。每個影片唯一需要重新處理的工作是產生 en.srt + translations.json(翻譯步驟)。引擎預設輸入為 1920×1080 解析度。

管道及各階段的決策

  1. 下載 yt-dlp(遇到 403 錯誤時嘗試 --extractor-args "youtube:player_client=web_safari,ios,tv";當 DASH 受 DRM 保護時,HLS 格式通常有效)。
  2. 語音辨識 (ASR) — 但先執行 yt-dlp --list-subs(參見陷阱):一個手動/創作者提供的字幕軌可能比 Whisper 更好且免費,-orig 標記會揭露影片的真實原始語言(避免在對已是目標語言的影片執行 Whisper 浪費時間),而一條 -orig 自動字幕則是一個免費的第二 ASR 用於交叉驗證。接著使用 openai-whisper:whisper source.mp4 --model large-v3-turbo --language <zh/ja> --word_timestamps True --output_format all(保留 JSON)。務必鎖定語言。(torch 沒有 py3.14 的 wheel → 請在 py3.12 的虛擬環境中執行 whisper。)
  3. 自行翻譯字幕(由代理以循環方式處理)— 免費、貼近語境、術語一致。保持 1:1 的片段↔時間戳映射。利用知識修正專有名詞(ASR 常聽錯)。保留笑點,而不只是字面意思 — 雙關語通常無法經由字面翻譯存活;重新創作一個具有相同機制的英文雙關語,並在字幕中呈現笑點(字幕是笑話的主要載體 — 配音會壓低原始音量)。同音雙關語在 ASR 中是不可見的(參見陷阱),因此請透過 OCR 辨識字幕來找到它們。
  4. 配音 — Kokoro-onnx TTS(參見陷阱)。以句子為單位合成,將每個區塊錨定到其真實時間戳(而不是逐段追逐漂移 — 這會累積延遲),進行時間調整,混音。調整視覺內容以配合配音,而不僅僅是讓配音去配合時鐘 — 請參見時間密度。
  5. 字幕 — 將英文字幕燒錄在信箱式黑色區域中,而非畫面上方(參見陷阱)。
  6. 視覺 OCR — ocrmac(Apple Vision),密集掃描(1fps),去重後得到時間區間。
  7. 自行翻譯螢幕文字;將英文覆蓋在僅含中文的區域上。
  8. 封裝 — ffmpeg-full(含 libass),依序進行:覆蓋層 → 信箱式黑邊 → 字幕燒入 → 配音音訊。

陷阱 — 這個技能存在的真正原因

陷阱現實 / 修正方式
ffmpeg 沒有 subtitles 濾鏡預設的 brew ffmpeg 缺少 libass。請使用 /opt/homebrew/opt/ffmpeg-full/bin/ffmpeg。(技能:hardsubbing-video)
TTS = say 聽起來平淡/機械預設使用 Kokoro-onnx(免費、神經網路、透過 onnxruntime 支援 py3.14)。男性聲 am_michael 等。
Kokoro 靜默失敗:phontab ... No such file捆綁的 espeak 資料路徑錯誤。brew install espeak-ng,然後在腳本中覆寫 espeakng_loader.get_data_path/get_library_path 指向 /opt/homebrew/share/espeak-ng-data + /opt/homebrew/lib/libespeak-ng.dylib。
英語發音資訊密度高於中文/日語 → 配音會延遲不要使用 atempo(>1.25× 會產生聲碼器偽影)— 改用 Kokoro 原生 speed 參數重新合成。不要使用遊標追逐漂移(cursor-start 追趕法):實證上在密集的連續語音中,它會在中段累積約 +5 秒的延遲。解決方案:(a) 將每個語句錨定到其真實起始時間(= 字幕/影片時間軸),這樣漂移就無法累積;(b) 將相鄰的 ASR 片段合併成約等於句子的語句,這樣較長的英文句子可以從較短的鄰居那裡「借用」時間 — 逐片段的調整在 1.9× 上限下截斷了 59% 的句子;而合併成句子後這個數字降至約 0%。錨定消滅了漂移,但非超時 — 一個語句的音訊長度超過其時間槽時,仍會與下一個錨點衝突。超時容錯順序: (1) 更簡潔的翻譯、(2) 在約 1.9× 上限內以更快的速度重新合成(「壓縮」= 原生 speed 重新合成或更短的文字 — 不是 atempo)、(3) 凍結延伸其下的投影片(參見時間密度)、(4) 借用相鄰低密度區塊的空閒時間;最後手段,設定硬上限並將尾部淡出 30 毫秒(字幕仍承載完整句子)。
英文字幕渲染在畫面上方,字體超大SRT→libass 預設使用 PlayResY=288 → 字型和邊距被放大了約 4.4 倍。請輸出含明確 PlayResY 的 ASS = 加上黑邊後的高度。並且使用信箱式黑邊(在底部填充一個黑條,Alignment=2),這樣英文字幕就不會與來源影片本身已燒錄的字幕衝突(你無法移除那些)。
視覺 OCR "需要自訂腳本"不需要 — pip install ocrmac;使用 ocrmac.OCR(f, language_preference=["zh-Hans","en-US"]).recognize() 即可回傳 (text, conf, (x,y,w,h)) 標準化座標,原點在左下角。
比對 ASR 與螢幕字幕底部字幕是旁白權威性的真實文字 — 絕佳的 ASR 交叉驗證。但創作者會埋入搞笑字幕(亂碼 ≠ 台詞);永遠不要盲目地用 OCR 取代 ASR。標記出差異處,逐一判斷。
ASR 靜默地抹平了同音雙關笑點就是這個同音字:例如 人工智能(AI)被說成 人工痔能("hemorrhoid-tech"),或 擱置("shelve the project")被說成 割痔瘡("hemorrhoid removal")。Whisper 會將罕見的雙關「校正」為常見詞,所以笑點永遠無法進入轉錄稿 — 而且沒有任何專有名詞修正能挽回。創作者通常會在內嵌字幕中拼寫出這個雙關,所以在這裡 OCR 不是交叉驗證 — 它通常是唯一可靠的恢復途徑(對於拼寫出的同音雙關,字幕是正確的,這與上面搞笑字幕的情況相反)。徵兆:某一行讀起來特別直白,或者觀眾的反應/畫面與台詞不符 → 在翻譯前先對那行字幕進行 OCR。
在檢查 YouTube 自己的字幕之前就執行 Whisperyt-dlp --list-subs 只需 5 秒,卻能帶來三種好處。(1) <lang>-orig 標記 = 影片的真實原始語言;如果它已經是你的目標語言(例如 en-orig),那麼整個管道就是無操作 — 在下載和執行 Whisper 之前就停止。(2) 手動/創作者提供的字幕軌(原始語言)通常比 Whisper 更好:有正確的標點、正確的專有名詞、沒有插入的 [music]。(3) 一條 -orig 自動字幕是免費的第二 ASR — 將其與 Whisper 的輸出進行比對,可以精確找出需要人工修正的臺詞。在一個 16 分鐘的英文演講中測量:單字一致性高達 98.2%,然而兩個引擎在 Arthur Andersen(YouTube 正確)vs Anderson(Whisper 錯誤)上產生分歧,並且兩者都搞錯了一個品牌名稱(Saily → "Saylite"/"Saley")— 交叉驗證可以標記這些錯誤;單獨任何一個引擎都無法發現。陷阱: --list-subs 中列出的其他 100 多種語言是 YouTube 的自動翻譯,不是創作者提供的字幕 — 不要將那裡的 zh-Hant 行誤認為是真正的中文來源。
覆蓋所有中文區域在評論影片中,螢幕上的許多「內容」(文章、嵌入的演講、推文)已經是英文,只是疊加了中文 — 再覆蓋一次是多餘且雜亂的。請將範圍限縮在僅中文元素。
在滾動文字上使用靜態覆蓋基於每個區塊(平均位置)的覆蓋無法追蹤連續滾動 — 中文部分會保持未覆蓋狀態。需要逐幀 OCR 加上框體追蹤;通常不值得(那些內容通常是已經處理過的英文內容)。
保留原始英文片段的可聽性當來源影片播放真實的英文片段(如訪談/示範)時,請在間隔處以完整音量傳遞原始音訊;僅在配音下方將其降低(約 0.1)。
在新影片上重複使用腳本請調整腳本,但檢查是否有硬編碼的長度或路徑。render_overlay.py 曾從一個硬編碼的幀數推導覆蓋層持續時間 — 在較長的影片上,覆蓋層會在中途靜默停止。請從 len(glob('f1/f_*.png')) 推導持續時間,而不是使用常數。 每個影片需要重新翻譯 en.srt + translations.json;索引配對的斷言檢查加上並排比對抽查可以捕捉翻譯/按鍵錯位。

時間密度:重新調整時間軸,而不只是調整配音

英語的資訊承載速度大約是普通話/日語的 1.5~2 倍,因此忠實的配音在密集的來源影片上總是會爭搶播放時間。壓縮配音(使用原生 speed 參數)是一個手段,但它在大約 1.9× 之前聽起來會很匆忙。更大的槓桿是:視覺時間軸是有彈性的 — 重新調整它以配合配音。 三個槓桿,按成本從低到高排列:

  • 首先採用更簡潔的翻譯(密集→更短)。 將最密集的句子改寫得更短。免費,不會損失觀眾看到的任何資訊,而且如果配音稍微修剪了一點,燒入的字幕仍然承載完整含義。這是 talking-head 鏡頭的主要槓桿(你無法在不產生抖動的情況下凍結移動的臉部;使用 B-roll 重新剪輯通常超出本地化任務的範圍)。
  • 凍結延伸靜態投影片(在壓力大的地方爭取時間)。 配音最急促的時候,正是 narrator 在朗讀螢幕截圖/投影片的時候 — 而那個畫面是靜態的,所以在一個自然的停頓處將它延長一小段時間來爭取空檔。這幾乎是隱形的,前提是你遵守三個條件:(i) 這是一個時間軸編輯 — 所有後續內容都會因這個停頓而延後,所以請插入凍結並根據調整後的時間軸重新產生字幕/配音/覆蓋層的時序(或在封裝時一併調整所有軌道),而不僅僅是將它錨定到原始時間;(ii) 僅在音訊背景也暫停時才進行凍結 — 在連續的音樂/環境音/原始音訊上進行凍結會使背景音訊不同步(請延伸/交叉淡入處理它,或僅在配音下方進行凍結,此時背景音訊已被壓低或靜音);(iii) 「靜態」必須是真正的靜態 — 畫面中的游標、閃爍的插入符號、雷射筆或網路攝影機畫面都會破壞這個幻覺。請進行多次小凍結,永遠不要一次長時間拖曳(幾秒鐘的凍結會被視為停頓/緩衝)。
  • 從低密度區域回收空閒時間(反向操作 — 低密度→高密度)。 開場、片尾、慢速平移都有多餘空間;讓配音在這些地方呼吸,或將空閒時間往前借給密集的段落。

為什麼這很有效:密度和可凍結性相關。 Narrator 的旁白最密集,正是因為他在解釋投影片 — 而投影片正是可以被凍結的。所以大部分的時間壓力往往會落在你可以吸收它的地方。測量它,不要假設它: 透過逐幀的畫面運動(在縮小灰階圖上計算 mean|frame − prev|)來標記每一秒是否為靜態 — 但閾值需要針對每個影片校準(編碼器噪點、位元率、幀率、顆粒感都會影響它;在某一個影片中約為 4/255),而且整幀平均值會錯過局部運動(游標/插入符號/滑鼠指標)→ 請遮罩掉字幕區域並檢查一個靜態區域,而不是整個畫面。然後將靜態遮罩與快速配音的語句區塊進行比對,以了解有多少壓力是可以透過凍結來解決的。在一個測量過的 10 分鐘解說影片中,在 1.4× 的冷靜上限下需要回收約 14 秒,而其中 74% 落在可凍結的靜態投影片上(26% 落在無法凍結的 talking-head 上 → 需要使用更簡潔的措辭)— 但這個比例因影片而異。對於一個獨立的檔案而言,超過來源影片的執行時間是可以接受的;沒有外部時鐘需要與它同步。

需要與操作者討論的決策點

  • 視覺範圍: 目標性(僅中文,建議)vs 全面性(也包含文章段落 — 在滾動時會降級)。
  • 配音聲音: 選擇哪個免費的 Kokoro 聲音;僅在操作者放寬禁止付費的限制時提議付費選項(ElevenLabs)。
  • 音訊: 完全取代 vs 保留原始音訊並在配音下方降低音量。
  • 節奏處理: 接受快速的配音(字幕承載完整含義)vs 重新調整時間軸以達到冷靜的上限(更簡潔的措辭 + 凍結延伸投影片 — 需要測量一次並重新封裝)。提供測量數字供操作者決定。

驗證(不要相信 — 親眼查看)

對最終的 mp4 檔案(讀取 JPG)進行幀取樣,時間點包括:一個旁白時刻、一個投影片/覆蓋層時刻、一個英文片段間隔,以及最後一行 — 確認字幕同步、覆蓋層位置、信箱式黑邊,以及音/影片長度匹配。像素是永久燒錄進去的。特別要對一個 DENSE-投影片時刻進行取樣(即配音最急促的地方)— 那是同步/漂移首先崩潰的地方;該時間戳上已燒入的中文字幕就是你的同步判準。(你無法自己試聽音訊 — 同步是結構性的,透過錨定的時間軸來保證;請直接這樣說,並要求操作者做最後的聽覺檢查。)

與以下技能搭配使用

hardsubbing-video(關於 ffmpeg/libass 燒錄陷阱的處理 — 本技能的第 8 階段)。

相關技能