Get this effect
Switch to Code in your Claude Desktop App
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/skillsAsk for the effect
Add a glow outline to input.mp4 Second the outline starts fading in: 0.5 Seconds the fade-in takes: 0.4
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 glow outline 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 |
|---|---|---|
START | 0.5 | Second the outline starts fading in. |
FADE | 0.4 | Seconds the fade-in takes. |
COLOR | (255, 40, 150) | Outline and glow color. |
LINE | 6 | Outline thickness in pixels, just outside the subject's edge. |
HALO | 18 | Blur radius of the soft glow around the line, in pixels. |
PULSE | 1.2 | Seconds per breath of the glow, which swings between 70% and 100% strength. |
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
Add a glow outline to input.mp4 (540x960, the camera circles a serum bottle that stands in the middle of the frame, from about 33% to 70% across and 21% to 80% down). Nothing changes before 0.5 seconds. On every frame from 0.5 seconds, cut the bottle out with rembg (u2net model) and threshold its mask at 128. Make a ring just outside the bottle by dilating the mask with a 13x13 elliptical kernel (6 pixels) and subtracting the mask, and a halo by Gaussian-blurring that ring with sigma 18 and scaling it so its peak is 1. The overlay opacity is the larger of the ring (fully opaque) and the halo times 1.3 times a breathing factor, capped at 0.8; the breathing factor is 0.85 + 0.15 * cos(2 * pi * (t - 0.5) / 1.2). Set the opacity to 0 on the bottle itself so the bottle stays untouched, multiply it by a fade-in that goes from 0 at 0.5 seconds to 1 at 0.9 seconds, and blend hot pink (255, 40, 150) over the frame with it. Leave the rest of the frame unchanged. Use Python with numpy, OpenCV and rembg, with ffmpeg to read and write the video (don't use ffmpeg's drawtext); keep the size, 30fps and the audio, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as glow-outline.py and run:
python3 glow-outline.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Glow outline: a neon pink line with a soft halo hugs the subject's edge and follows it as it moves.
Usage: python3 glow-outline.py input.mp4 output.mp4
Needs ffmpeg, numpy, OpenCV and rembg to cut the subject out of every frame
(pip install numpy opencv-python-headless "rembg[cpu]"; rembg downloads its u2net model on first use).
"""
import json
import math
import subprocess
import sys
import cv2
import numpy as np
from PIL import Image
from rembg import new_session
START = 0.5 # second the outline starts fading in
FADE = 0.4 # seconds the fade-in takes
COLOR = (255, 40, 150) # outline color
LINE = 6 # outline thickness in pixels, drawn just outside the subject's edge
HALO = 18 # blur radius of the soft glow around the line, in pixels
PULSE = 1.2 # seconds per breath of the glow (it swings between 70% and 100% strength)
def outline_alpha(rgb):
"""Opacity of the line and its halo for one frame: a ring just outside the subject, blurred into a glow."""
subject = (np.asarray(session.predict(Image.fromarray(rgb))[0]) > 128).astype(np.uint8)
grow = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2 * LINE + 1, 2 * LINE + 1))
ring = (cv2.dilate(subject, grow) - subject).astype(np.float32)
halo = cv2.GaussianBlur(ring, (0, 0), HALO)
halo /= max(halo.max(), 1e-6)
return ring, halo, subject.astype(np.float32)
def composite(rgb, t):
"""Frame, then the halo and line in COLOR, kept off the subject itself."""
if t < START:
return rgb
fade = min((t - START) / FADE, 1)
breath = 0.85 + 0.15 * math.cos(2 * math.pi * (t - START) / PULSE)
ring, halo, subject = outline_alpha(rgb)
alpha = np.maximum(ring, np.minimum(halo * 1.3 * breath, 0.8)) * (1 - subject) * fade
alpha = alpha[:, :, None]
return (rgb * (1 - alpha) + np.array(COLOR, np.float32) * alpha).round().astype(np.uint8)
def probe(path):
info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
"stream=width,height,r_frame_rate", "-of", "json", path]))
s = info["streams"][0]
num, den = s["r_frame_rate"].split("/")
return s["width"], s["height"], s["r_frame_rate"], float(num) / float(den)
def render(src, out):
"""Read src frame by frame, composite each one and save to out, keeping the audio."""
reader = subprocess.Popen(["ffmpeg", "-v", "error", "-i", src, "-f", "rawvideo", "-pix_fmt", "rgb24", "-"],
stdout=subprocess.PIPE)
writer = subprocess.Popen(["ffmpeg", "-y", "-v", "error",
"-f", "rawvideo", "-pix_fmt", "rgb24", "-s", f"{w}x{h}", "-r", rate, "-i", "-",
"-i", src, "-map", "0:v", "-map", "1:a?", "-c:v", "libx264", "-crf", "18",
"-pix_fmt", "yuv420p", "-c:a", "copy", "-shortest", out], stdin=subprocess.PIPE)
i = 0
while raw := reader.stdout.read(w * h * 3):
rgb = np.frombuffer(raw, np.uint8).reshape(h, w, 3)
writer.stdin.write(composite(rgb, i / fps).tobytes())
i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
sys.exit("ffmpeg failed")
src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
session = new_session("u2net")
render(src, out)





