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 verified badge to input.mp4 Name: Maya R. Label: Verified buyer Quote: “My skin glows after one week.”
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 verified badge 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 |
|---|---|---|
NAME | Maya R. | Reviewer's name; the badge sits right after it. |
LABEL | Verified buyer | Words that fade in next to the badge. |
QUOTE | “My skin glows after one week.” | The review line under the name. |
BADGE_IN | 1.2 | Second the badge pops in. |
CARD_Y | 0.78 | Card center, 0-1 down the frame. |
GREEN | (22, 163, 74) | Badge and label color. |
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 verified-buyer review card to input.mp4 (540x960). The card is white, 432x132 pixels with 22-pixel rounded corners, centered across with its center 78% down the frame. On it: a purple (124, 92, 210) circle avatar 64 pixels across, 20 pixels in from the card's left edge, with a white bold "M"; the name "Maya R." in 28-pixel bold dark gray (25, 25, 35) starting 100 pixels in, 42 pixels from the card's top; and under it, 78 pixels from the top, the quote “My skin glows after one week.” in 19-pixel bold gray (80, 80, 95). The card fades in from 0.3 to 0.6 seconds. At 1.2 seconds a green (22, 163, 74) circle 30 pixels across with a white tick pops in centered 22 pixels after the end of the name, on the name's line, scaling up over 0.3 seconds with a slight overshoot; the words "Verified buyer" in 19-pixel bold of the same green fade in just right of it from 1.35 to 1.6 seconds. Everything then stays to the end. Use Python with Pillow to draw it and ffmpeg to put it on the video (don't use ffmpeg's drawtext filter), keep the audio, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as verified-badge.py and run:
python3 verified-badge.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Verified badge: a green checkmark badge pops in beside a reviewer's name on a review card.
Usage: python3 recipe.py input.mp4 output.mp4
Needs ffmpeg and Pillow (pip install pillow).
"""
import json
import math
import subprocess
import sys
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
NAME = "Maya R." # reviewer's name
LABEL = "Verified buyer" # words that appear next to the badge
QUOTE = "\u201cMy skin glows after one week.\u201d" # the review line under the name
CARD_IN = 0.3 # second the card fades in
BADGE_IN = 1.2 # second the badge pops in beside the name
POP = 0.3 # seconds the pop takes
CARD_W = 0.80 # card width as a share of the frame width
CARD_Y = 0.78 # card center, 0-1 down the frame
GREEN = (22, 163, 74) # badge and label color
FONTS = ["/System/Library/Fonts/Supplemental/Arial Bold.ttf", # macOS
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", # Linux
"C:/Windows/Fonts/arialbd.ttf"] # Windows
FONT_FILE = next((f for f in FONTS if Path(f).exists()), None) or sys.exit("No bold font found: add one to FONTS")
def font(size):
return ImageFont.truetype(FONT_FILE, round(size))
def card():
"""The white card with avatar, name and quote; returns it and where the badge goes on it."""
cw = round(w * CARD_W)
u = cw / 432 # layout unit, so the card scales with the frame
ch = round(132 * u)
img = Image.new("RGBA", (cw, ch))
draw = ImageDraw.Draw(img)
draw.rounded_rectangle([0, 0, cw - 1, ch - 1], radius=round(22 * u), fill="white")
draw.ellipse([20 * u, 22 * u, 84 * u, 86 * u], fill=(124, 92, 210))
draw.text((52 * u, 54 * u), NAME[0], font=font(32 * u), anchor="mm", fill="white")
name_font = font(28 * u)
draw.text((100 * u, 42 * u), NAME, font=name_font, anchor="lm", fill=(25, 25, 35))
draw.text((100 * u, 78 * u), QUOTE, font=font(19 * u), anchor="lm", fill=(80, 80, 95))
badge_center = (100 * u + name_font.getlength(NAME) + 22 * u, 42 * u)
return img, badge_center, u
def badge(d):
"""A green disc with a white tick, d pixels across."""
img = Image.new("RGBA", (d, d))
draw = ImageDraw.Draw(img)
draw.ellipse([0, 0, d - 1, d - 1], fill=GREEN)
draw.line([(d * 0.27, d * 0.52), (d * 0.44, d * 0.69), (d * 0.74, d * 0.34)], fill="white",
width=max(2, round(d * 0.13)), joint="curve")
return img
def overlay(t):
img = Image.new("RGBA", (w, h))
if t < CARD_IN:
return img
layer = base.copy()
bx, by = badge_center
scale = ease_out_back((t - BADGE_IN) / POP) if t >= BADGE_IN else 0
if scale > 0.05:
b = tick.resize((max(1, round(tick.width * scale)),) * 2, Image.LANCZOS)
layer.alpha_composite(b, (round(bx - b.width / 2), round(by - b.height / 2)))
fade = min(1, max(0, (t - BADGE_IN - 0.15) / 0.25))
draw = ImageDraw.Draw(layer)
draw.text((bx + 22 * u, by), LABEL, font=font(19 * u), anchor="lm", fill=GREEN + (round(255 * fade),))
alpha = min(1, (t - CARD_IN) / 0.3)
if alpha < 1:
layer.putalpha(layer.getchannel("A").point(lambda a: round(a * alpha)))
img.alpha_composite(layer, ((w - layer.width) // 2, round(h * CARD_Y - layer.height / 2)))
return img
def ease_out_back(p):
"""0 -> 1 with a small overshoot past 1 before settling, which reads as a 'pop'."""
p = min(max(p, 0), 1)
return 1 + 2.70158 * (p - 1) ** 3 + 1.70158 * (p - 1) ** 2
def probe(path):
info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
"stream=width,height,r_frame_rate:format=duration", "-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), float(info["format"]["duration"])
def render(src, out):
"""Draw overlay(t) on every frame of src and save to out, keeping the audio."""
ff = subprocess.Popen(["ffmpeg", "-y", "-v", "error", "-i", src,
"-f", "rawvideo", "-pix_fmt", "rgba", "-s", f"{w}x{h}", "-r", rate, "-i", "-",
"-filter_complex", "[0:v][1:v]overlay=shortest=1,format=yuv420p[v]",
"-map", "[v]", "-map", "0:a?", "-c:v", "libx264", "-crf", "18", "-c:a", "copy", out],
stdin=subprocess.PIPE)
for i in range(math.ceil(duration * fps)):
ff.stdin.write(overlay(i / fps).tobytes())
ff.stdin.close()
if ff.wait():
sys.exit("ffmpeg failed")
src, out = sys.argv[1:3]
w, h, rate, fps, duration = probe(src)
base, badge_center, u = card()
tick = badge(round(30 * u))
render(src, out)





