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 film leader countdown to input.mp4 First number; the leader counts down to 2: 8 How long each number stays (a real leader uses 1): 0.5
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 film leader countdown 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 |
|---|---|---|
COUNT_FROM | 8 | First number; the leader counts down to 2. |
NUMBER_SECONDS | 0.5 | How long each number stays (a real leader uses 1). |
LEADER | (150, 150, 150) | Gray of the film leader. |
SWEPT | (95, 95, 95) | Darker gray the sweeping hand leaves behind. |
GRAIN | 9 | Strength of the film grain; 0 for none. |
POP | 1000 | Pitch in Hz of the beep on the 2; 0 for silence. |
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
Put a film leader countdown before input.mp4. For 3.5 seconds at 30 fps, show gray (150, 150, 150) film leader at the video's size with the numbers 8, 7, 6, 5, 4, 3, 2 for 0.5 seconds each: a black (20, 20, 20) bold number about 45% of the frame width tall (font size 62% of the width), centered in the frame. Behind it, a darker gray (95, 95, 95) wedge centered on the frame sweeps clockwise from 12 o'clock through a full turn over each number's 0.5 seconds and reaches past the frame edges, so the frame turns dark gray behind the hand. Over the wedge draw a light (235, 235, 235) crosshair through the center, lines 0.6% of the width thick, and two (245, 245, 245) rings centered on the frame, radius 40% and 34.4% of the frame width, 1.1% of the width thick. Make every frame look like worn film: random brightness flicker of up to 4%, gray film grain (normal noise, standard deviation 9), one to three thin light vertical scratches, a few small black or white dust specks and a 2-pixel up-and-down gate weave. The leader is silent apart from a 1000 Hz beep 0.05 seconds long at 3.0 seconds, as the 2 appears. Then play the whole of input.mp4 with its own audio, so the result is 3.5 seconds longer than the input. Use Python with Pillow and numpy to draw the leader frames and ffmpeg to join them to the video (don't rely on ffmpeg's drawtext filter), and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as film-leader-countdown.py and run:
python3 film-leader-countdown.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Film leader countdown: a sweeping hand counts 8 down to 2 over scratchy gray film leader, then the video starts.
Usage: python3 film-leader-countdown.py input.mp4 output.mp4 (the input needs an audio track)
Needs ffmpeg, Pillow and numpy (pip install pillow numpy).
"""
import json
import subprocess
import sys
from pathlib import Path
import numpy as np
from PIL import Image, ImageDraw, ImageFont
COUNT_FROM = 8 # first number; the leader counts down to 2, like a real Academy leader
NUMBER_SECONDS = 0.5 # how long each number stays (a real leader uses 1)
LEADER = (150, 150, 150) # gray of the film leader
SWEPT = (95, 95, 95) # darker gray the hand leaves behind as it sweeps
GRAIN = 9 # strength of the film grain (0 for none)
POP = 1000 # pitch in Hz of the short beep on the 2; 0 for silence
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")
rng = np.random.default_rng(8)
def leader_frame(t):
number, p = COUNT_FROM - int(t / NUMBER_SECONDS), t / NUMBER_SECONDS % 1 # p: how far round the hand is
img = Image.new("RGB", (w, h), LEADER)
draw = ImageDraw.Draw(img)
cx, cy, r = w / 2, h / 2, w * 0.40
big = r * 3 # the wedge reaches the frame edges
if p > 0:
draw.pieslice([cx - big, cy - big, cx + big, cy + big], -90, -90 + 360 * p, fill=SWEPT)
line = max(2, round(w * 0.006))
draw.line([0, cy, w, cy], fill=(235, 235, 235), width=line) # crosshair
draw.line([cx, 0, cx, h], fill=(235, 235, 235), width=line)
for ring in (r, r * 0.86): # double ring round the number
draw.ellipse([cx - ring, cy - ring, cx + ring, cy + ring], outline=(245, 245, 245), width=line * 2)
font = ImageFont.truetype(FONT_FILE, round(w * 0.62))
draw.text((cx, cy), str(number), font=font, anchor="mm", fill=(20, 20, 20))
return wear(np.asarray(img, np.float32))
def wear(px):
"""Grain, flicker, dust and a scratch or two, so it looks like old film run through a projector."""
px = px * rng.uniform(0.96, 1.04) + rng.normal(0, GRAIN, (h, w, 1))
for _ in range(rng.integers(1, 4)): # vertical scratches
x = rng.integers(0, w)
px[:, x:x + 2] = px[:, x:x + 2] * 0.5 + 115
for _ in range(rng.integers(3, 9)): # dust specks
x, y, s = rng.integers(0, w - 6), rng.integers(0, h - 6), rng.integers(2, 6)
px[y:y + s, x:x + s] = rng.choice([15, 230])
shift = rng.integers(-2, 3) # gate weave
return np.roll(px, shift, axis=0).clip(0, 255).astype(np.uint8).tobytes()
def probe(path):
info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
"stream=width,height", "-of", "json", path]))
return info["streams"][0]["width"], info["streams"][0]["height"]
src, out = sys.argv[1:3]
w, h = probe(src)
length = (COUNT_FROM - 1) * NUMBER_SECONDS
# leader frames come in on stdin, the beep on the 2 from a tone generator, then both are joined to the video
pop_at = length - NUMBER_SECONDS
beep = f"0.5*sin(2*PI*{POP}*t)*between(t,{pop_at},{pop_at + 0.05})"
ff = subprocess.Popen(["ffmpeg", "-y", "-v", "error",
"-f", "rawvideo", "-pix_fmt", "rgb24", "-s", f"{w}x{h}", "-r", "30", "-i", "-",
"-f", "lavfi", "-i", f"aevalsrc='{beep}':s=48000:d={length}",
"-i", src,
"-filter_complex", "[0:v]setsar=1[c];[2:v]fps=30,setsar=1[v];[1:a]aformat=channel_layouts=stereo[b];"
"[2:a]aformat=sample_rates=48000:channel_layouts=stereo[a];"
"[c][b][v][a]concat=n=2:v=1:a=1[joined][outa];[joined]format=yuv420p[outv]",
"-map", "[outv]", "-map", "[outa]", "-c:v", "libx264", "-crf", "18", "-c:a", "aac", out],
stdin=subprocess.PIPE)
for i in range(round(length * 30)):
ff.stdin.write(leader_frame(i / 30))
ff.stdin.close()
if ff.wait():
sys.exit("ffmpeg failed")





