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 LED screen to input.mp4 Second the picture switches to LEDs: 1.0 Pixels from one LED's center to the next: 15
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 led screen 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 | 1.0 | Second the picture switches to LEDs. |
PITCH | 15 | Pixels from one LED's center to the next. Bigger means fewer, chunkier LEDs. |
DOT | 0.38 | LED radius as a share of PITCH. Smaller leaves wider black gaps. |
GAIN | 1.1 | How much brighter each LED glows than the color it stands for. |
SATURATION | 1.8 | How much richer the LED colors are than the footage (1 = unchanged). |
GLOW | 0.2 | Strength of the soft halo around each LED. |
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
Turn input.mp4 (540x960, 30fps) into an LED screen from 1.0 seconds to the end, using Python with numpy and ffmpeg. Before 1.0 seconds leave the frames untouched. From 1.0 seconds on, split each frame into a grid of 15x15 pixel cells (36 across, 64 down) and average each cell's color. Push that color away from its own gray by 1.8x for richer color and multiply it by 1.1, clipped to 0-255. Then redraw the frame on black: in the center of each cell draw one round LED of radius 5.7 pixels (0.38 of the cell) in that cell's color, with a softly anti-aliased edge and a faint halo at 20% brightness fading out toward the cell edge, so dark gaps show between the dots. Keep the size, 30fps, the 6 second length and the audio. There's no text to draw, but if you add any, draw it with Pillow, not ffmpeg's drawtext. Save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as led-screen.py and run:
python3 led-screen.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""LED screen: at one second the shot is rebuilt from glowing round LED dots on a black panel, like a stadium screen.
Usage: python3 led-screen.py input.mp4 output.mp4
Needs ffmpeg and numpy (pip install numpy).
"""
import json
import subprocess
import sys
import numpy as np
START = 1.0 # second the picture switches to LEDs
PITCH = 15 # pixels from one LED's center to the next (540 / 15 = 36 LEDs across)
DOT = 0.38 # LED radius as a share of PITCH
GAIN = 1.1 # how much brighter each LED glows than the average color it stands for
SATURATION = 1.8 # how much richer each LED's color is than the footage's (1 = unchanged)
GLOW = 0.2 # strength of the soft halo around each LED
def led_cell():
"""One LED as brightness 0-1 over a PITCH x PITCH cell: a bright round core fading into a soft halo."""
y, x = np.mgrid[0:PITCH, 0:PITCH] + 0.5 - PITCH / 2
r = np.hypot(x, y) / (DOT * PITCH)
core = np.clip((1.15 - r) * 4, 0, 1)
halo = GLOW * np.exp(-((r - 1).clip(0) ** 2) * 2.5)
return np.maximum(core, halo).astype(np.float32)
def led_frame(img):
"""Average each PITCH x PITCH cell's color, make it richer, then light that cell's LED in it."""
cells = img[:rows * PITCH, :cols * PITCH].reshape(rows, PITCH, cols, PITCH, 3).mean(axis=(1, 3))
gray = cells.mean(axis=2, keepdims=True)
cells = np.clip((gray + (cells - gray) * SATURATION) * GAIN, 0, 255)
pic = cell[None, :, None, :, None] * cells[:, None, :, None, :]
out = np.zeros_like(img)
out[:rows * PITCH, :cols * PITCH] = pic.reshape(rows * PITCH, cols * PITCH, 3)
return out
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)
src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
cols, rows = w // PITCH, h // PITCH
cell = led_cell()
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):
img = np.frombuffer(raw, np.uint8).reshape(h, w, 3).astype(np.float32)
if i / fps >= START:
img = led_frame(img)
writer.stdin.write(np.clip(img, 0, 255).astype(np.uint8).tobytes())
i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
sys.exit("ffmpeg failed")





