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 speed ramp to input.mp4 Speed of the fast parts (2.5 = two and a half times real time): 2.5 Speed on the key moment (0.3 = 30% of real time): 0.3
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 speed ramp 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 |
|---|---|---|
FAST | 2.5 | Speed of the fast parts (2.5 = two and a half times real time). |
SLOW | 0.3 | Speed on the key moment (0.3 = 30% of real time). |
MOMENT | 2.0 | Second of the input the slow motion starts at. |
MOMENT_LEN | 0.6 | Seconds of the input played in slow motion. |
EASE | 0.4 | Seconds of the input each change of speed is spread over. |
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 speed ramp to input.mp4 (540x960, 30fps, 6 seconds). Change the playback speed by where you are in the input: 2.5x from input 0 to 1.6s; ease linearly from 2.5x down to 0.3x across input 1.6 to 2.0s; 0.3x (slow motion) from input 2.0 to 2.6s; ease linearly back up from 0.3x to 2.5x across input 2.6 to 3.0s; then 2.5x to the end. Work out which input time each output frame shows by adding up 1/speed over the input, so the output is about 4.6 seconds: input 2.0s lands at output 1.02s, input 2.6s at 3.02s, and input 6.0s at 4.61s. Make every output frame at 30fps by averaging the input it sweeps past (2-3 frames in the fast parts, for a little motion blur) and, in slow motion, by blending the two nearest input frames so it stays smooth. Don't crop, zoom or add anything to the picture, and don't add any text. Keep the input's audio playing normally (not sped up or slowed down), cut to the new length with a 0.3-second fade-out at the end. Keep the size and frame rate, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as speed-ramp.py and run:
python3 speed-ramp.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Speed ramp: race through the shot at 2.5x, ease into slow motion on the key moment, then race out again.
Usage: python3 speed-ramp.py input.mp4 output.mp4
Needs ffmpeg and numpy (pip install numpy).
"""
import json
import subprocess
import sys
import numpy as np
FAST = 2.5 # speed of the fast parts (2.5 = two and a half times real time)
SLOW = 0.3 # speed on the key moment (0.3 = 30% of real time)
MOMENT = 2.0 # second of the input the slow motion starts at
MOMENT_LEN = 0.6 # seconds of the input played in slow motion
EASE = 0.4 # seconds of the input each change of speed is spread over
def speed(x):
"""Playback speed at input second x: FAST, easing down to SLOW for the moment, then back up."""
down = np.clip((x - (MOMENT - EASE)) / EASE, 0, 1)
up = np.clip((x - (MOMENT + MOMENT_LEN)) / EASE, 0, 1)
return FAST + (SLOW - FAST) * (down - up)
def input_times(duration, fps):
"""The input second shown on each output frame: walk the input in small steps, adding up 1/speed."""
xs = np.arange(0, duration, 0.001)
out_t = np.concatenate([[0], np.cumsum(0.001 / speed(xs[:-1]))])
frames = np.arange(0, out_t[-1], 1 / fps)
return np.interp(frames, out_t, xs)
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 read_frames(src):
raw = subprocess.check_output(["ffmpeg", "-v", "error", "-i", src, "-f", "rawvideo", "-pix_fmt", "rgb24", "-"])
return np.frombuffer(raw, np.uint8).reshape(-1, h, w, 3)
def render(src, out):
"""Write one frame per output time. Each frame averages the input it sweeps past, so the fast parts
get a natural motion blur, and in slow motion it blends the two nearest input frames to stay smooth."""
frames = read_frames(src)
times = input_times(len(frames) / fps, fps)
length = len(times) / fps
def at(x):
pos = min(x * fps, len(frames) - 1)
i, mix = int(pos), pos - int(pos)
return frames[i] * (1 - mix) + frames[min(i + 1, len(frames) - 1)] * mix
ff = 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?",
"-af", f"atrim=0:{length:.3f},afade=t=out:st={length - 0.3:.3f}:d=0.3",
"-c:v", "libx264", "-crf", "18", "-pix_fmt", "yuv420p", "-c:a", "aac", out],
stdin=subprocess.PIPE)
for x, sweep in zip(times, np.diff(times, append=times[-1])):
steps = max(1, round(sweep * fps))
frame = sum(at(x + sweep * k / steps) for k in range(steps)) / steps
ff.stdin.write(frame.astype(np.uint8).tobytes())
ff.stdin.close()
if ff.wait():
sys.exit("ffmpeg failed")
src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
render(src, out)





