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 video inside text to input.mp4 Lines: ["PURE", "GLOW"]
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 video inside 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 | ["PURE", "GLOW"] | The words the video shows through, one per line. |
WIDTH | 0.90 | Widest line as a share of the frame width. |
STRETCH | 1.6 | How many times taller than normal the letters are drawn. |
CENTERS | [0.36, 0.64] | Where each line's middle sits, 0-1 down the frame. |
CARD | (10, 10, 14) | Color everywhere outside the letters. |
START | 1.0 | Second the card starts to fade in. |
FADE | 0.5 | Seconds the fade takes. |
SMOOTH | 4 | How much larger the card is drawn before shrinking, for smooth letter edges. |
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
Make the video in input.mp4 play inside text. Use Python with Pillow (not ffmpeg's drawtext) to draw one overlay image the size of the video: a solid (10, 10, 14) near-black card with the words "PURE" and "GLOW" cut out of it as fully transparent holes, one word per line, in Arial Black (or another heavy bold font). Size the font so the wider word is 90% of the frame width, then stretch each word 1.6 times taller, and center the words horizontally with their middles at 36% and 64% down the frame. Draw it at 4x size and shrink it for smooth edges. With ffmpeg, put the card over every frame, fading the card in from fully transparent starting at 1.0 seconds over 0.5 seconds, so the plain video shows for the first second and only the letters show video from 1.5 seconds to the end. Keep the audio, the original size and length, 30fps H.264 yuv420p, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as video-inside-text.py and run:
python3 video-inside-text.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Video inside text: a black card fades in and the footage keeps playing only inside two lines of huge letters.
Usage: python3 video-inside-text.py input.mp4 output.mp4
Needs ffmpeg and Pillow (pip install pillow).
"""
import io
import subprocess
import sys
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
LINES = ["PURE", "GLOW"] # the words the video shows through, one per line
WIDTH = 0.90 # widest line as a share of the frame width
STRETCH = 1.6 # letters drawn this many times taller than normal
CENTERS = [0.36, 0.64] # where each line's middle sits (0-1 down the frame)
CARD = (10, 10, 14) # color everywhere outside the letters
START = 1.0 # second the card starts to fade in
FADE = 0.5 # seconds the fade takes
SMOOTH = 4 # draw this many times larger, then shrink, for smooth letter edges
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 card(w, h):
"""The card with see-through letters cut out of it."""
W, H = w * SMOOTH, h * SMOOTH
probe_font = ImageFont.truetype(FONT_FILE, 100)
widest = max(probe_font.getlength(line) for line in LINES)
font = ImageFont.truetype(FONT_FILE, round(100 * WIDTH * W / widest))
letters = Image.new("L", (W, H))
for line, y in zip(LINES, CENTERS):
word = Image.new("L", (W, H))
ImageDraw.Draw(word).text((W / 2, H / 2), line, font=font, anchor="mm", fill=255)
word = word.crop(word.getbbox())
word = word.resize((word.width, round(word.height * STRETCH)), Image.LANCZOS)
letters.paste(word, (round((W - word.width) / 2), round(H * y - word.height / 2)))
big = Image.new("RGBA", (W, H), CARD + (255,))
big.putalpha(letters.point(lambda v: 255 - v))
return big.resize((w, h), Image.LANCZOS)
src, out = sys.argv[1:3]
w, h = map(int, subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
"stream=width,height", "-of", "csv=p=0", src], text=True).split(","))
png = io.BytesIO()
card(w, h).save(png, "PNG")
subprocess.run(["ffmpeg", "-y", "-v", "error", "-i", src, "-loop", "1", "-f", "png_pipe", "-i", "-",
"-filter_complex", f"[1:v]format=rgba,fade=in:st={START}:d={FADE}:alpha=1[card];"
"[0:v][card]overlay=shortest=1,fps=30,format=yuv420p[v]",
"-map", "[v]", "-map", "0:a?", "-c:v", "libx264", "-crf", "18", "-c:a", "copy", out],
input=png.getvalue(), check=True)





