---
title: "How to add a color match with Claude (tested prompt and script)"
description: "The dull gray push-in on the serum label is regraded to match the orbit shot used as reference: its murky backdrop brightens to the reference's pale icy blue and the bottle lifts from a muddy plum to soft lavender, so the two shots cut together. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/color-match
---

# How to add a color match with Claude

The dull gray push-in on the serum label is regraded to match the orbit shot used as reference: its murky backdrop brightens to the reference's pale icy blue and the bottle lifts from a muddy plum to soft lavender, so the two shots cut together.

Made by the script on this page, from our own test clips.

## Get this effect

1. ### Switch to Code in your [Claude Desktop App](https://claude.com/download)

2. ### Install the skill (once)

   ```
   Install the Recharm video effects skill: download https://recharm-growth-staging.s3.us-east-2.amazonaws.com/website/downloads/recharm-video-effects.zip and unzip it into ~/.claude/skills
   ```

3. ### Ask for the effect

   ```
   Make a color match from input.mp4 and reference.mp4
   Reference (second argument): reference.mp4
   ```

## Several videos, several effects, one ask

Put your clips in the folder, mention them with @, and ask for everything at once. Claude runs one tested script after another on each clip, then joins them.

Add a color match to **@clip1.mp4**, put a sale badge on **@clip2.mp4**, give **@clip3.mp4** a VHS look, then join all three with crossfades.

## Settings you can change

Ask Claude to change any of these, or edit them at the top of the script.

| Setting                       | Default         | What it does                                                                                                                                   |
| ----------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `reference (second argument)` | `reference.mp4` | The shot whose look you want. A clip or a still frame (.jpg or .png) both work.                                                                |
| `SAMPLES`                     | `12`            | Frames measured from each clip, spread evenly through it. More gives a steadier average on shots that change a lot.                            |
| `STRENGTH`                    | `1.0`           | How far to go toward the reference. 1 matches it fully, 0.5 goes halfway, 0 leaves the clip as it is.                                          |
| `LUT_SIZE`                    | `33`            | Grid points per axis in the .cube file the correction is baked into. The .cube is saved next to the output, so you can reuse it in any editor. |

## Without the skill

Don’t want to install the skill? Paste this prompt into Claude Code and Claude writes the script itself.

```
Color match input.mp4 to reference.mp4 so the two shots cut together. Use Reinhard color transfer in Lab: take 12 frames spread evenly through each clip, convert them to Lab with OpenCV (float RGB 0-1 into cv2.COLOR_RGB2LAB) and work out the mean and standard deviation of L, a and b over all those pixels. For every color, the matched Lab value is (value - input mean) / input std * reference std + reference mean, per channel. Use one correction for the whole clip, not one per frame, so it can't flicker: bake it into a 33x33x33 .cube LUT (LUT_3D_SIZE 33, red changing fastest, then green, then blue, values clipped to 0-1) and apply it with ffmpeg's lut3d filter (interp=tetrahedral) to every frame from first to last. The dull gray backdrop, around RGB (150, 156, 158), should come out the reference's pale icy blue, around RGB (196, 204, 216), the whole frame about 1.3 times as bright (around 190 out of 255, like the reference), and the purple glass should keep its color as it brightens, from around RGB (80, 73, 87) to around RGB (121, 112, 143), rather than going gray. Don't crop, zoom or add anything else, and don't add any text (if you ever do, draw it with Pillow, not ffmpeg's drawtext). Use Python with opencv-python-headless and numpy for the LUT and ffmpeg for the video. Keep the 540x960 size, 30fps, the 6 second length and the audio, encode H.264 yuv420p and save it as output.mp4.
```

## Run it without Claude

This is the exact script we tested. Save it as `color-match.py` and run:

```
python3 color-match.py input.mp4 reference.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Color match: regrade a clip so its brightness, contrast and color cast match a reference shot.

Usage: python3 color-match.py input.mp4 reference.mp4 output.mp4  (the reference can also be a .jpg or .png)
Needs ffmpeg and Python 3 with OpenCV and numpy (pip install opencv-python-headless numpy).
It measures both shots in Lab color (Reinhard color transfer), bakes the correction into a .cube LUT
next to the output and applies that to every frame with ffmpeg, so the grade can't flicker.
"""
import subprocess
import sys
from pathlib import Path

import cv2
import numpy as np

SAMPLES = 12      # frames measured from each clip (spread evenly through it)
STRENGTH = 1.0    # 1 matches the reference fully, 0.5 goes halfway, 0 leaves the clip as it is
LUT_SIZE = 33     # grid points per axis in the .cube file

def lab_stats(path):
    """Mean and spread of L, a and b over frames sampled evenly through a clip (or one image)."""
    count = subprocess.run(["ffprobe", "-v", "error", "-count_packets", "-select_streams", "v:0", "-show_entries",
                            "stream=nb_read_packets", "-of", "csv=p=0", path], capture_output=True, text=True).stdout
    step = max(1, int(count.strip() or 1) // SAMPLES)
    raw = subprocess.check_output(["ffmpeg", "-v", "error", "-i", path, "-vf", f"select='not(mod(n,{step}))',scale=270:-2",
                                   "-fps_mode", "passthrough", "-frames:v", str(SAMPLES), "-f", "rawvideo", "-pix_fmt", "rgb24", "-"])
    pixels = np.frombuffer(raw, np.uint8).reshape(1, -1, 3).astype(np.float32) / 255
    lab = cv2.cvtColor(pixels, cv2.COLOR_RGB2LAB).reshape(-1, 3)
    return lab.mean(axis=0), lab.std(axis=0)

def write_lut(path, src, ref):
    """A .cube file that moves each Lab channel from the source's mean and spread to the reference's."""
    (src_mean, src_std), (ref_mean, ref_std) = src, ref
    steps = np.linspace(0, 1, LUT_SIZE, dtype=np.float32)
    b, g, r = np.meshgrid(steps, steps, steps, indexing="ij")      # red changes fastest in a .cube file
    rgb = np.stack([r, g, b], axis=-1).reshape(1, -1, 3)
    lab = cv2.cvtColor(rgb, cv2.COLOR_RGB2LAB)
    matched = (lab - src_mean) * (ref_std / np.maximum(src_std, 1e-3)) + ref_mean
    lab = lab + STRENGTH * (matched - lab)
    out = np.clip(cv2.cvtColor(lab.astype(np.float32), cv2.COLOR_LAB2RGB), 0, 1).reshape(-1, 3)
    lines = ['TITLE "color match"', f"LUT_3D_SIZE {LUT_SIZE}"] + [f"{r:.6f} {g:.6f} {b:.6f}" for r, g, b in out]
    Path(path).write_text("\n".join(lines) + "\n")

src, ref, out = sys.argv[1:4]
lut = str(Path(out).with_name("color-match.cube"))
write_lut(lut, lab_stats(src), lab_stats(ref))
subprocess.run(["ffmpeg", "-y", "-v", "error", "-i", src, "-vf", f"lut3d=file='{lut}':interp=tetrahedral",
                "-r", "30", "-c:v", "libx264", "-crf", "18", "-pix_fmt", "yuv420p", "-c:a", "copy", out], check=True)
```

## More color looks

- [Apply a LUT **Apply a LUT**](https://www.recharm.com/effects/apply-a-lut)
- [Black and white **Black and white**](https://www.recharm.com/effects/black-and-white)
- [Bleach bypass **Bleach bypass**](https://www.recharm.com/effects/bleach-bypass)
- [Cinematic color grade **Cinematic color grade**](https://www.recharm.com/effects/cinematic-color-grade)
- [Color pop **Color pop**](https://www.recharm.com/effects/color-pop)

## Find 3x _winning ads_

Recharm cuts your ad footage into tagged, searchable clips: hooks, testimonials, product shots. Find the shots that win, add the effect with Claude, and ship 3x more ad edits.

[Start 14-day free trial](https://www.recharm.com/get-started)
