Communitygithub.com

ThomasHMD/subtitles

修正 Premiere Pro 自動語音轉錄 JSON 檔案(充滿錯字,尤其是專有名詞),透過本機 whisper.cpp 重新轉錄影片,然後重建一個與 Premiere 完全相符的 JSON 檔案,並修正名稱、標點、大小寫、作品名稱引號,以及透過強制對齊重新對齊字詞時間。

subtitles 是什麼?

這是一個專門為 Premiere Pro 使用者設計的 AI 技能,用於修復 Premiere 自動產生的字幕 JSON 檔案。Premiere 的語音轉錄常因專有名詞(如攝影師姓名)出現大量錯字,此技能會使用本機的 whisper.cpp 重新轉錄影片,並根據參考腳本修正名稱、恢復標點與大小寫、將作品名稱加上引號。接著,它會透過強制對齊 (forced alignment) 將字詞時間戳記重新對齊到音訊上,解決 whisper 時間漂移的問題,產出一個可直接重新匯入 Premiere 的 JSON 檔案。此技能支援法文與英文,並可透過語言設定檔擴充其他語言。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ThomasHMD/premiere-rough-cut/tree/HEAD/skills/subtitles

在你喜歡的 AI 中提問

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

說明文件

subtitles:修復 Premiere Pro 字幕

一次性設定:請參閱工具包根目錄的 INSTALL.md。使用外掛時,設定指令為 bash "${CLAUDE_PLUGIN_ROOT}/install.sh" --data "${CLAUDE_PLUGIN_DATA}";若手動安裝(將四個 skills/ 資料夾並排複製到 ~/.claude/skills/),請在工具包根目錄執行 bash install.sh。 腳本位於此技能的 scripts/ 資料夾中。此技能會指向另一個技能 ../rough-cut/...。

技能功能

Premiere 產生的自動轉錄(一個 .json 匯出檔案)通常充滿錯字,尤其是專有名詞(例如攝影師姓名被拆成兩個不相關的字)。whisper.cpp 的轉錄品質好得多。 此技能會在本機重新轉錄影片,然後重建一個與 Premiere 完全相符的格式的 .json 檔案(可直接重新匯入):藉助參考腳本修正名稱、恢復標點與大小寫、將作品名稱加上引號。最後,它會透過強制對齊將時間戳記重新對齊到音訊上(whisper 的時間戳記會漂移)。

  • 是:本機轉錄、名稱修正、標點與大小寫、作品名稱引號、音訊時間重新對齊(強制對齊)、與 Premiere 格式完全相同的檔案,可直接重新匯入。
  • 否:剪輯或粗剪影片(那是 rough-cut 的功能)、翻譯、重新同步原本正確的字幕檔、.srt/.vtt 字幕(此處的格式是 Premiere 的原生 JSON)。

預期輸入

  1. 從 Premiere 匯出的影片(.mp4/.mov):包含要轉錄的音訊。
  2. 從 Premiere 匯出的字幕 .json 檔案:提供要複製的目標格式(鍵值、speaker UUID、語言)。
  3. 影片的參考腳本,任何可讀取的格式皆可(純文字、Markdown、Google 文件、Notion 頁面、貼上的文字):這是專有名詞拼寫的權威來源(人物、作品、地點、品牌)。如果沒有,請索取,或者只修正明顯的錯字,並對任何不確定的名稱保留 whisper 的拼寫。

語言

排版(標點符號周圍的間距)、帶重音符號的字母、標點符號集、引號和拼寫標準化都存在於 languages/<code>.json 檔案中(內建 fr 和 en),絕不寫在程式碼中。語言透過 --lang <code> 選擇,否則使用 Premiere JSON 的語言,再否則使用 whisper 轉錄記錄的語言,最後預設為 en。檔案運作方式及如何新增語言:請參閱 ../rough-cut/references/languages.md(機制相同;此技能有自己的 languages/ 資料夾)。

需求(每台機器僅需設定一次)

whisper-cli + ffmpeg + 模型 ~/Models/whisper/ggml-large-v3-turbo.bin。請參閱 ../rough-cut/references/whisper-setup.md(共享設定)。檢查:which whisper-cli ffmpeg && ls ~/Models/whisper/。

強制對齊(將時間戳記重新對齊到音訊上,步驟 6b):

pip3 install --break-system-packages ctc-forced-aligner torch torchaudio unidecode

首次執行時會下載一個約 1.2 GB 的 ONNX 模型(快取目錄 ~/ctc_forced_aligner/)。檢查:python3 -c "import ctc_forced_aligner"。


工作流程

以下的 scripts/... 指令假設你位於技能資料夾中。工作目錄可在兩次 shell 呼叫之間重設:可以一次 cd 進入技能資料夾,或者為每個腳本加上絕對路徑。工作檔案(音訊、轉錄、修正)應放在任何同步資料夾之外的暫存資料夾中。

1. 檢查影片與輸入格式

首先:備份原始檔案。 Premiere 可能會在重新匯出時改寫輸入的 .json 檔案,而它是驗證步驟 7 時間的唯一同步真相:

cp "<Reel.json>" /tmp/subs_original_premiere.json
ffprobe -v error -show_entries format=duration:stream=codec_type,r_frame_rate \
  -of default=noprint_wrappers=1 "<video>"

記下持續時間(最後一個字必須落在持續時間內)和 fps。然後檢查輸入的 Premiere JSON 以確認格式:

python3 scripts/inspect_format.py "<Reel.json>"

它會列印出頂層/區段/字詞的鍵值、speaker UUID、語言、區段數量,以及逐區段的當前文字(= 要修正的錯字列表)。預期格式記錄在 references/premiere-format.md 中:如果檢查結果顯示不常見的鍵值,請閱讀該文件。

2. 在本機轉錄(whisper.cpp)

python3 scripts/extract_audio.py "<video>" /tmp/subs_audio.wav
python3 scripts/transcribe.py /tmp/subs_audio.wav /tmp/subs_transcript.json --model large-v3-turbo --language <code>

在 Apple Silicon 上,3 分鐘的影片約需 8 秒。轉錄結果包含帶有 text(已加標點、區分大小寫)和時間戳記 words 的區段。

2b. 如果 whisper 未加標點(連續輸出):重新加標點

在快速獨白中,whisper 有時會回傳一個沒有標點且沒有大寫的串流(區段在句子中間斷開,沒有 ./,)。明顯症狀:build_subs.py 報告 eos: 0。沒有標點的字幕無法閱讀。快速檢查:python3 scripts/words_of.py /tmp/subs_transcript.json 0 1 2 --plain。

如果是這種情況,請自行重新加標點(這是 LLM 的工作,不是 whisper 的):重寫每個區段的 text,加上標點和句子開頭大寫,保持 whisper 的字詞完全不變:只加入標點和大小寫;詞彙修正(名稱、縮寫)留在 corrections.json 中。標點符號永遠附加在單字上(so?,而不是 so ?):前面有空格的符號會變成一個獨立的 token,而對齊程式會默默地丟棄它(曾經有 114 個 ?/! 一次全部遺失)。build_subs.py 會自行套用語言對應的間距(法文是無間斷空格)。將結果放入一個 JSON {index: "標點文字"} 中,然後:

python3 scripts/repunctuate.py --transcript /tmp/subs_transcript.json --punct /tmp/punct.json --output /tmp/subs_transcript_punct.json

該腳本會拒絕你新增、刪除或更改任何字詞(它會顯示差異):這樣才能保持字詞與時間的對齊不變。注意區段之間的流暢度:延續句子的區段以小寫開頭,開始新句子的區段以大寫開頭。在後續步驟中使用這個已加標點的轉錄結果(步驟 6 中的 --transcript)。

另外,刪除任何結尾幻覺:在最後的寂靜中,whisper 經常編造一行字幕,例如“Thanks for watching”(每種語言的典型行數列在其 languages/<code>.json 檔案的 whisper_hallucinations 中)。使用 seq_rule N 到 0 將其刪除。另一種幻覺:連續且文字相同的區段,其字詞的持續時間接近零(start==end),是在寂靜中重複發明的句子(例如“here we go”三次)。偵測方式:區段 i 和 i+1 文字相同且字詞持續時間為 0。修正:在建立字幕前從轉錄結果中刪除它們(del segs[i:j])。

3. 閱讀 whisper 轉錄結果與參考腳本

逐區段列印轉錄結果(text),並與步驟 1 中輸入的 Premiere 文字進行比較。whisper 已經修正了很多,但名稱上的錯字仍然存在。閱讀參考腳本以取得專有名詞及其引用的作品名稱的規範拼寫。

4. 建立 corrections.json(智慧核心)

這是決定品質的關鍵。透過將 whisper 聽到的內容與腳本中的名稱進行比較來建立修正檔案。檢查受影響區段的逐字分割,以編寫精確的規則:

python3 scripts/words_of.py /tmp/subs_transcript.json 2 9 38   # 要檢查的區段的索引 token

輸出會索引每個字詞(9:Smyth 10:Jones):這讓你可以編寫精確的規則,而無需猜測 tokenization(名稱佔多少個 token、是否保留連字號等)。

corrections.json 的格式(所有鍵值皆為可選):

{
  "quote_char": "\"",
  "normalize_cotes": true,
  "seq_rules": [
    [["jon","smyth"], ["John","Smith"]],
    [["train","park"],    ["Trent","Parke"]],
    [["arthus","bertrand"], ["Arthus-Bertrand"]]
  ],
  "word_rules": {"macdum": "Magnum", "scholler": "Schoeller"},
  "titles": [
    {"match": ["the","decisive","moment"], "canonical": ["The","Decisive","Moment"]},
    {"match": ["errance"], "canonical": ["Errance"], "sep_comma": true}
  ]
}
  • seq_rules:多字名稱,或 1 對 N / N 對 1。比對時會將字詞轉換為小寫,並去除標點。用於任何跨越 whisper 2 個以上字詞的名稱,或字詞數量發生變化的情況。大小寫:目標字詞會逐字使用:寫上你想要的最終大小寫,包含在句子中的位置(如果單字開頭句子,使用 ["Today","we",...],而不是 ["today",...])。相同長度來源/目標:標點符號(內部逗號)和時間會按索引保留;不同長度:時間會重新分配,且只有第一個/最後一個字詞的標點會保留(被取代字詞的內部逗號會遺失:請在步驟 7 中重新閱讀這些區段)。刪除:空的目標 [["uh"], []] 會移除該字詞(保留給 whisper 重複的真正孤立噪音;對於轉錄錯誤的字詞,請修正而不是刪除,否則你可能會遺失部分句子)。
  • word_rules:一個字的名稱,強制大小寫(小寫鍵值對應到確切值)。
  • titles:被引用的作品(書籍、影集、有標題的照片)會自動加上引號(開頭在第一個字,結尾在最後一個字),加上一個 canonical 用於標題的正確大小寫。sep_comma: true 會在標題後加上逗號(當多個標題連續出現時很有用)。將作品放在引號中,而不是人名或品牌名。
  • normalize_cotes:套用語言檔案的拼寫標準化(normalize_words),用於 whisper 不一致書寫的變體。除非你設定,否則預設關閉。
  • french_typography:語言排版間距的開關(名稱是歷史因素;它適用於任何正在使用的語言)。預設值取自語言檔案:法文在雙標點符號和閉引號前使用無間斷空格(U+00A0),並在開引號後使用;英文則無。僅在你想使用附著標點時設定為 false。當你在步驟 2b 重新加標點時,標點必須附著(Flop:);build_subs.py 會自行套用間距。

5. 與使用者共同解決不確定之處(絕不自行猜測)

whisper 有時會產生一個含糊不清或難以理解的非名稱字詞。不要默默地猜測。 列出這些問題及其時間碼,並詢問使用者實際說了什麼,如果上下文或腳本有提示,可以提供一個假設。區分:

  • 直接修正:由腳本確認的專有名詞;明顯且確定的錯字。
  • 先詢問:含糊不清的非名稱字詞,或任何改變含義的修正(例如 whisper 聽成“who feels”而腳本是“without”:意義相反,即使腳本能解決也要標記)。

不要改寫口語風格(俚語、填充詞、重複):字幕必須跟隨音訊。

等待回答時在檔案中寫入什麼(你無需阻止生成):產生一個套用所有安全修正的第一版,加上你對常見含糊字詞的最佳假設(並標記它們),但對於腳本中未出現的不確定名稱,保留 whisper 的原始拼寫:絕不發明專有名詞。交付該版本以及需要驗證的項目列表(時間碼),然後在更新 corrections.json 後重新生成。這就是正常流程:生成、附帶問題呈現、精煉。

6. 產生修正後的檔案

python3 scripts/build_subs.py \
  --transcript /tmp/subs_transcript.json \
  --original "<Reel.json>" \
  --corrections /tmp/corrections.json \
  --output "<folder>/<name>_corrige.json" [--lang <code>]

該腳本會複製原始檔案的格式(speaker UUID、語言、排序鍵值、壓縮的 UTF-8)、恢復標點和大小寫、套用修正、加入引號、重新計算 eos,並列印一個驗證報告。

將 <name>_corrige.json 寫在原始檔案旁邊,切勿覆蓋原始匯出檔案(這是使用者的來源)。_corrige 後綴是腳本依賴的檔案名稱:請保留它。

6a. 檢查 build_subs.py 的 2 個常見陷阱(每次都檢查)

在許多影片中都見過兩個錯誤,每次建置後都必須檢查:

  1. 小數點重複。whisper 將 6.6 拆成 2 個 token(6 + .6;同樣地 1,33,或 4 AM 拆成 4 + AM);標點重新注入會使它們在輸出中重複(1.4 .4、6.6. .6),並且 seq_rules 比對錯誤(標準化不會去除內部的 ./,)。偵測:使用模式 \d[.,]?\s+[.,]\d 在最終輸出中搜尋。修正:在建置前對轉錄結果進行手術:將 2 個 token 合併為一個({'text':'1.4','start':a.start,'end':b.end,...};whisper 單字架構 = text/start/end/confidence,而非 duration),然後重新建置。
  2. 孤立句尾標點被刪除。存在於 whisper 區段 text 中但沒有自己 token 的 ?/!/: 會消失(How did we do it ? 失去其 ?)。偵測:比較 whisper 文字和輸出中 count('?')(以及 !、:)的數量。修正:直接編輯輸出 JSON:將 ?(使用語言的間距)重新附加到前一個 token。

如果偵測到陷阱 1,請修正轉錄結果並重新建置(步驟 6)。如果是陷阱 2,請直接修補輸出。

6b. 將時間對齊到音訊上:強制對齊(每次都要做)

whisper 的字詞時間會漂移(在快速、多段獨白中測量到最多早 7 秒,非線性):whisper 壓縮了各段之間的靜音,因此聲音在字幕之後才出現。典型抱怨:"當『Ah』出現時,我已經聽到下一句了"。DTW (-dtw) 沒有任何改變(相同的偏移),而在稀疏錨點上進行時間扭曲會扭曲原本已經正確的區域。whisper 的文字是好的,只有其時間是錯誤的,導致字幕與音訊不同步。強制對齊(CTC Forced Aligner)解決了這個問題。

python3 scripts/realign_timings.py \
  --transcript /tmp/subs_transcript.json \
  --audio /tmp/subs_audio.wav \
  --corrections /tmp/corrections.json \
  --output /tmp/subs_aligned.json \
  --language <code>  # 與步驟 2 相同的語言

該腳本會執行強制對齊,並將修正後的字幕時間戳記寫入 /tmp/subs_aligned.json。這個檔案現在已經準備好,可以在下一步驟中用於建置最終的 Premiere JSON。

7. 匯入前的最終驗證

python3 scripts/validate_timings.py \
  --original /tmp/subs_original_premiere.json \
  --corrected "<folder>/<name>_corrige.json" \
  --transcript /tmp/subs_aligned.json

此腳本會比較原始時間與修正後時間,確保所有字詞都落在影片持續時間內,並檢查是否有任何異常(例如時間倒退、重疊、大量漂移)。它也會輸出一個簡短的摘要,方便你或使用者進行視覺確認。

最後,在 Premiere Pro 中匯入 <name>_corrige.json:

  1. 將 <name>_corrige.json 複製到 Premiere 專案資料夾中。
  2. 在 Premiere 中,選擇「檔案 > 匯入」並選取該 JSON 檔案。
  3. 它會像原始檔案一樣作為字幕軌道匯入,但現在帶有修正後的文字和對齊的時間。
  4. 如果出現任何錯誤,請檢查 validate_timings.py 的輸出,並重新開始流程。

參考資料

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相關技能