Communitygithub.com

Developh/resolve-cut

在 DaVinci Resolve Studio 中完整編輯談話性影片(課程、訪談等):包含逐字稿、每個鏡頭的檔案、每段的最後完整錄製、影格精確的剪輯列表、根據腳本組建時間軸、使用預設渲染、品質檢查(音量、影格、重複字詞)及交付。請在任何 Resolve 腳本編寫、組裝、渲染、品質檢查或影片交付工作之前載入此技能。

resolve-cut 是什麼?

resolve-cut 是一個專門為 AI 助手(如 Claude Code)設計的技能,用於在 DaVinci Resolve Studio 中自動化談話性影片的端到端後製工作流程。它透過已儲存的腳本進行操作,而不是在每次對話中重新編寫組裝邏輯,這大幅減少了 token 消耗並確保操作的一致性。此技能支援 macOS 平台,需要 Resolve Studio 21.1.1 或更高版本以及 Python 環境,並提供從逐字稿生成、鏡頭評估、剪輯清單建立、時間軸組裝、渲染到最終品質檢查的完整流程。其核心優勢在於將創意決定權保留給人類(選擇保留哪些鏡頭),而 AI 則負責執行和測量(提供精確的幀數和時間碼數據)。技能包含一套精心設計的 Python 腳本(分別用於 Resolve 內部執行和外部媒體處理),並內建了從實際工作經驗中彙整的已知陷阱和解決方案,幫助使用者避免常見錯誤。

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

在你喜歡的 AI 中提問

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

說明文件

resolve-cut 是做什麼的?

你在 DaVinci Resolve Studio 中,透過已儲存的腳本(含參數)來組裝、渲染和檢查影片。你不會在每次對話中重新編寫組裝邏輯,而是呼叫腳本、讀取其回傳結果,並透過數字和影格來驗證輸出。最終的品味判斷仍保留給人類:由人決定保留什麼,你負責執行和測量。

$SKILL 代表此技能所在的資料夾(即此檔案所在位置)。scripts/resolve/ 中的腳本透過 run.py 在 Resolve 內部執行;scripts/media/ 中的腳本是使用 ffmpeg 的純 Python 腳本。每個腳本都有 --help 參數。

開始之前

  1. Resolve 是否回應:python3 "$SKILL/scripts/resolve/run.py" - '{}' <<< 'result = resolve.GetVersionString()'。 回傳碼 2 表示 Resolve 未開啟、是免費版,或偏好設定 > 系統 > 一般 > 使用外部腳本未設為「本機」。
  2. 確認 ffmpeg -version、python3 -c "import numpy, PIL" 和 ELEVENLABS_API_KEY(環境變數或 ./.env 檔案)。
  3. 如果專案有筆記檔案(VIDEO_NOTES.md 或類似名稱),請先閱讀:了解哪些內容已被批准或拒絕。不要要求修正同一個錯誤兩次。
  4. 工作資料夾:你產生的所有內容(逐字稿、檔案、影格、渲染檔)都應放在工作資料夾中,絕對不要放入原始素材資料夾。

工作流程

1. 逐字稿。 以逐字為單位的 JSON 檔案,每個片段一個: python3 "$SKILL/scripts/media/transcribe.py" <clips 資料夾> --out work/transcripts [--language por]。 逐字稿是所有工作的基礎:用於挑選鏡頭、在影格邊界精確剪輯,以及檢查最終混音。

2. 檔案。 將所有素材濃縮為一個緊湊的文字檔案,讀取一次即可: python3 "$SKILL/scripts/media/dossier.py" <clips 資料夾> --transcripts work/transcripts --out work/dossier.md [--sheets]。 它會列出每個句子及其時間碼,並在句子開頭與較早的句子相似時標記 «repeats C0076 20.2»(表示同一句的另一個嘗試)。對於有腳本的內容,保留每段的最後完整錄製;刪除猶豫、錯誤開頭和重複嘗試。僅在需要決定時才打開片段檢查: python3 "$SKILL/scripts/media/inspect_range.py" <clip> <t0> <t1> --words work/transcripts/<clip>.json(在一張圖片中顯示影格、波形和對應時間的字詞)。

3. 剪輯清單。 撰寫 work/plan.json,以順序列出所選的鏡頭 ({"Lesson 01 v1": [["01a", "C0081", 1.9, 12.6], ["01b", "C0083", 5.4, 23.8], ...]}:鏡頭、片段、開始時間、結束時間(以片段的秒數為單位)),然後: python3 "$SKILL/scripts/media/cut_list.py" work/plan.json work/transcripts <clips 資料夾> work/cuts.json。 剪輯點會對齊在字詞旁邊最安靜的影格邊界;超過 1 秒的停頓會被縮短;片段會交替縮放 1 倍 / 1.2 倍,使鏡頭切換時不會跳動。對於沒有間隙的錯誤開頭("co- contar"),可以透過 {"in_frame": N} 或 {"out_frame": N} 強制指定影格。給編輯的備註:add_markers.py。

4. 在 Resolve 中組裝。 每次呼叫執行一個重量級操作,並在進行下一次操作前讀取每個 result:

R="$SKILL/scripts/resolve/run.py"
python3 "$R" "$SKILL/scripts/resolve/project.py" '{"name": "Lesson 01", "width": 1920, "height": 1080, "fps": "25"}'
python3 "$R" "$SKILL/scripts/resolve/assemble.py" '{"phase": "import", "bin": "Raw", "media": "/abs/clips", "files": ["C0081.MP4"]}'
python3 "$R" "$SKILL/scripts/resolve/assemble.py" '{"phase": "timeline", "bin": "Raw", "cuts": "/abs/work/cuts.json", "timeline": "Lesson 01 v1", "zoom": {"center": [0.45, 0.37]}, "voice_isolation": 50}'

zoom.center 是臉部所在位置(影格比例),因此放大時臉部能保持在畫面中。檢查 frames == expected 且 failures 是否為空。

5. 渲染前檢查。 frames.py 能在不到一秒內從時間軸中導出影格 ({"timeline": "Lesson 01 v1", "frames": [100, 500], "folder": "/abs/work/frames", "max": 960})。檢查一張普通影格和一張放大影格。

6. 渲染。 python3 "$R" "$SKILL/scripts/resolve/render.py" '{"phase": "start", "timeline": "Lesson 01 v1", "folder": "/abs/out", "name": "lesson-01", "preset": "reel", "width": 1920, "height": 1080, "mark": [0, <frames - 1>]}', 然後每 10 秒輪詢 {"phase": "status", "job": "<id>"},直到 JobStatus 顯示為 Complete。等待渲染完成再回應:如果在「渲染已開始」時就結束對話,將無人檢查結果。

7. 驗證。 python3 "$SKILL/scripts/media/qc.py" out/lesson-01.mp4 --expected <frames> --transcribe (加上 --ref 與上次批准的版本比較,--frames 導出檢查表,--simulate 模擬 Instagram 壓縮)。在每個剪輯點讀取最終混音的逐字稿:重複字詞("decide, decide")、被切斷的字詞以及位置錯誤的字詞是剪輯清單最常見的缺陷。在移動剪輯點前,先透過波形(inspect_range.py)確認可疑的剪輯點,修正剪輯清單,組裝新版本(v2)並再次渲染。最多進行 3 輪,每個缺陷都應標註精確時間。永遠不要因為「看起來沒問題」就認為完成:必須引用數字。

8. 交付。 當混音未能達到目標時使用 loudness.py(線性增益和限制器,絕不使用 loudnorm),然後使用 deliver.py export.mp4 clean.mp4 [--no-editlist] [--copy <folder>]:不含時間碼軌道、無元資料、moov 前置、拷貝後進行逐位元組比較。

9. 審查,獲得批准後。 在筆記檔案中,以使用者的原話記錄他們批准和拒絕的內容,每個一行;每個新的陷阱及發現日期;以及每個你手動執行超過一次的操作,都應在這些腳本旁邊建立一個帶參數的腳本。

在 Resolve 內部執行腳本

  • run.py 連接到已開啟的 Resolve,並在定義了 resolve、project、P(JSON 物件)和 __file__ 的環境中執行腳本,然後以 JSON 格式輸出 result。這比透過 MCP 編寫相同腳本所需的 token 少得多。
  • 如果改用 MCP 伺服器(官方提供的 run_script_unsafe): P = {...}; __file__ = "<腳本的絕對路徑>"; exec(open(__file__, encoding="utf-8").read())。沙盒在未指定 encoding 時會以 ASCII 讀取檔案,且變數名稱在多次呼叫之間會持續存在:因此腳本需要為其變數加上前綴。
  • 在讀取和寫入之前儲存(GetProjectManager().SaveProject());沒有「復原」功能。每次建立新版本時,都應在時間軸的副本上進行(DuplicateTimeline,這也會複製 Fusion 合成)。
  • 查閱 API 文件而不是猜測:官方 MCP 的 search_scripting_api、get_scripting_docs 和 get_whats_new(每個對話階段一次),或者 Blackmagic 在 Resolve 的 Developer/Scripting 資料夾中的 README 文件(說明 > 文件 > 開發人員)。
  • 有需要重複執行的新操作?將其編寫為一個包含 P 字典和 result 的腳本,放置在這些腳本旁邊。

交付目標

目標平台畫面聲音
Reels、Stories、Shorts、TikTok1440x2560,使用拍攝影格率,H.264 High 約 20 Mbps 即時速度,Rec.709 標籤 (1-1-1),faststart-14 LUFS,真實峰值低於 -1.5 dBTP
課程與教學影片原始解析度 (1920x1080 或 3840x2160)-16 LUFS,真實峰值最高 -1 dBTP
YouTube4K 母版(1080p 上傳會損失畫質),不含 edit list 的 MP4使用母版混音
LinkedIn1920x1080 和 1080x1920 16 Mbps,附 SRT使用母版混音

已驗證的陷阱

在 macOS 上使用 Resolve Studio 21.1.1 和 21.1.2 進行測量,時間為 2026 年 10 月和 11 月。

機器

  • 一次只能執行一個 ffmpeg,使用 nice -n 15 和 -threads 2:同時執行 96 個 ffmpeg 程序會導致 Mac 凍結並需要強制重啟。
  • 在 zsh 中,$var 不會分割成單字(ffmpeg $args 會出錯):應在 Python 中建構引數列表。
  • 將輸出寫入工作資料夾:某個輔助腳本將圖片儲存在片段旁,意外寫入了原始素材硬碟。

Resolve 設定與 API

  • Resolve 21.1 將 Python 腳本功能移至 Studio 版:run.py 和兩個 MCP 伺服器都需要 DaVinci Resolve Studio。
  • 外部腳本必須設定為「本機」(偏好設定 > 系統 > 一般),否則 scriptapp("Resolve") 會回傳 None。
  • StartRendering 是腳本的最後一個呼叫:在此之後,所有操作都會回傳 None,直到渲染結束。
  • 專案影格率在建立第一個時間軸時鎖定:必須在此之前設定(project.py)。
  • 解析度設定:使用 SetSetting 一次設定一個鍵,並先使用 useCustomSettings。
  • MCP 超時(預設 10 秒,最多 60 秒)會回傳錯誤,但腳本仍會在 Resolve 內部繼續執行:在再次執行前檢查狀態。
  • 沒有修剪、移動或滑動功能:刪除項目,然後使用 startFrame、endFrame(不包含結尾)和 recordFrame 重新添加。
  • startFrame 從檔案的第一個影格開始計數,即使有攝影機時間碼也是如此。
  • GetSourceStartFrame 有時會讀取到錯誤的影格(866 讀成 865),但實際放置位置是正確的:使用 GetLeftOffset 讀取入點。
  • AddMarker 每個影格只能標記一個標記。
  • ReplaceClip 會清除片段的元資料。
  • SetTrackEnable 在某些時間軸上會回傳 True 但實際未改變任何設定:請使用 SetClipEnabled 停用片段,並透過導出的影格確認。
  • 在非當前時間軸上使用 SetClipEnabled 會回傳 False:先使用 SetCurrentTimeline,然後用 GetClipEnabled 確認。
  • DeleteClips(items, True) 會影響所有軌道:先在不影響相鄰片段的情況下,刪除跨過剪輯點的內容(背景、字幕)。
  • 可透過腳本使用語音隔離:TimelineItem.SetVoiceIsolationState({"isEnabled": True, "amount": 100}) 可將房間殘響降低 3 到 4 dB;Timeline.SetVoiceIsolationState(track, {...}) 可控制整個軌道。
  • API 無法設定 ResolveFX 參數(臉部細化、瑕疵去除):需要由人員設定,或透過輔助功能驅動 UI。
  • 當螢幕鎖定或 Resolve 最小化時,輔助功能視窗會消失,但 API 仍可正常運作:透過導出的影格進行驗證。
  • Super Scale 是媒體池屬性:SetClipProperty("Super Scale", 2);更換檔案後需要重新設定。
  • 用於 Graph.SetLUT 的 LUT 必須放在 Resolve 系統 LUT 資料夾的子資料夾中,並在 RefreshLUTList() 之後以相對路徑傳遞。
  • 在 Resolve 播放時切換頁面會導致掛起;item.GetFusionCompByIndex(1).Execute(lua) 可在不開啟 Fusion 頁面的情況下編輯合成。

匯入與媒體

  • 每次匯入只能匯入一個 ProRes 檔案:一次呼叫匯入多個 ProRes 4444(以及一次兩個新的 ProRes 422)會導致 Resolve 21.1 崩潰(UiMpController,std::out_of_range)。相機 MP4 檔案一次匯入 22 個則沒有問題。
  • 崩潰後,殘留的 ResolvePython 程序會導致 MCP 的 launch_resolve 回報 Resolve 正在執行:需要殺死該程序並重新開啟 Resolve。
  • 使用路徑列表的 ImportMedia:在 21.1 版中,使用字典形式的呼叫對 MP4 回傳了 None。
  • Resolve 會根據路徑快取解碼:重新渲染的檔案需使用新名稱。
  • MOV 中的 PCM 24-bit little-endian 會被讀取為白噪聲:請使用 pcm_s24be。
  • iPhone HEVC 導致 macOS 解碼器崩潰:請從 ProRes 編輯。
  • iPhone HDR(HLG、Dolby Vision):我們自己的色調映射看起來褪色,被拒絕了兩次。請在開始時要求 SDR 輸出。
  • 1 影格的 .mov 會被匯入為 150 影格的靜止圖片:請提供至少 3 個影格,然後在時間軸上修剪。
  • 直接 Alpha:Resolve 以未預乘的方式讀取 Alpha,因此在透明畫布上使用 ffmpeg overlay 製作的疊加層會變暗;請使用 pad=W:H:x:y:[email protected] 定位。

渲染

  • 使用 SelectAllFrames 時,StartRendering 有時會回傳 False:請設定 MarkIn/MarkOut(render.py 中的 mark),這也能剪掉延長時間軸的聲音尾音。
  • 在僅音訊任務之後立即建立的 H.264 任務可能沒有影片:請在 SetRenderSettings 之前載入預設,並使用 ffprobe 檢查是否有影片串流。
  • H.264 VideoQuality 是上限而非平均值:20000 在 1440x2560 下給出 14.7 Mbps,27300 給出 20.7 Mbps。
  • "Force sizing to highest quality" 不是 SetRenderSettings 的鍵,但它包含在渲染預設中(ForceHighestQualitySizing)。
  • ExportRenderPreset(name, path) 將 path 視為資料夾;ImportRenderPreset 以檔案名稱為預設命名。
  • 預設儲存了影格率:請從時間軸設定 FrameRate,否則 29.97 fps 的影格率會被轉換(render.py 會處理)。
  • ExportFrame(21.1.2)在 0.75 秒內輸出 4 個 1440x2560 的影格,品質在渲染的 41 到 46 dB 之間:可以在不渲染的情況下檢查影格。

聲音與逐字稿

  • 兩個鏡頭之間的剪輯可能會連接重複的字詞("decide, decide"):請對最終混音進行逐字稿,並尋找重複的內容。在不改變長度的情況下修復:在第一個片段中該字詞之前結束,在第二個片段中從良好鏡頭的停頓處更早開始。
  • 逐字稿不會聽到耳語和呼吸聲:剪輯點應來自攝影機自己的聲音(cut_list.py)。
  • Scribe 有一次在拍掌和耳語之後,將一個字詞提前了 3 秒放置:在移動剪輯點之前,請在波形上確認。
  • MP3 音效大約延遲 60 毫秒(編碼器延遲未補償):對於任何必須精確對齊影格的內容,請使用 WAV。
  • 單次 loudnorm 會動態調整並改變已批准的混音;兩次 loudnorm 會靜默地回退到動態模式:請使用 loudness.py。

素材與平台

  • 25 fps 在 Instagram 上:以 25 fps 發布(2026 年 11 月對發布檔案的 ffprobe 結果)。卡頓來自 ProMotion iPhone,它們沒有 25 或 50 Hz 模式。將 25 fps 素材保持為 25 fps(轉換為 30 fps 會每五幀重複一幀);以 29.97 fps 和 1/50 快門拍攝新素材。
  • 在 50 Hz 燈光下閃爍取決於快門而非影格率:1/50 和 1/100 不會閃爍;1/60 在 30 fps 下會閃爍。
  • Instagram 會在手機和伺服器上再次編碼:基本交付約 720x1280 1.4 Mbps,聲音標準化至約 -14 LUFS,因此高於 -14 的母版不會有增益。qc.py --simulate 會顯示哪些內容能存活下來。
  • ffmpeg 的 CRF 會使暗色背景畫質不足:一個 Reel 僅剩下 6.8 Mbps。在交付前檢查實際位元率。
  • 一個無頭的 claude -p 會在渲染開始時結束對話,除非提示中明確要求等待。

腳本

腳本功能
scripts/media/transcribe.py每個片段輸出 Scribe 逐字 JSON(金鑰透過 stdin 傳遞,絕不在程序列表中顯示)
scripts/media/dossier.py將每個片段輸出為緊湊文字:帶時間碼的句子、停頓、重複嘗試、可選的影格表
scripts/media/inspect_range.py一個範圍的一張圖片:影格、波形、帶時間碼的字詞
scripts/media/cut_list.py取鏡頭,放置於最安靜的影格邊界,縮短停頓,產生交錯縮放...

...(此為翻譯後的局部內容,完整文件應涵蓋所有後續腳本)

相關技能