Skip to content

Repository files navigation

REFGRADE

AI reference-match grading companion for DaVinci Resolve Studio (built against the Resolve 20/21 scripting API). Drop a reference image into a chat, and Claude — acting as a colorist — computes a deterministic color match, bakes it into a 3D LUT (+ a DCTL with a Strength slider), applies it to your clip's node graph, looks at a verification still of the actual result, and iterates with CDL trims until it matches.

Split brain: Claude makes the taste decisions (strategy, strengths, protection, critique). Deterministic math produces the pixels — Monge-Kantorovich / Reinhard / CDF matching computed in Oklab (perceptually uniform), with tone and color matched independently (match the palette without touching your contrast, or vice versa). Everything bakes into a LUT: temporally stable, render-safe.

How a turn works: Claude first renders 3-4 candidate recipes locally (free, no Resolve round-trip) as a scored contact sheet, applies the winner to your MATCH node, reads a verification still plus an objective match report (sliced-Wasserstein score + per-zone Oklab deltas vs the reference), and lands residuals with one CDL trim. Say "apply it to the whole timeline" and the match rolls out to every clip on video track 1 with sample-clip verification stills. For exact duplication ("nail this, 99% on target") the idt engine converges the full color distribution onto the reference - measured at 99%+ through the baked LUT.

Also built in: multi-frame sampling (match statistics come from stills sampled across the clip, so camera moves don't skew the match - sample_frames in config), progressive results (plates land in the panel as each tool round completes), A/B wipe (hover any verification plate to sweep it against the reference, double-click to zoom), and taste memory (say "always keep wood warm" once - Claude records it and applies it in every future session).


Requirements

  • DaVinci Resolve Studio (free version does not allow external scripting)
  • macOS or Windows, Python 3.10+
  • An Anthropic API key (https://platform.claude.com)

The API key is stored in your system credential store (macOS Keychain / Windows Credential Manager). All Resolve paths (LUT folder, scripting modules, plugin folder) resolve per-platform automatically.

LLM gateways supported: set API base URL in Settings (any Anthropic-compatible proxy, e.g. https://your-gateway.example/v1) and paste the gateway token as the key — it is then sent as a bearer token instead of an x-api-key. Leave the base URL empty for a standard sk-ant-… key against api.anthropic.com.

One-time setup

  1. Resolve preferences — Preferences → System → General → External scripting usingLocal. Restart Resolve.

  2. Node convention — REFGRADE owns the last two nodes of each clip it grades:

    • second-to-last node → match LUT (label it REFGRADE MATCH)
    • last node → CDL trim (label it REFGRADE TRIM)

    Set up ONE clip exactly how every clip should start (your CST + the two REFGRADE nodes), open it on the Color page, and hit Settings → Capture from current clip. That saves a .drx node template; from then on the agent's prep clip and timeline rollout apply it automatically (note: applying the template REPLACES a clip's existing grade — that's its job). If a clip has only one node, REFGRADE uses it for both (works, but match + trim share a node).

  3. API key — launch the app, open Settings, paste your key (stored in macOS Keychain, never on disk in plaintext).

Deploying to the Resolve machine

Run ./make-release.command to build dist/refgrade-vX.Y.Z.zip (code only, no local state). Copy it over, unzip anywhere, then run the installer below from inside the unzipped folder. Your API key/gateway settings are per-machine: enter them once in the panel's Settings on the target.

Install as a Resolve plugin (recommended)

macOS:

cd ~/Desktop/refgrade
./install-plugin.command

Windows (may need an elevated "Run as administrator" PowerShell to write into ProgramData):

cd path\to\refgrade
powershell -ExecutionPolicy Bypass -File .\install-plugin.ps1

This registers REFGRADE as a Workflow Integration plugin: it copies plugin/com.refgrade.panel/ into Resolve's plugins folder, pulls the version-matched WorkflowIntegration.node from Resolve's own developer samples, and points the plugin at this repo's Python engine. Then restart Resolve and open Workspace > Workflow Integrations > REFGRADE. The panel starts the grading engine automatically (log: engine.log in this folder) and shuts it down when you close the panel. Re-run the installer after a Resolve upgrade (to refresh WorkflowIntegration.node) or if you move this folder or change the port.

Run standalone (without the plugin)

cd ~/Desktop/refgrade
./run.command        # macOS — first run creates .venv and installs deps
run.bat              # Windows equivalent

Open http://127.0.0.1:8765. Either way, have Resolve running with your clip open on the Color page, drop a reference image, and type what you want:

"Match this, but keep it subtle and don't let the wood go orange." "More like the reference's shadows, but protect the sofa fabric." "Less contrast, warmer highlights."

Each turn, REFGRADE grabs a still, computes, applies, grabs a verification still, lets Claude critique it against the reference, and trims. Generated LUTs land in …/DaVinci Resolve/LUT/REFGRADE/ — a .cube (applied automatically) plus a matching .dctl you can apply manually instead if you want a live Strength slider on the node.

Color pipeline (read this once)

Your footage is linear EXR out of V-Ray/Vantage; a 3D LUT lives in a 0–1 box. Two modes (Settings → Grade domain):

  • display (default) — matching happens on display-referred stills (exactly what you see in the viewer), and the LUT expects display-referred input. The REFGRADE nodes must therefore be LAST in the node chain, after your CST / tone-mapping node. This is the robust choice for unmanaged timelines with a CST per clip, and the verification loop self-corrects small discrepancies.
  • scene_di — matching happens in DaVinci Intermediate log; the generated DCTL wraps linear→DI→LUT→DI⁻¹→linear. For color-managed timelines where node input is scene-linear. Set Source colorimetry to acescg if your EXRs are ACEScg. In this mode, prefer applying the generated .dctl (it does the linearization); the raw .cube alone would clip super-white detail.

Tests (no Resolve needed)

./.venv/bin/python -m tests.test_engine

First run on the Resolve machine? Run the doctor

./.venv/bin/python -m refgrade.doctor      # macOS
.venv\Scripts\python.exe -m refgrade.doctor  # Windows

With Resolve open and a clip on the Color page, it exercises every API call REFGRADE depends on (connection, stills, LUT apply, CDL, .drx capture, timeline enumeration, API key) and prints PASS/FAIL per step. Safe: its only writes are an identity LUT (visual no-op, restored where possible) and a neutral CDL.

Troubleshooting

  • Anything misbehaving — run the doctor (above) first; send the FAIL lines.
  • "Could not connect to DaVinci Resolve" — Resolve running? Studio? External scripting set to Local? A project open?
  • "SetLUT failed" — the clip must be the current clip on the Color page, and the node index must exist (add the two REFGRADE nodes). LUTs are also listed under the LUT browser → REFGRADE if you want to check they registered.
  • Result in the viewer doesn't match the verification still — grade domain mismatch; see the pipeline section above.
  • Stills look double-graded — the REFGRADE nodes weren't bypassed during the "before" grab; make sure the node indices in config match where the nodes actually are.

Layout

refgrade/
├── refgrade/
│   ├── app.py             Flask server + orchestration + tool executor
│   ├── colorist.py        Claude agent (system prompt, tools, loop)
│   ├── resolve_bridge.py  Resolve scripting API wrapper
│   ├── transfer.py        Matching engines in Oklab (mkl / reinhard / hist / hybrid)
│   ├── metrics.py         Sliced-Wasserstein match score + zone deltas
│   ├── lutbake.py         .cube writer + trilinear sampler (tests)
│   ├── dctl.py            DCTL generator (strength slider)
│   ├── imaging.py         EXR/PNG IO, analysis domains, stats
│   ├── spaces.py          DaVinci Intermediate log, sRGB, ACEScg, hue math
│   ├── config.py          settings + Keychain key storage
│   └── ui/index.html      chat panel
├── plugin/com.refgrade.panel/   Resolve Workflow Integration plugin
│   ├── manifest.xml       plugin registration (id, name, entry point)
│   ├── main.js            Resolve-hosted Electron main: engine supervisor + window
│   └── index.html         boot splash / engine error screens
├── tests/                 engine + stress tests (offline)
├── install-plugin.command installs the plugin into Resolve
└── run.command            standalone launcher

How the plugin works: Resolve launches main.js with its bundled Electron. The plugin health-checks the engine at 127.0.0.1:8765, spawns .venv/bin/python -m refgrade.app if it isn't running (reusing an already running engine otherwise), shows a boot splash, then loads the panel UI in the plugin window. Closing the panel stops the engine only if the plugin started it. WorkflowIntegration.node is used for plugin registration and the ResolveQuit callback; grading traffic goes through the Python scripting bridge, so the external-scripting preference must stay on Local.

Roadmap: image-model creative engine with LUT-fitting (v2) · IDT / true-OT match engines · multi-frame sampling · semantic-weighted matching.

About

REFGRADE — AI reference-match color grading for DaVinci Resolve Studio. Claude-driven colorist panel: drop a reference, it matches, bakes LUTs, verifies, iterates.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages