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 TV static to input.mp4 Second the static starts to break through: 2.0 Seconds from the first speck to the clean picture again: 1.2
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 tv static 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 | 2.0 | Second the static starts to break through. |
LENGTH | 1.2 | Seconds from the first speck to the clean picture again. |
FADE | 0.2 | Seconds the static takes to cover the picture, and to clear. |
GRAIN | 2 | Size of one static speck, in pixels. |
BAND_SPEED | 1.5 | Screen heights per second the bright band rolls down. |
HISS | 0.2 | Loudness of the hiss, 0 to 1. |
DUCK | 0.2 | How loud the clip's own sound stays under the hiss, 0 to 1. |
SEED | 7 | Random seed; change it for a different but repeatable pattern of static. |
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 burst of TV static to input.mp4. Use Python with numpy and ffmpeg, working frame by frame at 30fps. The static runs from 2.0s to 3.2s: it fades in over 0.2 seconds (2.0s to 2.2s), fully covers the picture from 2.2s to 3.0s, and fades out over 0.2 seconds (3.0s to 3.2s), mixed as (1 - p) * picture + p * static. Leave every frame outside 2.0s to 3.2s untouched. Static is black-and-white snow: a random gray value from 0 to 255 for every 2x2 pixel block, new each frame, multiplied by 0.75 plus 0.4 times a horizontal Gaussian band (width 6% of the frame height) that rolls down the screen at 1.5 screen heights per second and wraps back to the top, with every odd row darkened to 80% for scan lines. Sound: keep the clip's audio, turned down to 20% volume from 2.0s to 3.2s, and mix in a white-noise hiss at amplitude 0.2 over the same 1.2 seconds with 0.2 second fades in and out, without normalizing. Use a fixed random seed so it repeats. Keep the video 6 seconds long and save it as output.mp4 (H.264, yuv420p).Run it without Claude
This is the exact script we tested. Save it as tv-static.py and run:
python3 tv-static.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""TV static: halfway through the clip the picture dissolves into hissing black-and-white snow with a bright band rolling down it, then tunes back in.
Usage: python3 tv-static.py input.mp4 output.mp4 (the clip needs an audio track)
Needs ffmpeg and numpy (pip install numpy).
"""
import json
import subprocess
import sys
import numpy as np
START = 2.0 # second the static starts to break through
LENGTH = 1.2 # seconds from the first speck to the clean picture again
FADE = 0.2 # seconds the static takes to cover the picture, and to clear again
GRAIN = 2 # size of one static speck, in pixels
BAND_SPEED = 1.5 # screen heights per second the bright band rolls down the static
HISS = 0.2 # loudness of the static's hiss (0-1)
DUCK = 0.2 # how loud the clip's own sound stays under the hiss (0-1)
SEED = 7 # change for a different (but repeatable) pattern of static
def static(t):
"""One frame of black-and-white snow with scan lines and a bright band that rolls down over time."""
specks = rng.integers(0, 256, (h // GRAIN + 1, w // GRAIN + 1)).astype(np.float32)
snow = specks.repeat(GRAIN, 0).repeat(GRAIN, 1)[:h, :w]
rows = np.arange(h)[:, None]
band = np.exp(-((rows - (t * BAND_SPEED % 1) * h) / (h * 0.06)) ** 2)
snow = snow * (0.75 + 0.4 * band) * np.where(rows % 2, 0.8, 1.0)
return np.repeat(np.clip(snow, 0, 255)[:, :, None], 3, axis=2)
def cover(t):
"""How much of the picture the static hides at time t: 0 outside the burst, 1 at full static."""
into, left = t - START, START + LENGTH - t
return float(np.clip(min(into, left) / FADE, 0, 1))
src, out = sys.argv[1:3]
info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
"stream=width,height", "-of", "json", src]))["streams"][0]
w, h = info["width"], info["height"]
rng = np.random.default_rng(SEED)
# Sound: the clip's own audio drops to DUCK under a white-noise hiss for the length of the static
end = START + LENGTH
sound = (f"[1:a]volume='if(between(t,{START},{end}),{DUCK},1)':eval=frame[a];"
f"anoisesrc=d={LENGTH}:c=white:a={HISS}:r=48000,afade=t=in:d={FADE},afade=t=out:st={LENGTH - FADE}:d={FADE},"
f"adelay={START * 1000:.0f}:all=1[hiss];"
f"[a][hiss]amix=inputs=2:duration=first:normalize=0[au]")
reader = subprocess.Popen(["ffmpeg", "-v", "error", "-i", src, "-vf", "fps=30", "-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", "30", "-i", "-", "-i", src, "-filter_complex", sound, "-map", "0:v", "-map", "[au]",
"-c:v", "libx264", "-crf", "18", "-pix_fmt", "yuv420p", "-c:a", "aac", "-shortest", out],
stdin=subprocess.PIPE)
i = 0
while True:
raw = reader.stdout.read(w * h * 3)
if len(raw) < w * h * 3:
break
img = np.frombuffer(raw, np.uint8).reshape(h, w, 3)
p = cover(i / 30)
if p > 0:
img = ((1 - p) * img + p * static(i / 30)).astype(np.uint8)
writer.stdin.write(img.tobytes())
i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
sys.exit("ffmpeg failed")





