Communitygithub.com

Developh/resolve-cut

DaVinci Resolve Studio でトーキングヘッド動画(レッスン、コース、インタビュー)をエンドツーエンドで編集します。ワードレベル文字起こし、全テイクの資料、各パラグラフの最後の完全なテイク、フレーム精度のカットリスト、スクリプトによるタイムラインアセンブリ、プリセットレンダリング、QC(ラウドネス、フレーム、繰り返し単語)と納品を行います。Resolve スクリプト、アセンブリ、レンダリング、QC、ビデオ納品作業の前に読み込んでください。

resolve-cut とは?

このスキルは、DaVinci Resolve Studio 上でトーキングヘッド動画の編集ワークフロー全体を、保存されたスクリプトとパラメータを使って自動化します。開発者は、動画の文字起こし、全テイクの資料作成、各パラグラフの最適なテイク選択、フレーム精度のカットリスト生成、スクリプトベースのタイムラインアセンブリ、プリセットレンダリング、そしてラウドネスやフレームチェック、繰り返し単語の検出といった品質管理(QC)を実行できます。このスキルは Claude Code などの AI エージェントと組み合わせて使用することを想定しており、AI エージェントが編集判断を行い、スキルがそれを正確に実行・検証します。対応プラットフォームは DaVinci Resolve Studio(有料版)で、macOS での動作が確認されています。開発者は、このスキルのスクリプトを呼び出し、結果を読み取り、数値やフレームで検証することで、編集作業を効率的に進めることができます。各スクリプトは独立しており、パラメータを変更することで柔軟にワークフローをカスタマイズできます。また、様々な配信先(YouTube、Instagram、LinkedIn など)に最適化されたレンダリングプリセットが用意されています。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Developh/resolve-cut/tree/HEAD/skills/resolve-cut

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

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 が閉じている、無料版である、または環境設定 > システム > 一般 > 外部スクリプトの使用が Local に設定されていないことを意味します。
  2. ffmpeg -version、python3 -c "import numpy, PIL"、および ELEVENLABS_API_KEY(環境変数または ./.env)が必要です。
  3. プロジェクトにメモファイル(VIDEO_NOTES.md など)がある場合は、それを読んでください。人間が以前に承認したものと拒否したものが書かれています。同じ修正を二度求めないでください。
  4. ワークフォルダ:作成するすべてのもの(文字起こし、資料、フレーム、レンダリング)はワークフォルダに保存します。生の動画フォルダには決して保存しません。

ワークフロー

1. 文字起こし。 ワードレベルの文字起こし。クリップごとに 1 つの JSON ファイル。 python3 "$SKILL/scripts/media/transcribe.py" <クリップフォルダ> --out work/transcripts [--language por] 文字起こしは、すべての基本となります。テイクの選択、フレーム境界でのカット、最終ミックスのチェックに使用されます。

2. 資料。 すべての素材を 1 つのコンパクトなテキストファイルにまとめ、一度読む: python3 "$SKILL/scripts/media/dossier.py" <クリップフォルダ> --transcripts work/transcripts --out work/dossier.md [--sheets] 各文をその時間とともにリストアップし、文が以前の文と似たように始まる場合(同じラインの別の試行)には «repeats C0076 20.2» というフラグを付けます。スクリプトを使用する場合は、各段落の 最後の完全なテイク を保持します。ためらい、言い間違い、繰り返しの試行は削除します。判断が必要な場合のみクリップを開きます。 python3 "$SKILL/scripts/media/inspect_range.py" <クリップ> <t0> <t1> --words work/transcripts/<クリップ名>.json(フレーム、波形、単語を 1 つの画像に表示)。

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 <クリップフォルダ> work/cuts.json カットは、単語の隣の最も静かなフレーム境界に配置されます。1 秒以上のポーズは短縮され、セグメントはズーム 1 / 1.2 で交互になるため、テイク間のカットが飛び跳ねることはありません。間のない言い間違い(「コ- コント」)の場合は、{"in_frame": N} または {"out_frame": N} でフレームを強制します。編集者向けのメモ:add_markers.py。

4. Resolve でアセンブル。 1 回の呼び出しで 1 つの重い操作を行い、次の操作の前に各 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 は、1 秒未満でタイムラインからフレームを直接エクスポートします。 ({"timeline": "Lesson 01 v1", "frames": [100, 500], "folder": "/abs/work/frames", "max": 960})。通常のフレームと拡大フレームを 1 つずつ確認します。

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, <フレーム数 - 1>]}' その後、JobStatus が Complete になるまで、10 秒ごとに {"phase": "status", "job": "<id>"} をポーリングします。応答する前に レンダリングが終了するのを待ってください。「レンダリング開始」でターンを終了するヘッドレス実行では、チェックする人がいなくなります。

7. 検証。 python3 "$SKILL/scripts/media/qc.py" out/lesson-01.mp4 --expected <フレーム数> --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 <フォルダ>]:タイムコードトラックなし、メタデータなし、moov を先頭に、コピーをバイト単位で比較します。

9. レビュー(人間が承認した後)。 メモファイルに、人間が承認したものと拒否したものを、その人の言葉で、1 行に 1 つずつ書き込みます。新しいトラップはそれぞれ日付とともに記録します。手動で 2 回以上行ったルーチンは、パラメータ付きのスクリプトにして、これらの隣に配置します。

Resolve 内でのスクリプトの実行

  • run.py は、開いている Resolve に接続し、resolve、project、P(JSON)、__file__ が定義された状態でスクリプトを実行し、result を JSON として出力します。MCP を介して同じスクリプトを記述するよりも、はるかに少ないトークン数で済みます。
  • 代わりに MCP サーバー(公式の run_script_unsafe)を使用する場合: P = {...}; __file__ = "<スクリプトの絶対パス>"; exec(open(__file__, encoding="utf-8").read())。サンドボックスは encoding なしでファイルを ASCII として読み取り、変数名は呼び出し間で保持されるため、スクリプトは変数に接頭辞を付けます。
  • 書き込みの前後で保存します(GetProjectManager().SaveProject())。元に戻すことはできません。新しいバージョンは常にタイムラインのコピー(Fusion コンポもコピーされる DuplicateTimeline)で作成します。
  • 推測する代わりに API を調べてください。公式 MCP の search_scripting_api、get_scripting_docs、get_whats_new(セッションごとに 1 回)、または Resolve の Developer/Scripting フォルダ(ヘルプ > ドキュメント > 開発者)にある Blackmagic の README を参照してください。
  • 新しい操作で繰り返し発生するものは?P 辞書と result を持つスクリプトとして一度作成し、これらと一緒に配置します。

納品先

宛先映像音声
Reels, Stories, Shorts, TikTok撮影フレームレートの 1440x2560、約 20 Mbps 実効の H.264 High、Rec.709 タグ (1-1-1)、faststart-14 LUFS、トゥルーピーク -1.5 dBTP 未満
レッスンとコース記録された解像度のまま (1920x1080 または 3840x2160)-16 LUFS、トゥルーピーク -1 dBTP まで
YouTube4K マスター(1080p アップロードは品質が低下)、編集リストなしの MP4マスターのミックス
LinkedIn16 Mbps の 1920x1080 および 1080x1920、SRT 付きマスターのミックス

確認済みのトラップ

macOS 上の Resolve Studio 21.1.1 および 21.1.2、2026 年 10 月および 11 月に測定。

マシン

  • 一度に 1 つの 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 が必要です。
  • 外部スクリプトは Local に設定する必要があります(環境設定 > システム > 一般)。そうしないと、scriptapp("Resolve") は None を返します。
  • StartRendering はスクリプトの最後の呼び出しです。レンダリングが終了するまで、他のすべては None を返します。
  • プロジェクトのフレームレートは、最初のタイムラインが作成されたときにロックされます。事前に設定してください(project.py)。
  • 解像度:useCustomSettings を最初に設定した後、SetSetting で 1 つのキーずつ設定します。
  • MCP タイムアウト(デフォルト 10 秒、最大 60 秒)はエラーを返しますが、スクリプトは Resolve 内で実行を続けます。再実行する前に状態を確認してください。
  • トリム、移動、スリップはありません。アイテムを削除し、startFrame、endFrame(排他)、recordFrame を使用してもう一度追加します。
  • startFrame は、カメラのタイムコードに関係なく、ファイルの最初のフレームからカウントされます。
  • GetSourceStartFrame は、配置が正しい場合でも、1 フレーム早く読み取ることがあります(866 が 865 と読み取られる)。GetLeftOffset でイン点を読み取ってください。
  • AddMarker はフレームごとに 1 つのマーカーを保持します。
  • ReplaceClip はクリップのメタデータを消去します。
  • SetTrackEnable は True を返しますが、一部のタイムラインでは何も変更しません。SetClipEnabled でクリップを無効にし、エクスポートされたフレームで確認します。
  • 現在のタイムラインではないタイムラインで SetClipEnabled を実行すると False が返ります。最初に SetCurrentTimeline を実行し、その後 GetClipEnabled で確認します。
  • DeleteClips(items, True) はすべてのトラックをリップルします。最初にリップルなしで、カットを横切るもの(ステム、キャプション)を削除します。
  • ボイスアイソレーションはスクリプトで動作します。TimelineItem.SetVoiceIsolationState({"isEnabled": True, "amount": 100}) は、部屋の残響を 3 ~ 4 dB 低減しました。Timeline.SetVoiceIsolationState(track, {...}) は、トラック全体に対して 1 つの制御を設定します。
  • API は ResolveFX パラメータ(フェイスリファインメント、ブレミッシュリムーバル)を設定できません。人間が設定するか、アクセシビリティを介して UI を操作します。
  • 画面がロックされているか、Resolve が最小化されている場合、ウィンドウはアクセシビリティから消えますが、API は機能し続けます。エクスポートされたフレームで確認します。
  • スーパースケールはメディアプールのプロパティです。SetClipProperty("Super Scale", 2)。交換ファイルは再度設定する必要があります。
  • Graph.SetLUT の LUT は、Resolve のシステム LUT フォルダ内のサブフォルダに配置し、RefreshLUTList() の後に相対パスで渡します。
  • Resolve の再生中にページを変更するとハングします。item.GetFusionCompByIndex(1).Execute(lua) は、Fusion ページを開かずにコンポを編集します。

インポートとメディア

  • インポート呼び出しごとに 1 つの ProRes。1 回の呼び出しで複数の ProRes 4444(および一度、2 つの新しい ProRes 422)をインポートすると、Resolve 21.1 がクラッシュしました(UiMpController、std::out_of_range)。カメラ MP4 は 1 回の呼び出しで 22 ファイルでも問題ありませんでした。
  • そのクラッシュ後、孤立した ResolvePython プロセスにより、MCP の launch_resolve が Resolve を実行中と報告します。そのプロセスを強制終了し、Resolve を再度開いてください。
  • パスのリストを使用した ImportMedia:辞書形式は 21.1 で MP4 に対して None を返しました。
  • Resolve はパスによってデコードをキャッシュします。再レンダリングするファイルには新しい名前を付けてください。
  • MOV 内の PCM 24 ビットリトルエンディアンはホワイトノイズとして読み取られます。pcm_s24be を使用してください。
  • iPhone の HEVC は macOS デコーダーをクラッシュさせました。ProRes から編集してください。
  • iPhone HDR(HLG、Dolby Vision):私たちのトーンマップは色あせて見え、2 回拒否されました。最初に SDR エクスポートを依頼してください。
  • 1 フレームの .mov は 150 フレームの静止画としてインポートされます。少なくとも 3 フレームにして、タイムライン上でトリミングしてください。
  • ストレートアルファ:Resolve はアルファを乗算されていない状態で読み取るため、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 でした。
  • 「最高品質に強制サイズ変更」は SetRenderSettings のキーではありませんが、レンダープリセット内(ForceHighestQualitySizing)に含まれています。
  • ExportRenderPreset(name, path) は path をフォルダとして扱います。ImportRenderPreset はプリセットにファイルの名前を付けます。
  • プリセットはフレームレートを保存します。タイムラインから FrameRate を設定するか、29.97 のタイムラインは変換されてレンダリングされます(render.py が行います)。
  • ExportFrame(21.1.2)は、1440x2560 で 4 フレームを 0.75 秒で出力し、レンダリングの 41 ~ 46 dB の範囲でした。レンダリングせずにフレームを確認してください。

音声と文字起こし

  • 2 つのテイク間のカットは、繰り返し単語(「decide, decide」)を結合する可能性があります。最終ミックスを文字起こしし、重複を探します。長さを変えずに修正するには、単語の前に最初の部分を終了し、良いテイクのポーズの早い段階で 2 番目の部分を開始します。
  • 文字起こしはささやき声や息遣いを聞き取りません。カットポイントはカメラ自身の音声(cut_list.py)から取得します。
  • Scribe はかつて、拍手とささやきの後、単語を 3 秒早く配置しました。カットを移動する前に波形で確認してください。
  • MP3 効果音は約 60 ミリ秒遅れて配置されます(エンコーダ遅延が補正されていません)。フレームに正確に合わせる必要があるものには WAV を使用してください。
  • 1 パスの loudnorm は動的に変化し、承認されたミックスを変更します。2 パスでは、静かに動的フォールバックします。loudness.py を使用してください。

動画とプラットフォーム

  • Instagram 上の 25 fps:25 で配信されます(提供されたファイルの ffprobe、2026 年 11 月)。カクつきは ProMotion iPhone が原因で、25 Hz または 50 Hz モードはありません。25 fps の素材は 25 のままにします(30 に変換すると 5 フレームに 1 フレームが繰り返されます)。1/50 シャッターで 29.97 fps の新しい素材を撮影します。
  • 50 Hz ライト下のフリッカーは、フレームレートではなくシャッターに依存します。1/50 と 1/100 はフリッカーしません。30 fps での 1/60 はフリッカーします。
  • Instagram は電話上とサーバー上で再エンコードします。基本的な配信は約 720x1280@1.4 Mbps、音声は約 -14 LUFS に正規化されるため、-14 を超えるマスターは何も得られません。qc.py --simulate は何が生き残るかを示します。
  • ffmpeg の CRF は暗い背景を劣化させます。1 つのリールは 6.8 Mbps のままでした。配信前に実際のビットレートを確認してください。
  • ヘッドレス claude -p 実行は、プロンプトが待機を指示しない限り、レンダリングが開始された時点でターンを終了します。

スクリプト

スクリプト機能
scripts/media/transcribe.pyクリップごとの Scribe ワードレベル JSON(キーは stdin から、プロセスリストには決して含まれません)
scripts/media/dossier.pyすべてのクリップをコンパクトなテキストとして出力:時刻付きの文、ポーズ、繰り返しの試行、オプションのフレームシート
scripts/media/inspect_range.py範囲の 1 つの画像:フレーム、波形、時刻付きの単語
scripts/media/cut_list.pyテイク

…

[翻訳用に切り詰められました]

関連スキル