Communitygithub.com

ビデオカラーグレード

映像のカラー補正、ホワイトバランス調整、露出修正、Log→Rec.709変換、クリエイティブなルック作成、肌色チェック、およびカット・アズ・コード配信用のポータブル.cube LUT生成を行います。

ビデオカラーグレード とは?

このスキルは、映像素材に対して完全にコードベースでカラーグレードを適用するための包括的なワークフローを提供します。最初に素材を評価し、補正ベース(Log→Rec.709変換やホワイトバランス調整など)を設定した上で、複数の名前付きクリエイティブルック(暖色系、クール系、ティール&オレンジなど)を生成します。各ルックは「補正ベース + クリエイティブ層」の2層構造で設計されており、肌色の品質を最優先に評価します。人間の選択またはエージェントの判断でルックを決定した後、選択したルックをポータブルな.cube LUTとしてベイク(焼き付け)し、最終映像全体に適用します。ffmpeg、Python(numpy + Pillow)を利用し、音声は-c:a copyで無劣化維持されます。Claude Code、Cursor、CodexなどのAIエージェント環境で動作し、決定プロセスと根拠をgrade-plan.jsonに記録します。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/WhiteTowerAI/cut-as-code/tree/main/skills/video-color-grade

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

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

ドキュメント

ビデオカラーグレード(評価→補正→ルック→選択→LUT+適用)

グレードをコードとしてゼロから作成し、実際の映像上で複数の異なる名前付きルックを生成し、明示的な人間の選択または委任されたエージェントの判断で1つを選択し、ポータブルな.cube LUTをベイクしてフルクリップに適用します。プリセットパックは使いません。

中核となる考え方 — まず補正、次にスタイル。 すべてのルックは補正ベース + クリエイティブ層です:

  • 補正ベース は映像を素直にします — フラットなLOG/HLGの場合はlog→Rec.709変換、すでにRec.709の映像の場合はWBニュートラル化+露出+マイルドなコントラストです。 すべてのルックがこのベースを共有するため、「ニュートラル」は意味を持ち、ルックは意図によって異なります。
  • クリエイティブ層 はその上に重ねるルックです(ウォーム/クール/ティールオレンジ/パンチィ/フェードなど)。

肌が品質基準です。 人物 — 特に肌の色が濃い人 — に対して、teal_orange や cool_desat はしばしば緑/灰色のキャストを発生させます。まず顔で全てのルックを評価し、中間調の暖かさを維持し、ティントをシャドウ/ハイライト/背景に押し込み、生のsaturationよりもvibranceを優先します。ホワイトバランスを完全にニュートラルにまで追い込まないでください。肌が死にます。

必要条件:ffmpeg/ffprobe がPATHに存在すること、Python に numpy + Pillow がインストールされていること。

契約

  • すべてのルック = ベース + クリエイティブ層、ベースは全ルックで共有。
  • すべてのルックは同じ代表フレーム(公平で制御された比較用)に、ラベル付きでフル解像度でレンダリングされます。
  • フル適用では**-c:a copy(音声は再エンコードされない → A/V同期は同一)を使用し、ソースの長さ、fps、寸法**を維持します。
  • 納品前にルック選択を完了します。ユーザーが選択を求めた場合はhumanモードを使用し、ユーザーが選択を委任したか自動実行を要求した場合はagentモードを一時停止なしで使用します。両方のモードで、永続的な計画に rationale(根拠)を保存します。

プロジェクトプロトコルワークフロー

永続的な決定を work/color-grade/grade-plan.json に保存します:

{
  "schema_version": 1,
  "target": "base-video",
  "base": "eq=contrast=1.05",
  "looks": [{"name": "clean", "chain": "null"}],
  "selected_look": "clean",
  "selection_mode": "agent",
  "selection_rationale": "Neutral correction preserves natural skin and source lighting.",
  "selected_lut": "../../final/selected-color-look.cube",
  "evidence_refs": ["media:source"]
}

デフォルトでは base-video を使用し、コンテンツカードやキャプションが再着色されないようにします。composite は、すでに合成されたピクセルを意図的にグレーディングする場合にのみ有効です。共有の work/understand/media.json と視覚的エビデンスを読み込みます。review/02-color-grade/choose-color-look.jpg と review/02-color-grade/skin-tone-check.jpg を生成し、オプションで短い selected-look-preview.mp4 を生成します。決定とエビデンスを review/02-color-grade/selected-look.md に記録します。

明示的なユーザー選択の後は selection_mode を human に設定します。ユーザーが決定を委任するか、中断のないワークフローを要求した場合は agent に設定し、肌色、ハイライト保持、ニュートラルバランスを優先して保守的に選択します。常に空でない selection_rationale を記述し、agent モードでは一時停止しないでください。

選択された LUT を final/selected-color-look.cube にベイクします。その LUT が出荷されるときは、grade plan の selected_lut を設定して、共有レンダラーがその正確なファイルを消費するようにします。ベイクされたフルルック LUT にはすでに補正ベースが含まれています。レンダラーは base + lut3d ではなく、lut3d のみを適用する必要があります。

操作の正確な入力リビジョンを based_on に記録し、計画または選択された入力が変更されたときにその整数 revision をインクリメントし、レビューファイルが完了した後にのみ操作チェックを pass に設定し、完全なプロトコルフィールドを提供します:

{
"target": {"sequence": "main", "scope": "base-video"},
"effects": {
  "changes_timeline": false,
  "changes_geometry": false,
  "changes_video_pixels": true,
  "changes_audio": false,
  "adds_track": null
},
"check": {
  "status": "pass",
  "report": "../review/02-color-grade/selected-look.md"
},
"render": {
  "kind": "video-filter",
  "target": "base-video",
  "plan": "color-grade/grade-plan.json"
}
}

共有レンダラーは selected_look が存在することを検証し、タイムライン変換後、オーバーレイ前にグレードを適用し、最終ビデオを一度エンコードします:

python skills/video-understand/scripts/build_render_plan.py .
python skills/video-understand/scripts/render_project.py work/render/render-plan.json

スタンドアロン互換性のための入力

  • ソースビデオ。
  • looks.json(base + 名前付き looks);looks.example.json から始めて、assess.py が報告する内容に基づいて base を再調整します。

既存のすべてのスクリプトは、引き続き従来の looks.json を受け入れます。gradelib.load_spec() は正規の grade-plan.json も受け入れるため、コンタクトシート、クリップ、LUT、スタンドアロン適用コマンドは移行中も互換性を保ちます。

looks.json スキーマ

{
  "base": "<補正ベース:log→Rec.709 変換、または通常の映像用の WB+露出+コントラスト>",
  "looks": [
    { "name": "clean_neutral", "label": "1 · CLEAN NEUTRAL", "desc": "補正のみ", "chain": "eq=contrast=1.02" },
    { "name": "teal_orange",   "label": "4 · TEAL & ORANGE", "desc": "シネマティック",      "chain": "colorbalance=...,eq=..." }
    // ルックの完全な ffmpeg フィルター = base + "," + chain。チェーンを単独で使用するには "prepend_base": false を設定。
  ]
}

ワークフロー

  1. 評価 — 決して盲目的にグレーディングしないでください。

    python scripts/assess.py SOURCE.mp4 --out work/
    

    log-vs-Rec.709、ホワイトバランスのキャスト(128に対する signalstats U/V)、露出(Y)を報告し、代表フレーム(work/assess/frame.png)を選び、ベース調整案を提示します。それに応じて looks.json の base を再調整します(例:暖色キャスト → 少し青を追加;log → log→709 変換を base に入れる)。

    • 代表フレームは顔ではなく、輝度の中央値で選ばれます。 シングルショットのトーキングヘッドでは通常良い顔フレームになりますが、Bロールが多い/マルチショットの映像では顔のないフレームを選ぶ可能性があります — その場合 face_skin_check.png は役に立ちません(肌が品質基準です)。既知の顔の瞬間を --frame-time SECONDS で強制します。
    • WB/露出の統計は、再生時間の10%の位置にある約10秒間の signalstats ウィンドウから取得されます — 一定の照明には問題ありませんが、照明が変化する映像の場合は --win-start SECONDS / --win-dur SECONDS で移動/延長します。
  2. 選択用にルックをレンダリングします。

    python scripts/render_looks.py work/assess/frame.png looks.json --out work/looks
    

    work/looks/looks_compare.png(オリジナル+全ルック、ラベル付き、フル解像度)と face_skin_check.png(拡大肌ストリップ)を生成します。両方を見てください。 肌が基準です — 肌を灰色/緑にするルックは再調整するか削除してから再レンダリングします。被写体が中央にいない場合は --face-crop W:H:X:Y を追加します。 これらのPNGを作業中の中間ファイルとして扱い、承認されたレビューコピーを review/02-color-grade/choose-color-look.jpg と review/02-color-grade/skin-tone-check.jpg として公開します。

  3. (オプション) モーションプレビュー 上位2〜3のルックを動きで確認します(音声は保持):

    python scripts/make_clips.py SOURCE.mp4 looks.json --out work/clips \
      --pick clean_neutral,warm_filmic,teal_orange --with-original --ss 148 --t 8
    
  4. 1つのルックを選択します。 ユーザーが選択を求めた場合のみ、コンタクトシートを提示して待機します。それ以外の場合は agent モードで選択し、決定のための一時停止なしで続行します。納品前に selected_look、selection_mode、selection_rationale を記述します。

  5. 選択後 — LUTをベイクしてフルクリップに適用します。

    python scripts/bake_lut.py looks.json --name CHOSEN \
      --out final/selected-color-look.cube --verify-frame work/assess/frame.png
    python scripts/apply_grade.py SOURCE.mp4 --looks looks.json --name CHOSEN --out out/graded.mp4
    #   または配送されたLUTを適用:--lut final/selected-color-look.cube
    

    apply_grade.py は長さ/音声が保持されていることを確認し、WBシフト(U/Vが128に向かう)を表示し、スポットフレームを出力して目視確認できるようにします。

    • 適用ではビデオを一度再エンコードします(ロスあり);音声は -c:a copy です。 品質/時間は --crf(デフォルト18)と --preset(デフォルト slow)で設定します。slow は小規模/短いクリップには適していますが、1080p/4Kの長時間映像では大きな時間コストがかかります — 配信時は --preset medium に下げ(クイックプレビューには veryfast)、最終版のみ slow にします。
    • 配信ビデオを配信LUTに一致させる: チェーン(--name)とベイクされた33³の .cube(--lut)は、急峻なカーブで最大約5/255異なる可能性があります(bake_lut.py はこの max|d| を報告します)。ほとんどの作業では目に見えませんが、.cube を出荷する場合でレンダリングされたビデオをそれに正確に一致させたい場合は、--name ではなく --lut final/selected-color-look.cube で適用します。

設計ノート / 落とし穴

  • クリーンカットをグレーディングし、グレーディングされた映像の上にコンポジットオーバーレイを重ねます。 すでに焼き込みキャプション/カードがあるビデオをグレーディングしなければならない場合、assess.py を信頼してはいけません:そのWB/露出統計とフレーム選択はグラフィックスによって歪められます(暗い上下スクリムはYを引き下げ、明るいキャプションテキスト/ティールアクセントはU/Vを歪め、フレーム選択がキャプションの多いフレームにランディングする可能性があります)— 映像ではなくオーバーレイを補正することになります。クリーン映像で調整された base を再利用し、グレードがオーバーレイに色味を付けることを想定して、微妙な/補正的なルック(clean_neutral)のみを使用します;teal_orange/vintage_faded はテキスト/アクセントを明らかに再着色します。
  • 1つのルック/LUTがすべての関連クリップをカバーします。 ルックを選択したら、すべての関連クリップ(例:クリーンカット+オーバーレイ版)で同じ looks.json / .cube を再利用します — クリップごとに2フェーズの選択を再実行しないでください。
  • まず補正、次にスタイル。 ベースはデッキのS-Log3→Rec.709ステップの一般化です。通常の映像ではベースはWB+露出+コントラストです。log映像の場合はそこに変換を入れます。
  • 肌が最優先。 teal_orange/cool_desat は、肌の色が濃い被写体で通常の問題となるルックです — 中間調を暖かく保ち、シャドウ/ハイライト/bgにティントを入れ、vibrance を使用します。U/Vを完全にニュートラルにしないでください。
  • ラベルはffmpegによってオーバーレイされるPIL PNGです — drawtext は使用しません。 Windowsでは drawtext の fontfile パス(ドライブコロン)が信頼できません。フォントは gradelib.py の先頭で設定されます。
  • ドライブコロンパスは、パスを受け取るffmpegフィルターグラフオプション(lut3d、metadata=print:file=)を壊します。 スクリプトは cwd をファイルのフォルダに設定してffmpegを実行し、ベース名で参照します。新しいパスを受け取るフィルターではこのパターンを維持してください。
  • 出力は渡した --out ディレクトリ(永続的)に格納され、システムの一時ディレクトリには格納されません。
  • 顔/肌ストリップは、顔検出ではなく、固定された中央上部のクロップを使用します。 被写体がおおよそ中央にいない場合は、render_looks.py に --face-crop W:H:X:Y を渡してください。そうしないと、肌ストリップが間違った領域を表示します。
  • apply_grade.py の検証用スポットフレームは再生時間の20%の位置にあります — ルックが選択されたフレームとは異なるフレームです。その20%のポイントに顔がない場合は、代わりに別のフレームで肌を目視確認します(または --frame-time を assess.py に渡して、選択されたフレームが既知の顔の瞬間になるようにします)。
  • LUTベイクは正確です — ここでのすべてのフィルターはピクセルごとのポイント操作だからです:bake_lut.py は33³のアイデンティティグリッドを実際のチェーンに押し込み、それに対して自己チェックします(mean|d| は1/255を十分に下回るはずです。数レベルの max|d| は単なる補間です)。
  • 常に納品前に選択を行います。 人間の選択と委任されたエージェントの選択は両方とも有効ですが、計画にはどちらが発生したかとその理由を記録する必要があります。

Individual skills in this repo

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

関連スキル