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 an anime style to input.mp4 Second the picture turns into a cartoon: 1.0 Median filter size at half resolution: 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 an anime style 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 turns into a cartoon. |
SMOOTH | 5 | Median filter size at half resolution. Bigger irons out more texture into flat color. |
SHADES | 4 | Flat brightness bands for the cel shading. 3 is bolder and more graphic; 6 keeps more of the original shading. |
SATURATION | 2.2 | Color boost. 1 keeps the original colors. |
EDGE | 15 | How sharp a brightness change must be to get an outline. Lower draws more lines, higher keeps only the strongest contours. |
LINE | 3 | Outline thickness in pixels (odd numbers). |
INK | (25, 15, 40) | Outline color. |
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
Give input.mp4 (540x960) an anime cartoon look from 1.0 seconds to the end; before 1.0 seconds leave every frame untouched. For each frame from 1.0 s: shrink it to half size (270x480, box filter) and run a 5x5 median filter on it (Pillow's MedianFilter(5)) to flatten texture into smooth areas of color. Color: scale that back up to 540x960 (bicubic), convert to HSV, cut V into 4 flat bands (v becomes (floor(v*4/256)+0.5)*64, so 32, 96, 160 or 224), multiply S by 2.2 (capped at 255), keep H, and convert back to RGB. Outlines: on the half-size smoothed frame's grayscale, take the brightness difference between the pixels on either side horizontally and vertically (central differences), and mark every pixel where the length of that gradient is above 15. Scale the mask up to 540x960, thicken it with a 3x3 max filter, soften it with a 0.6 pixel Gaussian blur and use it to paint dark ink (25, 15, 40) over the color image. Use Python with numpy and Pillow for the frames and ffmpeg to read and write the video (don't use ffmpeg's drawtext if you add any text), keep the size, 30fps, the 6 second length and the audio, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as anime-style.py and run:
python3 anime-style.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Anime style: at one second the shot is redrawn as a cel-shaded cartoon with dark ink outlines and vivid flat color.
Usage: python3 anime-style.py input.mp4 output.mp4
Needs ffmpeg, Pillow and numpy (pip install pillow numpy).
"""
import json
import subprocess
import sys
import numpy as np
from PIL import Image, ImageFilter
START = 1.0 # second the picture turns into a cartoon
SMOOTH = 5 # median filter size (at half resolution) that irons out texture into flat areas of color
SHADES = 4 # flat brightness bands (cel shading); fewer gives a bolder, more graphic look
SATURATION = 2.2 # color boost; 1 keeps the original colors
EDGE = 15 # brightness step (0-255, across 2 half-size pixels) that gets an outline; lower draws more lines
LINE = 3 # outline thickness in pixels (odd)
INK = (25, 15, 40) # outline color
def anime(img):
"""Redraw one frame as a cartoon: flatten it, band its brightness, boost its color and ink its edges."""
half = img.resize((img.width // 2, img.height // 2), Image.BOX) # half size: faster, and smooths grain
flat = half.filter(ImageFilter.MedianFilter(SMOOTH))
h, s, v = [np.asarray(c, np.float32) for c in flat.resize(img.size, Image.BICUBIC).convert("HSV").split()]
v = (np.floor(v / 256 * SHADES) + 0.5) * 256 / SHADES # flat cel-shading bands
s = np.clip(s * SATURATION, 0, 255)
hsv = Image.merge("HSV", [Image.fromarray(c.astype(np.uint8)) for c in (h, s, v)])
color = np.asarray(hsv.convert("RGB"), np.float32)
gray = np.asarray(flat.convert("L"), np.float32)
gx, gy = np.zeros_like(gray), np.zeros_like(gray)
gx[:, 1:-1] = gray[:, 2:] - gray[:, :-2]
gy[1:-1] = gray[2:] - gray[:-2]
edges = Image.fromarray((np.hypot(gx, gy) > EDGE).astype(np.uint8) * 255)
edges = edges.resize(img.size, Image.BILINEAR).filter(ImageFilter.MaxFilter(LINE)).filter(ImageFilter.GaussianBlur(0.6))
ink = (np.asarray(edges, np.float32) / 255)[..., None]
return color * (1 - ink) + np.array(INK, np.float32) * ink
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)
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):
if i / fps >= START:
img = anime(Image.frombytes("RGB", (w, h), raw))
raw = np.clip(img, 0, 255).astype(np.uint8).tobytes()
writer.stdin.write(raw)
i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
sys.exit("ffmpeg failed")





