rough-cut:Premiere Pro 自動粗略剪輯
一次性設定:請參閱根目錄下的 INSTALL.md。使用外掛時,設定指令行為
bash "${CLAUDE_PLUGIN_ROOT}/install.sh" --data "${CLAUDE_PLUGIN_DATA}";手動安裝時(將四個 skills/ 資料夾並排複製到 ~/.claude/skills/),從根目錄執行 bash install.sh。腳本位於此技能的 scripts/ 資料夾中。
範圍
- 是:Final Cut Pro 7 XML (XMEML,
.xml) 時間軸,已移除重拍、虛假開頭、結巴、填充詞和長時間靜音;一份 Markdown 報告;在待決定事項上標註紅色標記。 - 否:修改片段、轉碼、匯出影片、調色、混音,或在明顯的重新措辭之外選擇兩個版本(這是剪輯師的職責)。
核心規則:原始片段絕不修改
此技能只會在片段旁寫入:
<片段>_Derush_v1.xml:要匯入的剪輯 (FCP7 / XMEML);<片段>_Derush_v1.report.md,<片段>_Derush_v1.log.txt;<片段>_Derush_v1_work/:工作資料夾,保留(逐字稿、中間剪輯)。
XML 使用絕對路徑 (file://localhost/...) 指向片段:Premiere 僅參考它。新的一次執行會建立 v2、v3...,而不會覆蓋任何內容。
使用者操作(3 步驟)
- 在 Premiere 中:匯入片段,執行逐字稿(文字面板 > 轉錄),儲存專案。逐字稿隨後會存在
.prproj中:切勿要求使用者匯出它。 - 提供 Claude 片段的路徑,以及影片的參考腳本(如果有的話,可以是純文字、Markdown、Google 文件、Notion 頁面等任何可讀格式)。腳本僅用於判斷重複是否為刻意為之。若無腳本,仍可執行;但刻意重複會變成標記而非剪輯。
- 匯入
.xml(File > Import)。會出現一個Derush_vN序列,已經編輯完成:剪輯的片段已從時間軸消失(片段端對端相接,無需閉合間隙),而存疑的片段會以紅色標記保持為啟用片段。
無需詢問其他事項:語言、片段類型和選項會自動推斷(見下文),僅在片段類型確實不明確時才值得提問。
語言
所有與語言相關的內容(填充詞、虛假開頭詞組、拍板模式、孤立連接詞、應剪掉的開場白、Whisper 幻覺、標記的原因文字)都存放在 languages/<code>.json 中,而非程式碼中。內建法文 (fr) 和英文 (en)。語言透過 --lang <code> 選擇,否則使用逐字稿中記錄的語言,再否則使用 en。詳細資訊及如何新增語言:references/languages.md。
管道 v2:版本選擇(正常路線)
僅偵測缺陷(v1,如下)的召回率約為 57%,因為 Whisper 會默默對重複版本進行去重:其反循環解碼器會將逐字重複的句子視為幻覺,並只轉錄一次。這無法透過設定修正。Premiere 的逐字稿會保留每個版本,逐字記錄,且其單詞起始點在長時間靜音後不會漂移(Whisper 會)。因此:
| 步驟 | 工具 | 角色 |
|---|---|---|
| 1 | extract_prproj_transcript.py project.prproj words_premiere.json [--rush CLIP.MOV] | .prproj 轉換成 words_premiere.json(主要來源)。若專案無逐字稿,則回傳代碼 2:要求使用者執行並儲存專案。備援:在手動 JSON 匯出上使用 parse_premiere_transcript.py |
| 2 | extract_audio.py + transcribe.py | whisper 作為第二意見(交叉檢查文字,絕非時間邊界) |
| 2b | calibrate_premiere_times.py | 重新對齊 Premiere 逐字稿與音訊。每次粗略剪輯後立即執行(若逐字稿時間正確,它不會動任何東西)。透過互相關逐視窗測量偏移;已見過在 21 分鐘片段末尾有 1.8 秒漂移。若忘記執行,症狀為:silence_cuts.py 報告數十個「可疑噪音」 |
| 3 | Claude 上下文 | 語義分析:透過比較 Premiere 的逐字稿與腳本及 Whisper 結果,找出重拍、虛假開頭和結巴。規則如下 |
| 4 | silence_cuts.py | Premiere 單詞之間 >= 1.0 秒的靜音,單詞結尾重新對齊到音量水準,列舉防護(兩個短區塊之間的短暫停頓 = 刻意節奏),噪音區域:標記或剪輯(見下文)。預設值已根據完成的剪輯校準:未重新測量前請勿更改(參見 references/lessons.md,「Measuring」) |
| 5 | apply_takes.py <work> | 步驟 3 決定的版本會寫入 takes.json(單詞索引;可選的手動邊界或剪輯時間(秒))。腳本會將邊界放在音量低谷,與靜音合併,合併兩個剪輯之間留下的靜默片段,將每個剪輯邊緣重新對齊到真實聲音,並標記剪輯邊緣處小於 0.25 秒的孤立聲音,寫入 cuts_final.json。protect(保留靜音)僅在使用者要求時執行 |
| 6 | build_premiere_xml.py | XMEML。選項 meta["audio_file"]:將音訊指向一個全長度的已處理 WAV(參見已知限制)。多個片段:每個片段一個 XML,然後 merge_xml.py output.xml "name" a.xml b.xml = 一個端對端的單一序列 |
| 6b | 重新轉錄剪輯 | 端對端檢查:串聯 audio.wav 中保留的區間,在其上執行 whisper,並使用剪輯點讀取文字。能捕獲其他檢查遺漏的問題:剪輯中殘留的靜音(一個 8 秒片段只說 3 個字)、被截斷的單詞、殘存的失敗版本 |
| 7 | qc_repeat_scan.py | 確定性檢查:若剪輯中殘存 30 秒內重複的 5-gram,或在暫停或剪輯後出現的某兩個單詞已在少於 8 秒的剪輯時間內說過(帶變體的重複版本),則回傳代碼 2。每個命中都會與腳本進行比對,並透過聽覺 (hear.py) 檢查:殘存的重拍(保留最後一個)或刻意修辭(頭韻、列舉) |
| 7b | montage_qc.py <work> | 剪輯的音訊會被轉錄並逐片段讀取,比較 Premiere 單詞 (P) 與 Whisper 單詞 (W):若空白時間 > 1.6 秒或片段 < 1 秒,則回傳代碼 2。可疑邊緣會使用 hear.py audio.wav 12.3-14.0 ...(在孤立切片上使用 Whisper)進行檢查 |
| 8 | report_v2.py | 報告:剪輯時長和片段時長、版本、疑點;--notes 用於「刻意保留」以及觸及腳本敏感點的部分 |
步驟 3,決策規則
硬規則:
- 重複文字:保留最後一個版本(即使它不如較早的版本乾淨);
- 結巴:保留最長的連續片段;
- 疑點:
flag,絕不disable。少剪總比多剪好:添加剪輯很容易,恢復錯失的段落則非常困難。 - 剪輯邊界對齊 Premiere 單詞,保留的第一個單詞前有大約 0.15 秒的留白。
從真實剪輯中學到的規則:
- 任何夾在兩個版本剪輯之間、少於 2 秒的孤立片段都需要聽取 (
hear.py)。這幾乎總是虛假開頭。切勿僅根據 Premiere 的文字進行判斷:呼吸聲可能承載單詞(在 Premiere 中),而「Thanks for watching」這類 Whisper 幻覺則意味著根本沒有單詞。 - 帶有噪音的靜音,且非腳本中的句子(如旁白、「開始了」、調整相機)會直接被剪掉,而非標記。
- 句子開頭的填充開場白(語言檔案中的
openers列表,例如「So,」或「Well,」)會被剪掉。 - 句子內部的逐字口吃(如「It's it's」)會被禁用。但一個名字在句號前後重複(如「less documented than Nikon. Nikon has plenty of docs」)則不是口吃:Premiere 可能會將其記錄為雙重。在對任何單一單詞進行剪輯前,請使用
hear.py聽取該切片。 - 孤立連接詞(在剪輯靜音前的孤立「And / So / But」)會被包含在剪輯中。同樣地,任何夾在剪輯和暫停之間、後接另一個開始的孤立虛假開頭單詞也是如此。
- Premiere 逐字稿中有意義的詞語,但無對應的 Whisper 內容,且位於冗餘的旁白中,這是結巴:至少標記它。
- 不承載資訊的填充短語,且重複下一個句子:僅標記(這屬於編輯決定)。
- 「重拍」可能是前一句的結尾,被 Premiere 錯誤地標記日期(一個持續 5 秒的單詞)。剪輯的 Whisper 文字會顯示這一點。
- Premiere 有時會將一個句子分成兩半:一個兩個單詞的「虛假開頭」可能是下一個句子的開頭。
- Premiere 會遺漏小的含糊單詞:剪掉一個重複的句子可能會留下一個孤立的引導詞。首先使用
hear.py聽取切片;然後手動設定邊界(takes.json中條目的第 6 個元素)。 - 單一個重複的單詞(如「the the」):邊界可能會吞掉前面的單詞,因為 Premiere 在同一口氣中為兩者都標記了日期。聆聽接合處(使用
ffmpeg atrim處理兩個保留的片段,然後使用hear.py)。 - 兩個片段之間的接縫:一起聽取片段 1 的結尾和片段 2 的開頭。一個在片段 1 結尾開始、在片段 2 開頭重複的句子,會從其第一個單詞開始被剪掉。
- 對著相機為剪輯師說的指示(如「這是給你的,在這裡放一些圖形」)會被視為指示而剪掉,並在報告中列出,因為它們說明了要插入圖形的位置。
- 剪掉一個版本後,聽取保留版本的開頭(當 Premiere 有兩個單詞時,第一個單詞可能被吃掉)。
Premiere 的逐字稿存在於 .prproj 中
.prproj 是一個 gzip 壓縮的 XML,包含一個區塊
<ExternallyProvidedTranscriptDocument><TranscriptData Encoding="base64">,其內容是一個 FlatBuffers 緩衝區。extract_prproj_transcript.py 解碼它:
Segment -> f0 i64 start_ticks, f3 vector<Word>, f4 string language
Word -> f0 i64 start_ticks, f1 i64 duration_ticks, f2 string text, f3 f32 confidence
Premiere ticks = 254016000000 per second
文字為空的項目是 Premiere 標記的暫停(其持續時間涵蓋整個無聲段)。腳本會丟棄它們;否則單詞之間的每個間隙都會是 0,silence_cuts.py 會找不到任何東西(症狀:「gaps > 1s: 0」且單詞長達 39 秒)。
一個專案中有多個片段:.prproj 為每個片段保留一個逐字稿。--rush NAME.MOV 會選擇符合片段時長的逐字稿(若無指定,則選擇最長的那個,並顯示警告)。它會比較最後一個單詞的起始點,允許 0.3% 時長的漂移。檢查不同片段的單詞數量是否不同。每個片段一個工作資料夾,然後執行 merge_xml.py。
此逐字稿的兩個陷阱:
- 它可能會相對於檔案漂移:步驟 2b。剪輯是以檔案時間(XML 讀取的時間)為準,因此單詞會被修正,而非反過來。
- 單詞持續時間可能會吞噬後續的靜音:靜音不再存在於單詞之間,也不會被剪掉。
silence_cuts.py會將這些單詞恢復到其實際結尾 (trim_overflow)。永遠不要相信 Premiere 的單詞結尾;只有起始點是可靠的。
更多陷阱(在靜音內標記日期的單詞、靜默片段、微小孤立片段):references/lessons.md。
版本剪輯邊界:位於單詞起始點最近的音量低谷,在保留單詞的開始前保留 0.12 秒的留白。使用單詞索引(而非秒數)來描述剪輯:它們能在重新對齊後存活。
v1 管道(如下)在沒有 Premiere 逐字稿時仍為備援方案(警告:逐字的重拍很可能會被遺漏)。
機器需求
啟動時檢查;若缺少任何項目,會指向 INSTALL.md(僅 whisper 部分則指向 references/whisper-setup.md)。
brew install whisper-cpp ffmpeg
mkdir -p ~/Models/whisper
curl -L -o ~/Models/whisper/ggml-large-v3-turbo.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin
Python 3 搭配 numpy(無其他需求)。無需 API 金鑰、無需帳戶,模型下載後所有操作皆在本地完成。
管道 v1(備援,8 階段)
由 scripts/derush.py 執行。每個階段會寫入 <片段>_Derush_vN_work/,位於片段旁,絕不刪除(可恢復與檢查)。
| # | 腳本 | 角色 |
|---|---|---|
| 1 | derush.py(入口點) | ffprobe 元資料,版本號碼 |
| 2 | extract_audio.py | ffmpeg 轉換為 audio.wav 16 kHz 單聲道 |
| 3 | transcribe.py | whisper.cpp 轉換為 transcript.json |
| 4 | mechanical_cuts.py | 語言檔案的單詞列表和模式,轉換為 cuts_mechanical.json |
| 5 | 語義分析 (Claude) | 轉換為 cuts_semantic.json(見下文) |
| 6 | merge_cuts.py | 合併、對齊單詞、評分,轉換為 cuts_final.json |
| 7 | build_premiere_xml.py | 轉換為 .xml (XMEML / FCP7) |
| 8 | build_report.py | 轉換為 .report.md |
階段 5:語義分析
腳本會寫入 prompt_semantic.txt 並停止。這是正常路線:執行此技能的 Claude 隨後執行以下操作。
- 完整讀取
prompt_semantic.txt; - 依照提示中的規則分析逐字稿;
- 將 JSON 寫入
cuts_semantic.json(路徑在提示中給出); - 恢復:
derush.py <片段> --resume-from=6 --work-dir=<work>。
如果 cuts_semantic.json 已存在,則跳過此階段。
三層級決策(此技能的理念)
每個提議的剪輯都有一個 0 到 1 之間的信心分數。
disable:該段落會從時間軸上移除,而非停用。build_spine_clips()透過減法建立序列:僅保留的區間留下來,端對端相接,於是序列時長等於所有保留區間的時長總和。這相當於已經應用了「漣漪刪除」。閾值:機械式剪輯 >= 0.85,語義剪輯 >= 0.92(LLM 經常超出其邊界)。flag(0.6 到 0.85):不剪輯。該段落會以啟用片段的形式保留,並在正確位置帶有一個紅色序列標記(「DOUBT <類型> (conf X): 原因」)。由使用者決定。ignore(< 0.6):不做任何事,避免淹沒時間軸。
絕不能顛倒這些語義。交付停用的、灰顯的片段讓使用者手動刪除,是將工作量轉嫁給使用者而非減少工作量:承諾的是可直接使用的序列。
剪輯類型
filler:填充詞(「um」、「uh」...)和句子起始的填充開場白。stumble:結巴、虛假開頭。retake:重拍(相同內容的不同版本)。silence:長時間靜音。noise:非語音噪音(咳嗽、調整相機、環境聲)。instruction:對剪輯師說的指示。slate:拍板(如「take 1」、「take 2」)。