A-roll 處理
目標:將一個長錄影或多個相同腳本的錄影,轉換成由每個台詞的最佳 take 所建構的緊湊粗剪。語音直接銜接語音,每個字詞都完整,剪輯聽起來就像一次乾淨的 take,而且是第一次就成功。
此技能專為 Claude Code 和 Runneth 設計。它需要:
- ffmpeg 來測量音訊、擷取靜態畫格和剪輯影片。
- 所有說話內容的字詞時間戳: 一個能提供每個字詞時間的語音轉文字工具(Whisper、faster-whisper、whisper.cpp)。
- 評判畫面的方法: 請參閱下方的「如何評判一個 take」。
- 檢查腳本 位於
scripts/cut_check.py(需要 python3 加上 numpy 和 ffmpeg)。
用簡單日常的語言與剪輯師溝通,一次只講一個重點。
開始之前:工具
在 Runneth 中,所有東西都已安裝:請跳過此章節。
在 Claude Code 中,此技能需要 video-editing-setup 技能所安裝的免費影片工具。請低調檢查 ~/.video-editing-tools/bin/ffmpeg -version 是否可執行。如果可以,請在此技能提到 ffmpeg、ffprobe 或 python3 的地方,使用 ~/.video-editing-tools/bin 中的工具(ffmpeg、ffprobe、python),然後繼續。如果不行,請先遵循 video-editing-setup 技能,然後再回到這裡。
步驟 0:開始任何工作前的兩個快速檢查
-
檔案是剪輯師想處理的那個。 如果他們說這是重拍或新片段,但它與先前的片段長度或場景相同,請在開始前用一句話詢問。
-
準確地問這個問題,作為一個有兩個選項的問題:
「您要我先把我要保留的 take 給您看,還是直接進行剪輯?」
- 先給我看 → 遵循以下每個步驟,並在步驟 4 停止,等待剪輯師確認。
- 直接剪輯 → 從頭到尾執行所有步驟,不要停止。最後一次說明您不確定的任何事項。
如果剪輯師已經說過要哪個選項(例如「直接剪」、「先把 take 給我看」),則跳過此問題。如果沒有人可以回答,則視為「直接剪輯」。
步驟 1:取得文字
- 使用
ffprobe檢查每個錄影的長度、方向和影格率。當有多個錄影時,為每個錄影指定一個簡單的標籤(影片 A、影片 B、影片 C),並對所有錄影執行以下每個步驟。 - 從每個錄影中抽取音訊:
ffmpeg -i IN.mov -vn -ac 1 -ar 16000 audio.wav。 - 標記每個說話段落:
ffmpeg -i audio.wav -af silencedetect=n=-35dB:d=0.3 -f null -。靜音之間的段落就是語音島。每個字詞都存在於某個語音島內,而且這些島比任何文字稿的時間都更準確。 - 使用帶有字詞時間戳的語音轉文字工具進行轉錄。使用 faster-whisper 時:model 設為
base、word_timestamps=True、condition_on_previous_text=False,以及一個initial_prompt,列出影片中可能出現的名字和品牌詞。較大的純英文模型會默默地清理重啟(restarts),這會隱藏此技能需要看到的假開頭(false starts)。 - 在長段落中,文字稿可能會漂移或跳過。每個語音島都需要有字詞。當一個語音島沒有字詞,或字詞似乎遺漏在靜音之間時,請重新轉錄該段落:將視窗從語音島前約 1 秒開始,到語音島後約 1 秒結束,並關閉任何語音過濾器(
vad_filter=False)。 - 短的重新轉錄視窗可能會在結尾憑空產生未被說出的字詞(例如「非常感謝」、「感謝觀看」)。僅保留那些落在語音島內且符合台詞的字詞;堆疊在同一時間戳的字詞是憑空產生的。
- 修正名字和品牌詞的明顯誤聽。如果有腳本,請將其用作台詞的地圖;如果沒有,則文字稿就是地圖。
步驟 2:將 take 分組
- 將 footage 分割成台詞(每個句子或想法),並將每個台詞的所有嘗試(attempt)分組,跨越多個錄影。多個相同腳本的錄影是一個 take 池:例如,台詞 1 會得到來自影片 A、B、C 的所有 take 1,並排在一起,每個 take 都會標記其錄影來源(例如「影片 B,take 3」)。嘗試通常以相同的幾個字詞開頭。
- 一個 take 從一次嘗試的開始,到其最後一個字詞結束,然後才開始下一次嘗試。
- 將每個 take 標記為完整(說完整句台詞)或假開頭(中途停止)。
- 台詞內的每個短語都視為獨立的片段。一個台詞可以由不同 take 的最佳片段組合而成(例如,第一句來自 take 4,第二句來自 take 2),這也包括來自假開頭的乾淨片段。
步驟 3:評判每個 take
每個台詞的每個 take 都要被評判,包括只說了一次的台詞。每個短語的最佳版本勝出,無論它來自哪個 take 或順序。當短語之間的接合處乾淨時(請參閱下方的規則 7),從這些最佳片段構建每個台詞。使用下方的「如何決定一個 take 是否被保留」,並在 take 檔案(模板:templates/takes.md)中為每個 take 寫一行:台詞、take、時間、你看到的、保留與否,以及簡短原因。
如何評判一個 take
評判的內容在兩種情況下都相同。如何看到它則取決於工具:
- 在 Runneth 中(或任何可以將影片發送給能觀看影片的模型(如 Gemini)的設定):讓該模型觀看每個錄影,並根據「什麼讓一個 take 成為保留的 take」以及語氣、重點、笑話時機和猶豫來評判每個重複的台詞。將您自己的選擇與發送給模型的內容分開,使兩次讀取保持獨立。當模型選了一個與您不同的 take 時,採用模型的選擇。始終從文字稿和語音島獲取時間,絕不從影片模型獲取:其時間戳會漂移,有時會跳過台詞。
- 在 Claude 中,它無法觀看影片,因此根據三件它可以自行檢查的事情來評判:
- 台詞(文字稿):完整的台詞,沒有結巴、沒有填充詞、沒有中途重啟。
- 聲音(對每個 take 使用
astats):穩定的音量,沒有削波、沒有爆音或噪音爆發。 - 畫面(靜態畫格):每個重複台詞一張工作表,每個 take 堆疊在一起,每秒 2 個畫格:對每個 take 使用
ffmpeg -nostdin -ss START -t LENGTH -i IN.mov -vf fps=2,scale=160:-2,tile=10xN take.jpg,然後將所有 take 的圖片堆疊成一張圖片。查看工作表中的所有內容,參考「什麼讓一個 take 成為保留的 take」。
- 帶有聲音的螢幕錄影: 評判台詞、聲音,以及指向或點擊的動作是否與所說的內容相符。
步驟 4:顯示選取的 take(僅當編輯要求先看時)
- 顯示剪輯清單:每個保留的片段一行,包含
start-end和確切的保留文字。在接近的選擇行上標示「(接近選擇:take 2 也一樣乾淨)」,以便編輯知道要檢查哪裡;明確的選擇則沒有註解。僅在有任何阻礙剪輯的事情(例如無法辨識的字詞)時,在結尾添加一行簡短說明。 - 編輯會批准、替換一個 take(例如「台詞 4 使用 take 2」)或刪除一行台詞。他們的變更具有決定性,即使影片模型後來不同意。當他們替換時,如果他們沒有說明原因,請用一個簡短的問題詢問原因。他們的原因是技能學習的依據(步驟 7)。
步驟 5:建構剪輯
剪輯非常緊湊:語音到處都直接銜接語音,包括在保留的 take 內部。思考停頓和短語之間的呼吸聲會被剪掉。唯一保留的停頓是最後一個畫格上的約 0.5 秒。
- 邊界來自語音島,而不是文字稿。每個保留的片段從其語音島的第一個聲音開始,到其最後一個聲音結束。第一個字詞之前的呼吸聲、咂嘴聲和操作噪音可能會超過 -30dB 並被縫合到語音島中,因此片段應從第一個字詞的起始點開始(音量上升到語音水準的位置,通常為 -25dB 或更大),而不是從第一個小雜音開始。片段開頭或結尾的任何呼吸或噪音段落都會被剪掉。結尾則反過來運作:一句台詞通常會安靜地結束(例如輕聲說「在晚上睡著」),因此片段應在其最後一個字詞之後結束,即使該字詞比其他字詞安靜。檢查剪輯的文字稿中是否包含每句台詞的最後一個字詞。
- 保留 take 內部的停頓 會用更敏感的參數找到,使用
silencedetect=n=-30dB:d=0.2,所有 0.25 秒或更長的停頓都會被剪掉。take 內部的重啟和重複字詞也會被剪掉,只保留乾淨的最終措辭。 - 每個片段在兩側各填充約 0.05 秒。 填充太多會留下停頓;填充太少則會切到字詞。然後將每個邊界對齊到完整的畫格(開始時間向下取整到前一個畫格,結束時間向上取整到後一個畫格)。邊界落在畫格之間會導致接合處重複或丟失畫格,這會使之後的每個剪輯點移動一到兩個畫格,並在將 B-roll 放置在剪輯點上時讓雜散畫格通過。
- 短於約 0.3 秒的片段幾乎都是剩餘物(一個雜散的音節)。除非它包含一個完整的字詞,否則予以丟棄。
- 在每個接合處添加 20 毫秒的音訊淡入淡出,並從工作副本中以一次重新編碼連接所有內容。原始檔案保持不變。
- 將片段清單(
[[start, end], ...],以秒為單位)儲存為clips.json;檢查腳本會讀取它。
步驟 6:在編輯看到剪輯之前進行檢查
編輯看到的每個版本都必須通過對該確切檔案進行的所有檢查。未執行的檢查視為失敗。
- 執行檢查腳本:
python3 scripts/cut_check.py --voice audio.wav --clips clips.json --out CUT.mp4。它會檢查三件事並列印RESULT PASS或FAIL:- 結尾: 每個片段的最後 50 毫秒低於語音水準(-30dB)。如果不是,表示有一個字詞被切斷:將該結束時間向後移動,直到音量下降。
- 開頭: 每個片段開始前的 30 毫秒是安靜的,因此沒有片段從字詞中間開始。
- 間隙: 剪輯中除了最後的保留停頓外,沒有任何地方有 0.25 秒或更長的停頓。
如果有多個錄影,則對每個錄影執行一次:使用該錄影的音訊作為
--voice,並僅在clips.json中包含該錄影的片段,每次使用相同的剪輯作為--out。 如果聲音來自與畫面不同的檔案(例如獨立麥克風),則還要用相同的修剪方式剪輯攝影機自己的音訊,並將其作為--camlock傳遞,以便腳本也檢查同步(每 3 秒內在 40 毫秒以內)。
- 每個字詞都完整,且只出現一次: 使用字詞時間戳轉錄剪輯,並逐字與剪輯清單進行比較。接合處出現半個字詞表示邊界太緊。接合處出現重複的字詞或短語表示有殘留的重啟。 字詞之間沒有死寂: 在該文字稿中,一個字詞結束到下一個字詞開始之間的任何間隙不得長於約 0.3 秒(最後的保留停頓除外)。腳本中的間隙檢查只能找到安靜的停頓;充滿呼吸聲的停頓音量夠大,可以通過檢查,因此這個字詞間隙檢查才能捕捉到它。將片段修剪到其第一個字詞,然後重新執行所有檢查。
- 每個接合處,逐一檢查: 對於每個剪輯點,說出它前一個字詞和後一個字詞,並確認兩者都已完整說出。轉錄每個接合點前後 2 秒的視窗來檢查(一個籠統的「有任何問題嗎?」會讓被切斷的字詞漏掉)。在 Runneth 中,也讓影片模型像挑剔的初次觀看者一樣觀看剪輯,並列出問題及其時間:被剪掉或遺漏的字詞、畫面瑕疵、凍結畫格、突兀的跳躍。
- 長度: 剪輯的長度必須與剪輯清單的總長度相符。
修復所有失敗的地方,再次剪輯並重新執行所有檢查。
步驟 7:從編輯那裡學習
每當編輯替換一個 take、更改邊界或說明為什麼某個 take 更好時,將該原因轉化為一個通用規則,並將其合併到下方的「什麼讓一個 take 成為保留的 take」中(或者如果是關於剪輯緊湊度的規則,則合併到步驟 5 中)。保持清單簡短:重寫和合併規則,而不是堆疊新的規則。只有編輯的原因會改變規則。
什麼讓一個 take 成為保留的 take
這些規則來自一位編輯對她自己的 talking-head 影片的真實選擇。按順序應用它們,然後隨著您的編輯的意見到來,用您自己的編輯規則替換它們。
- 整句台詞,說得乾淨利落。 一個有結巴或遺漏字詞的 take,無論其畫面多好,都會輸給一個乾淨的 take。
- 沒有東西遮住臉。 手或麥克風放在嘴前會使 take 被淘汰。
- 活力。 手勢、動作和生動的表現勝過靜止、平淡的朗讀。
- 最快樂的臉。 在兩個乾淨的 take 之間,真誠的微笑和明亮的眼神勝出。
- 臉與台詞相符。 在笑點上睜大眼睛,在快樂的台詞上真誠微笑。
- 自然、平穩的節奏。 不急促,沒有長時間的停頓。
- 最佳片段,乾淨地接合。 最佳 take 無論來自哪個錄影都會勝出,而由兩個 take 的部分組成的台詞,當每個部分都是更好的版本時,會勝過一個完整的 take。當說話者的頭部和手勢在接合處兩側大致位於相同位置時(檢查接合處前後的畫格),或者當接合處稍後會被 B-roll 覆蓋時,接合就是乾淨的。錄影之間的切換還需要在兩側具有相同的外觀(頭髮、光線、構圖、手中的產品);當外觀改變時,切換應落在台詞之間,並由 B-roll 或變焦變化覆蓋。
- 更簡短,但力道更強。 當台詞的其餘部分重複了已經說過的話或拖慢了影片速度時,將其剪到最有力的部分(例如用「直到我用完」代替「我沒意識到它在幫助我,直到我用完」)。
- 接近的選擇保持為接近的選擇。 當兩個 take 同樣乾淨且畫格顯示沒有真正差異時,選擇一個並將其標記為接近的選擇。靜態畫格無法顯示語調,所以不要假裝其中一個明顯更好。
每個剪輯的規則
- 剪輯中的每個字詞都來自音訊。無法辨識的字詞標記為不清楚,絕不猜測。
- 時間來自原始錄影的時間軸,剪輯清單中的每個片段都標記其錄影來源。
- AI 時間是接近的,而不是精確的。每個邊界都根據語音島設定,並在音訊中檢查。