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 speed lines to input.mp4 Seconds the lines are on screen: 1.0, 4.0 Streaks in each frame: 90
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 speed lines 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, END | 1.0, 4.0 | Seconds the lines are on screen. |
COUNT | 90 | Streaks in each frame. More reads as faster. |
REACH | (0.58, 0.85) | How far in the streak tips reach (1 = the frame edge). Raise it to leave more of the middle clear. |
WIDTH | (3, 14) | Streak width at the frame edge, in pixels. |
COLOR | (255, 255, 255) | Streak color. Black suits bright, white scenes. |
EDGE_DIM | 0.75 | Picture brightness at the corners while the lines are on (1 = no darkening). |
REDRAW | 2 | Frames between new arrangements. 1 flickers hardest. |
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 anime speed lines to input.mp4 from 1.0 to 4.0 seconds. Each frame, draw 90 pure white (255, 255, 255) thin wedges with Python and Pillow: each at a random angle around the frame center, 3 to 14 pixels wide where it leaves the frame and tapering to a point. The point sits on an oval the shape of the frame, at a random 58% to 85% of the way from the center to the edge, so an oval in the middle (out to 58% of the half-width and half-height) stays completely clear. Give each wedge a random opacity of 75% to 100% and soften the layer with a 0.6 pixel blur. Draw a new random arrangement every 2 frames so the lines flicker. While the lines are on, darken the picture toward the edges: unchanged inside 50% of the way from the center, falling to 75% brightness at the corners. Before 1.0s and from 4.0s on the video must be unchanged. Don't use ffmpeg's drawtext filter. Keep the size, 30fps, length and audio, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as speed-lines.py and run:
python3 speed-lines.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Speed lines: from 1 to 4 seconds, flickering white anime streaks point in from every edge, leaving the middle clear.
Usage: python3 speed-lines.py input.mp4 output.mp4
Needs ffmpeg, numpy and Pillow (pip install numpy pillow).
"""
import json
import math
import subprocess
import sys
import numpy as np
from PIL import Image, ImageDraw, ImageFilter
START, END = 1.0, 4.0 # seconds the lines are on screen
COUNT = 90 # streaks in each frame
REACH = (0.58, 0.85) # how far in the streak tips reach: 1 = the frame edge, 0 = the center
WIDTH = (3, 14) # streak width where it leaves the frame, in pixels (thinnest, thickest)
COLOR = (255, 255, 255) # streak color
EDGE_DIM = 0.75 # the picture's brightness at the corners while the lines are on, so they stand out
REDRAW = 2 # new arrangement every this many frames, which makes them flicker
SEED = 3 # change for a different arrangement
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 lines(rng):
"""One frame of streaks as an opacity layer (0-1): thin wedges, wide at the edge, pointed at the tip."""
layer = Image.new("L", (w, h))
draw = ImageDraw.Draw(layer)
cx, cy = w / 2, h / 2
for _ in range(COUNT):
a = rng.uniform(0, 2 * math.pi)
tip = rng.uniform(*REACH)
half = rng.uniform(*WIDTH) / 2
dx, dy = math.cos(a), math.sin(a)
# the tip sits on an oval the shape of the frame, so the clear middle fits portrait and landscape alike
x0, y0 = cx + dx * cx * tip, cy + dy * cy * tip
x1, y1 = cx + dx * cx * 1.5, cy + dy * cy * 1.5 # well past the edge
nx, ny = -dy * half, dx * half
draw.polygon([(x0, y0), (x1 + nx, y1 + ny), (x1 - nx, y1 - ny)], fill=round(255 * rng.uniform(0.75, 1)))
return np.asarray(layer.filter(ImageFilter.GaussianBlur(0.6)), np.float32)[..., None] / 255
src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
rng = np.random.default_rng(SEED)
color = np.array(COLOR, np.float32)
# 1 in the middle of the frame, falling to EDGE_DIM toward the edges and corners
ys, xs = np.mgrid[0:h, 0:w]
r = np.hypot(xs / (w / 2) - 1, ys / (h / 2) - 1)
dim = (1 - (1 - EDGE_DIM) * np.clip((r - 0.5) / 0.9, 0, 1)).astype(np.float32)[..., None]
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", "16", "-pix_fmt", "yuv420p", "-c:a", "copy", "-shortest", out],
stdin=subprocess.PIPE)
i, alpha = 0, None
while raw := reader.stdout.read(w * h * 3):
img = np.frombuffer(raw, np.uint8).reshape(h, w, 3)
if START <= i / fps < END:
if alpha is None or i % REDRAW == 0:
alpha = lines(rng)
img = (img * dim * (1 - alpha) + color * alpha).astype(np.uint8)
writer.stdin.write(img.tobytes())
i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
sys.exit("ffmpeg failed")





