How to add a color replace with Claude

At 1 second the purple serum fades to amber orange inside its glass, while the pastel holographic backdrop and clear block keep their original colors.

Get this effect

  1. Switch to Code in your Claude Desktop App

  2. Install the skill (once)

    Show the prompt
    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

    Add a color replace to input.mp4
    Hue range to replace, on OpenCV's 0-180 scale: (118, 158)
    Pixels less saturated than this keep their color, so pale tints of the same hue are left alone: 60

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 replace 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.

SettingDefaultWhat it does
FROM_HUE(118, 158)Hue range to replace, on OpenCV's 0-180 scale. 118-158 is the bottle's purple.
MIN_SAT60Pixels less saturated than this keep their color, so pale tints of the same hue are left alone.
SOFT8How gradually the mask fades at the edges of the hue and saturation ranges.
TO_HUE18The new hue, 0-180. 18 is amber orange; 60 is green, 100 blue.
SAT_BOOST1.6Saturation multiplier on the new color. 1 keeps the original strength.
START1.0Second the new color starts fading in. 0 replaces it from the first frame.
FADE0.4Seconds the change takes.

Without the skill

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

Show the prompt
In input.mp4, replace the bottle's purple with amber orange using Python and OpenCV. Convert each frame to HSV (OpenCV scale, hue 0-180) and select pixels with hue between 118 and 158 and saturation above 60, fading the mask over 8 units at both edges and blurring it with a 5x5 Gaussian so the edges don't band. In those pixels set the hue to 18 (amber orange) and multiply the saturation by 1.6, keeping the brightness. Leave the first second untouched, then fade the new color in from 1.0 to 1.4 seconds and keep it to the end. Everything less saturated, like the pale lilac backdrop, keeps its color. No text is drawn (if you add any, draw it with Pillow, not ffmpeg's drawtext). Keep the size, 30fps, the 6-second length and the audio, and save it as output.mp4.

Run it without Claude

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

python3 color-replace.py input.mp4 output.mp4
Show the script
#!/usr/bin/env python3
"""Color replace: at 1 second the purple bottle turns amber orange while the pastel backdrop keeps its colors.

Usage: python3 color-replace.py input.mp4 output.mp4
Needs ffmpeg, OpenCV and numpy (pip install opencv-python-headless numpy).
"""
import subprocess
import sys

import cv2
import numpy as np

FROM_HUE = (118, 158)   # hue range to replace, OpenCV scale 0-180 (here the bottle's purple, 236-316 degrees)
MIN_SAT = 60            # pixels less saturated than this keep their color (the pale lilac backdrop)
SOFT = 8                # hue and saturation units over which the mask fades, so edges don't band
TO_HUE = 18             # new hue, 0-180 (18 = amber orange, 36 degrees)
SAT_BOOST = 1.6         # saturation multiplier on the replaced color
START = 1.0             # second the new color starts fading in
FADE = 0.4              # seconds the change takes


def mask_of(hsv):
    """0-1 weight per pixel: how much it belongs to the color being replaced."""
    h, s = hsv[..., 0].astype(np.float32), hsv[..., 1].astype(np.float32)
    in_hue = np.clip(np.minimum(h - FROM_HUE[0], FROM_HUE[1] - h) / SOFT + 0.5, 0, 1)
    in_sat = np.clip((s - MIN_SAT) / SOFT + 0.5, 0, 1)
    return cv2.GaussianBlur(in_hue * in_sat, (5, 5), 0)[..., None]


def recolor(frame, amount):
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    swapped = hsv.copy()
    swapped[..., 0] = TO_HUE
    swapped[..., 1] = np.clip(hsv[..., 1] * SAT_BOOST, 0, 255)
    new = cv2.cvtColor(swapped, cv2.COLOR_HSV2BGR).astype(np.float32)
    weight = mask_of(hsv) * amount
    return (frame * (1 - weight) + new * weight).astype(np.uint8)


src, out = sys.argv[1:3]
video = cv2.VideoCapture(src)
fps = video.get(cv2.CAP_PROP_FPS)
w, h = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
ff = subprocess.Popen(["ffmpeg", "-y", "-v", "error", "-f", "rawvideo", "-pix_fmt", "bgr24", "-s", f"{w}x{h}",
                       "-r", str(fps), "-i", "-", "-i", src, "-map", "0:v", "-map", "1:a?", "-shortest",
                       "-c:v", "libx264", "-crf", "18", "-pix_fmt", "yuv420p", "-c:a", "copy", out],
                      stdin=subprocess.PIPE)
i = 0
while True:
    ok, frame = video.read()
    if not ok:
        break
    amount = min(max((i / fps - START) / FADE, 0), 1)
    ff.stdin.write((recolor(frame, amount) if amount else frame).tobytes())
    i += 1
ff.stdin.close()
if ff.wait():
    sys.exit("ffmpeg failed")

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