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 rolling credits to input.mp4 Credits: [("Directed by", "Maya Chen"), ...]
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 rolling credits 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 |
|---|---|---|
CREDITS | [("Directed by", "Maya Chen"), ...] | The (role, name) pairs, top to bottom. |
FADE_START | 1.0 | Second the clip starts fading to black. |
FADE | 0.5 | Seconds the fade takes. |
ROLL_START | 1.5 | Second the first line enters at the bottom. |
SPEED | 200 | Pixels the credits move up each second. |
ROLE_SIZE, NAME_SIZE | 0.042, 0.068 | Text heights as a share of the frame width. |
ROLE_COLOR | (160, 160, 160) | Color of the small role line. |
NAME_COLOR | (255, 255, 255) | Color of the name line. |
GAP | 1.6 | Space between entries, in name heights. |
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 rolling end credits to input.mp4 (540x960). Play the clip untouched until 1.0 seconds, then fade it to solid black between 1.0 and 1.5 seconds and keep it black to the end. From 1.5 seconds, scroll five centered credits up from the bottom edge at a steady 200 pixels per second: "Directed by" / "Maya Chen", "Starring" / "The Glow Serum", "Cinematography" / "Leo Park", "Music" / "The Late Hours", "Edited with" / "Claude". Each role is in capitals, 23 pixels tall, gray (160, 160, 160), with its name 34 pixels below it in white (255, 255, 255) Arial Bold 37 pixels tall; entries start 131 pixels apart. The top of the first role line is at the bottom edge (y = 960) at 1.5 seconds and 200 pixels higher each second after, so at 6 seconds all five credits are on screen. Draw the credits once on a tall transparent image and move it each frame. Use Python with Pillow to draw the text (don't rely on ffmpeg's drawtext filter) and ffmpeg to put it on the video, keep the audio and the 6 second length at 30fps, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as rolling-credits.py and run:
python3 rolling-credits.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Rolling credits: the clip fades to black and white names scroll steadily up the screen, like the end of a film.
Usage: python3 rolling-credits.py input.mp4 output.mp4
Needs ffmpeg and Pillow (pip install pillow).
"""
import json
import math
import subprocess
import sys
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
CREDITS = [("Directed by", "Maya Chen"), # (role, name) pairs, top to bottom
("Starring", "The Glow Serum"),
("Cinematography", "Leo Park"),
("Music", "The Late Hours"),
("Edited with", "Claude")]
FADE_START = 1.0 # second the clip starts fading to black
FADE = 0.5 # seconds the fade takes
ROLL_START = 1.5 # second the first line enters at the bottom
SPEED = 200 # pixels the credits move up each second
ROLE_SIZE, NAME_SIZE = 0.042, 0.068 # text heights as a share of the frame width
ROLE_COLOR = (160, 160, 160) # small gray role line
NAME_COLOR = (255, 255, 255) # big white name line
GAP = 1.6 # space between entries, in name heights
FONTS = ["/System/Library/Fonts/Supplemental/Arial Bold.ttf", # macOS
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", # Linux
"C:/Windows/Fonts/arialbd.ttf"] # Windows
FONT_FILE = next((f for f in FONTS if Path(f).exists()), None) or sys.exit("No bold font found: add one to FONTS")
def credits_strip():
"""Every credit drawn once on a tall transparent strip as wide as the frame, centered."""
role_font = ImageFont.truetype(FONT_FILE, round(w * ROLE_SIZE))
name_font = ImageFont.truetype(FONT_FILE, round(w * NAME_SIZE))
entry = role_font.size * 1.5 + name_font.size * (1 + GAP)
strip = Image.new("RGBA", (w, math.ceil(entry * len(CREDITS))))
draw = ImageDraw.Draw(strip)
for i, (role, name) in enumerate(CREDITS):
y = i * entry
draw.text((w / 2, y), role.upper(), font=role_font, anchor="mt", fill=ROLE_COLOR)
draw.text((w / 2, y + role_font.size * 1.5), name, font=name_font, anchor="mt", fill=NAME_COLOR)
return strip
def overlay(t):
"""Black fading in over the clip, with the strip's top edge SPEED pixels higher every second after ROLL_START."""
fade = min(max((t - FADE_START) / FADE, 0), 1)
img = Image.new("RGBA", (w, h), (0, 0, 0, round(255 * fade)))
if t >= ROLL_START:
img.alpha_composite(strip, (0, round(h - (t - ROLL_START) * SPEED))) # Pillow clips what falls off the frame
return img
def probe(path):
info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
"stream=width,height,r_frame_rate:format=duration", "-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), float(info["format"]["duration"])
def render(src, out):
"""Draw overlay(t) on every frame of src and save to out, keeping the audio."""
ff = subprocess.Popen(["ffmpeg", "-y", "-v", "error", "-i", src,
"-f", "rawvideo", "-pix_fmt", "rgba", "-s", f"{w}x{h}", "-r", rate, "-i", "-",
"-filter_complex", "[0:v][1:v]overlay=shortest=1,format=yuv420p[v]",
"-map", "[v]", "-map", "0:a?", "-c:v", "libx264", "-crf", "18", "-c:a", "copy", out],
stdin=subprocess.PIPE)
for i in range(math.ceil(duration * fps)):
ff.stdin.write(overlay(i / fps).tobytes())
ff.stdin.close()
if ff.wait():
sys.exit("ffmpeg failed")
src, out = sys.argv[1:3]
w, h, rate, fps, duration = probe(src)
strip = credits_strip()
render(src, out)





