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 neon sign text to input.mp4 Text: GLOW UP
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 neon sign 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 |
|---|---|---|
TEXT | GLOW UP | The sign's words. |
START | 0.6 | Second the sign first sparks. |
FLICKER | [(0.7, 0.8), (0.87, 1.0), (1.05, 1.12), (3.6, 3.67)] | From and to seconds the tubes drop out. |
Y | 0.14 | Text center, 0-1 down the frame. |
SIZE | 0.16 | Font size as a share of the frame width. |
TUBE | (255, 40, 160) | Lit tube and glow color. |
BOARD | (18, 8, 24, 215) | Backing panel color and opacity. |
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 a neon sign to the top of input.mp4: the words "GLOW UP" drawn as hollow tube outlines (each letter's outline, 10 pixels thick) in a bold rounded font at size 86 pixels (16% of the frame width), centered horizontally 14% of the way down. Each tube is hot pink (255, 40, 160) with a 4-pixel white-hot center line (255, 235, 245) along it and a pink glow around it (the tube blurred by 6 pixels with its opacity boosted 1.6x, and by 22 pixels with its opacity boosted 2.2x, both laid underneath). Behind the letters put a dark panel (18, 8, 24) at 84% opacity (alpha 215) with rounded corners, padded 27 pixels (5% of the frame width) around the letters. Nothing shows before 0.6 seconds. From 0.6 seconds the panel is there and the sign flickers on: lit until 0.7s, off 0.7-0.8s, lit, off 0.87-1.0s, lit, off 1.05-1.12s, then lit for good apart from one more dropout at 3.6-3.67s. When off, the tubes stay visible as dark unlit glass (95, 45, 80) with no glow. Use Python with Pillow to draw it and ffmpeg to put it on the video (don't rely on ffmpeg's drawtext filter), keep the audio, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as neon-sign-text.py and run:
python3 neon-sign-text.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Neon sign text: hot pink tube letters stutter on like a neon sign, then glow steadily.
Usage: python3 neon-sign-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, ImageChops, ImageDraw, ImageFilter, ImageFont
TEXT = "GLOW UP" # the sign's words
START = 0.6 # second the sign first sparks
FLICKER = [(0.7, 0.8), (0.87, 1.0), (1.05, 1.12), (3.6, 3.67)] # (from, to) seconds the tubes drop out
Y = 0.14 # text center, 0-1 down the frame
SIZE = 0.16 # font size as a share of the frame width
TUBE = (255, 40, 160) # lit tube and glow color
CORE = (255, 235, 245) # white-hot center line of each tube
UNLIT = (95, 45, 80) # dark glass tube when switched off
BOARD = (18, 8, 24, 215) # dark backing panel behind the tubes (RGBA)
FONTS = ["/System/Library/Fonts/Supplemental/Arial Rounded 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 tube(width):
"""A mask of each letter's outline, `width` pixels thick, so the letters read as bent glass tubes."""
font = ImageFont.truetype(FONT_FILE, round(w * SIZE))
r = width // 2
outer = Image.new("L", (w, h))
ImageDraw.Draw(outer).text((w / 2, h * Y), TEXT, font=font, anchor="mm", fill=255, stroke_width=r, stroke_fill=255)
inner = Image.new("L", (w, h))
ImageDraw.Draw(inner).text((w / 2, h * Y), TEXT, font=font, anchor="mm", fill=255)
return ImageChops.subtract(outer, inner.filter(ImageFilter.MinFilter(2 * r + 1)))
def layer(color, mask, strength=1.0):
img = Image.new("RGBA", (w, h), color)
img.putalpha(mask.point(lambda v: min(255, round(v * strength))))
return img
def sign():
"""The lit sign (wide glow, tight glow, tube, white core) and the switched-off sign, both on the panel."""
body, core = tube(10), tube(4)
x0, y0, x1, y1 = body.getbbox()
pad = round(w * 0.05)
board = Image.new("RGBA", (w, h))
ImageDraw.Draw(board).rounded_rectangle([x0 - pad, y0 - pad, x1 + pad, y1 + pad], radius=pad, fill=BOARD)
lit, unlit = board.copy(), board.copy()
lit.alpha_composite(layer(TUBE, body.filter(ImageFilter.GaussianBlur(22)), 2.2))
lit.alpha_composite(layer(TUBE, body.filter(ImageFilter.GaussianBlur(6)), 1.6))
lit.alpha_composite(layer(TUBE, body))
lit.alpha_composite(layer(CORE, core))
unlit.alpha_composite(layer(UNLIT, body))
return lit, unlit
def overlay(t):
if t < START:
return blank
return unlit if any(a <= t < b for a, b in FLICKER) else lit
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)
lit, unlit = sign()
blank = Image.new("RGBA", (w, h))
render(src, out)





