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 8-bit pixel text to input.mp4 Lines: ("LEVEL UP", (255, 214, 0), 7, 0.08, 0.5), ("YOUR GLOW", (255, 255, 255), 6, 0.155, 1.4)
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 8-bit pixel text 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 |
|---|---|---|
LINES | ("LEVEL UP", (255, 214, 0), 7, 0.08, 0.5), ("YOUR GLOW", (255, 255, 255), 6, 0.155, 1.4) | Each line's text, color, block size in pixels, center (0 = top, 1 = bottom) and start second. |
STEP | 0.1 | Seconds between letters. |
FLICKER | 3 | Frames each new letter blinks on, off, on as it lands. |
OUTLINE | (40, 12, 70) | Color of the outline and drop shadow. |
FONT_SIZE | 10 | Glyph height in font pixels before scaling up; smaller looks blockier. |
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 8-bit pixel text to input.mp4. Two lines, each drawn with Pillow at a 10-pixel font size (Arial Black) with antialiasing off, then scaled up with nearest-neighbor so every font pixel becomes a solid square block: "LEVEL UP" in yellow (255, 214, 0) with 7-pixel blocks, centered horizontally with its middle 8% of the way down, and "YOUR GLOW" in white (255, 255, 255) with 6-pixel blocks, centered with its middle 15.5% down. Give the letters a dark purple (40, 12, 70) outline one block thick plus the same color offset one block down and right as a hard shadow. The letters land one at a time, left to right, every 0.1 seconds: "LEVEL UP" starting at 0.5 seconds and "YOUR GLOW" at 1.4 seconds. Each new letter blinks for its first 3 frames: shown, hidden, shown. Nothing is added before 0.5 seconds, the letters stay to the end, and the video behind them is untouched. Draw the text with Python and Pillow (don't rely on ffmpeg's drawtext filter), composite it with ffmpeg, keep the size, 30fps and audio, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as pixel-text.py and run:
python3 pixel-text.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""8-bit pixel text: blocky arcade letters land one at a time near the top, each flickering as it arrives.
Usage: python3 pixel-text.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, ImageFilter, ImageFont
LINES = [("LEVEL UP", (255, 214, 0), 7, 0.08, 0.5), # text, color, block size in px, center (0 = top), start second
("YOUR GLOW", (255, 255, 255), 6, 0.155, 1.4)]
STEP = 0.1 # seconds between letters
FLICKER = 3 # frames each new letter blinks on, off, on as it lands
OUTLINE = (40, 12, 70) # one-block outline and drop shadow behind the letters
FONT_SIZE = 10 # glyph height in font pixels; each is scaled up to a solid square block
FONTS = ["/System/Library/Fonts/Supplemental/Arial Black.ttf", # macOS
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", # Linux
"C:/Windows/Fonts/ariblk.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 blocks(text, shown, color, pixel):
"""The first `shown` letters of text drawn at FONT_SIZE with no smoothing, outlined, then scaled up
so every font pixel becomes a solid square block."""
font = ImageFont.truetype(FONT_FILE, FONT_SIZE)
mask = Image.new("L", (math.ceil(font.getlength(text)) + 4, FONT_SIZE + 6))
draw = ImageDraw.Draw(mask)
draw.fontmode = "1"
draw.text((2, 1), text[:shown], font=font, fill=255)
edge = mask.filter(ImageFilter.MaxFilter(3))
img = Image.new("RGBA", mask.size)
img.paste(OUTLINE, (0, 0), edge)
img.paste(OUTLINE, (1, 1), edge)
img.paste(color, (0, 0), mask)
return img.resize((mask.width * pixel, mask.height * pixel), Image.NEAREST)
def overlay(t):
img = Image.new("RGBA", (w, h))
for text, color, pixel, y, start in LINES:
if t < start:
continue
frames, per = round((t - start) * fps), round(STEP * fps)
n = min(frames // per + 1, len(text)) # letters landed so far
age = frames - (n - 1) * per # frames since the newest one landed
shown = n - 1 if age < FLICKER and age % 2 == 1 else n
if (text, shown) not in cache:
cache[text, shown] = blocks(text, shown, color, pixel)
b = cache[text, shown]
img.alpha_composite(b, (round((w - b.width) / 2), round(h * y - b.height / 2)))
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)
cache = {}
render(src, out)





