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 pencil sketch to input.mp4 Second the picture turns into a pencil drawing: 1.0 Blur radius in pixels for the dodge blend: 12
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 pencil sketch 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 pencil drawing. |
BLUR | 12 | Blur radius in pixels for the dodge blend. Bigger draws bolder, softer strokes; smaller gives thin outlines only. |
DARKEN | 2.6 | Power applied to the sketch. Higher makes the lines and shading darker; 1 leaves them faint. |
PAPER | (250, 250, 247) | Paper color. |
GRAIN | 6 | Paper grain strength (0-255). 0 gives perfectly smooth paper. |
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) into a gray pencil sketch from 1.0 seconds to the end; before 1.0 seconds leave it untouched. Use Python with OpenCV and numpy. For each frame from 1.0 s: convert it to grayscale, invert it, Gaussian-blur the inverted image with sigma 12 pixels, and color-dodge the grayscale over it (cv2.divide(gray, 255 - blurred_inverted, scale=256)). Scale the result to 0-1, raise it to the power 2.6 to darken the strokes, multiply it by a fixed paper grain (1 minus random noise blurred with sigma 0.8, at most 6/255, the same for every frame) and multiply by the paper color (250, 250, 247), so bare paper is (250, 250, 247) and the strokes are neutral gray with no color left. Read and write frames through ffmpeg (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 pencil-sketch.py and run:
python3 pencil-sketch.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Pencil sketch: at one second the colors drop away and the shot is redrawn as gray pencil lines and shading on white paper.
Usage: python3 pencil-sketch.py input.mp4 output.mp4
Needs ffmpeg, numpy and OpenCV for the blur and dodge blend (pip install numpy opencv-python-headless).
"""
import json
import subprocess
import sys
import cv2
import numpy as np
START = 1.0 # second the picture turns into a pencil drawing
BLUR = 12 # blur radius in pixels for the dodge blend; bigger draws bolder, softer strokes
DARKEN = 2.6 # power applied to the sketch; higher makes the lines and shading darker
PAPER = (250, 250, 247) # paper color
GRAIN = 6 # paper grain strength (0-255); 0 gives perfectly smooth paper
def sketch(img):
"""Redraw one frame (h, w, 3, RGB) as pencil: a color-dodge of the grayscale over its own blurred negative."""
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
blurred_negative = cv2.GaussianBlur(255 - gray, (0, 0), BLUR)
lines = cv2.divide(gray, 255 - blurred_negative, scale=256).astype(np.float32) / 255 # 1 = bare paper
lines = np.clip(lines, 0, 1) ** DARKEN
lines = lines * (1 - grain) # graphite skips over the paper's tooth
return (lines[..., None] * paper).astype(np.uint8)
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)
paper = np.array(PAPER, np.float32)
grain = cv2.GaussianBlur(np.random.default_rng(1).random((h, w), np.float32), (0, 0), 0.8) * GRAIN / 255
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)
if i / fps >= START:
img = sketch(img)
writer.stdin.write(img.tobytes())
i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
sys.exit("ffmpeg failed")





