Communitygithub.com

影片調色 (video-color-grade)

用於需要色彩校正、白平衡或曝光修復、Log 轉 Rec.709、具名創意調色風格、膚色檢查,或為「剪輯即交付」流程產出可攜式 .cube LUT 的情境。

影片調色 (video-color-grade) 是什麼?

此技能以程式碼從頭編寫影片調色流程,透過真實素材生成多種具名調色風格,經由明確的人工選擇或委派給代理判斷來選定一種風格,最後烘焙出可攜式的 .cube LUT 並應用於完整片段。核心概念是「先校正,再風格化」:每一種調色風格都由一個共享的校正基底加上創意分層構成,確保中性風格保持意義,而不同風格則體現不同的意圖。膚色是品質標竿,尤其在處理較深膚色的主體時,會優先以臉部判斷,避免常見的綠/灰偏色,並傾向使用 vibrance 而非飽和度。技能支援 ffmpeg 與 Python,可在 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 中提問

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

說明文件

影片調色 (Video Color Grade) (評估 → 校正 → 風格 → 選擇 → LUT + 套用)

從頭以程式碼編寫調色流程,在真實素材上生成數種具名風格,透過明確的人工選擇或委派代理判斷選定一種,接著烘焙出可攜式的 .cube LUT 並套用於完整片段。不使用預設套件。

核心概念 — 先校正,再風格化。 每一種風格都是 校正基底 + 創意分層:

  • 校正基底 讓素材變得 真實 — 對於平坦的 LOG/HLG 素材,它是 log→Rec.709 轉換;對於已是 Rec.709 的素材,它是白平衡中和 + 曝光 + 適度對比。 每種風格共用此基底,因此「中性」始終有意義,而不同風格的差異來自於 意圖。
  • 創意分層 是疊加在基底之上的風格 (暖色 / 冷色 / 青橙 / 鮮明 / 褪色…)。

膚色是品質標竿。 在人物身上 — 尤其是較深膚色 — teal_orange 和 cool_desat 經常造成綠色/灰色偏色。務必先以臉部判斷每一種風格;保持中間調溫暖,將色調推向陰影/高光/背景,偏好使用 vibrance 而非原始 saturation。不要將白平衡完全推向中性,否則膚色會失去生氣。

需求:ffmpeg/ffprobe 位於 PATH,Python 搭配 numpy + Pillow。

合約

  • 每種風格 = 基底 + 創意分層;基底由所有風格共用。
  • 所有風格都渲染在同一個代表性影格上 (公平、可控的比較),附上標籤,以完整解析度呈現。
  • 完整套用使用 -c:a copy (音訊永不重新編碼 → 影音同步一致),並保持來源的時長、fps、尺寸。
  • 在交付前完成風格選擇。當使用者要求選擇時使用 human 模式;當使用者委派選擇或要求自主執行時使用 agent 模式,不暫停。兩種模式都需在持久化計畫中保留選擇理由。

專案協定工作流程

將持久性決策儲存在 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": "中性校正保留了自然的膚色與原始光線。",
  "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 交付時,在調色計畫中設定 selected_lut,以便共享渲染器使用該確切檔案。已烘焙的完整風格 LUT 已包含校正基底;渲染器必須單獨套用 lut3d,而不是 base + 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 · 乾淨中性", "desc": "僅校正", "chain": "eq=contrast=1.02" },
    { "name": "teal_orange",   "label": "4 · 青橙色", "desc": "電影感",      "chain": "colorbalance=...,eq=..." }
    // 一個風格的完整 ffmpeg filter = base + "," + chain。將 "prepend_base": false 設為 true 可獨立使用 chain。
  ]
}

工作流程

  1. 評估 — 絕不盲目調色。

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

    報告 log 與 Rec.709 的關係、白平衡色偏 (signalstats U/V 與 128 的比較)、曝光 (Y),挑選一個代表性影格 (work/assess/frame.png),並建議基底調整。據此重新調整 looks.json base (例如暖色偏 → 加入一點藍色;log → 將 log→709 轉換放入 base)。

    • 代表性影格是根據中間亮度選取,而非臉部。 在單一鏡頭的 talking-head 上,這通常會落在一個好的臉部影格,但在 B-roll 為主 / 多鏡頭素材上,它可能會選到一個沒有臉部的影格 — 此時 face_skin_check.png 就沒有用處 (膚色是品質標竿)。使用 --frame-time SECONDS 強制指定一個已知有臉的時刻。
    • WB/曝光統計來自約 10 秒的 signalstats 視窗,位於時長 10% 的位置 — 對於恆定光源來說沒問題;對於光線會變化的素材,使用 --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. 選擇一種風格。 僅在使用者要求選擇時才呈現聯絡表並等待。否則以 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 並且希望渲染的影片與之完全匹配,請使用 --lut final/selected-color-look.cube 套用,而不是 --name。

設計備註 / 陷阱

  • 先對乾淨的剪輯調色,再將合成疊加層疊加在調色後的影片上。 如果你必須對已含有燒錄字幕/卡片的影片進行調色,請勿相信 assess.py:它的 WB/曝光統計和影格選取會被圖形干擾 (暗色頂部/底部遮幅會拉低 Y,明亮的字幕文字/青色強調色會偏移 U/V,且影格選取可能落在一個字幕繁多的影格上) — 你等於是在校正疊加層,而不是素材。重複使用在乾淨素材上調整好的 base,並預期調色會影響疊加層的顏色,因此僅使用微妙/校正性質的風格 (clean_neutral);teal_orange/vintage_faded 會明顯地重新著色文字/強調色。
  • 一種風格/LUT 涵蓋所有相關片段。 一旦你選定了一種風格,就在每個相關片段 (例如乾淨剪輯 + 加上疊加層的版本) 上重複使用相同的 looks.json / .cube — 不要為每個片段重新執行兩階段的選擇流程。
  • 先校正,再風格化。 基底是典範中 S-Log3→Rec.709 步驟的一般化。對於一般素材,基底是 WB+曝光+對比;對於 log 素材,則將轉換放在那裡。
  • 膚色優先。 teal_orange/cool_desat 是較深膚色主體上常見的問題 — 保持中間調溫暖,將色調推向陰影/高光/背景,使用 vibrance。不要完全中和 U/V。
  • 標籤是以 PIL 生成的 PNG,由 ffmpeg 疊加 — 絕不使用 drawtext。 在 Windows 上,drawtext 的 fontfile 路徑 (磁碟機冒號) 不可靠。字型在 gradelib.py 頂部設定。
  • 磁碟機冒號路徑會破壞接受路徑的 ffmpeg filtergraph 選項 (lut3d、metadata=print:file=)。腳本以 cwd = 檔案所在資料夾的方式執行 ffmpeg,並以基本名稱引用它。對於任何新的接受路徑的 filter,請保持此模式。
  • 輸出會落入你傳入的 --out 目錄 (持久化),而非系統暫存目錄。
  • 臉部/膚色條使用固定的居中上半部裁切,而非臉部偵測。 如果主體沒有大致居中,請向 render_looks.py 傳遞 --face-crop W:H:X:Y,否則膚色條會顯示錯誤的區域。
  • apply_grade.py 的驗證檢查影格位於時長的 20% — 這是一個與選擇風格時不同的影格。如果該 20% 的位置沒有臉部,請改為目視檢查另一個影格的膚色 (或向 assess.py 傳遞 --frame-time,使選定的影格是一個已知有臉的時刻)。
  • LUT 烘焙是精確的,因為這裡的每個 filter 都是逐像素的點運算: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.

相關技能