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 time freeze to input.mp4 Second the world stops: 1.5 Second time starts again: 4.5
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 time freeze 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 |
|---|---|---|
FREEZE | 1.5 | Second the world stops. |
RESUME | 4.5 | Second time starts again. |
FADE | 0.3 | Seconds the frozen look takes to drain in and to wash back out. |
SATURATION | 0.15 | Color left in the frozen world: 0 is gray, 1 untouched. |
TINT | (0.86, 0.95, 1.12) | Red, green and blue multipliers that cool the frozen world. |
DARKEN | 0.88 | Brightness of the frozen world. |
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 time freeze to input.mp4 (540x960, 30fps, 6 seconds, a camera orbiting a serum bottle on an acrylic block). Use Python with numpy, Pillow, OpenCV and rembg (u2net model), and ffmpeg to read and write the video. Before 1.5 seconds the video is untouched. At 1.5 seconds take that frame as the frozen world: cut the bottle out with rembg, make a mask of every pixel where rembg's mask is above 40, dilate it with a 15x15 square kernel and paint that area out with cv2.inpaint (radius 9, INPAINT_TELEA), so no frozen copy of the bottle is left behind. Give the frozen world a cold look: gray = 0.299 R + 0.587 G + 0.114 B, keep 15% of the color (gray + (rgb - gray) * 0.15), multiply red, green and blue by 0.86, 0.95 and 1.12 and everything by 0.88; ramp this look in linearly from none at 1.5 seconds to full at 1.8 seconds. From 1.5 to 4.5 seconds, cut the bottle out of every live frame with rembg and lay it, in its original colors, over the frozen world using rembg's mask as soft alpha, so only the bottle keeps turning while the backdrop and acrylic block hold still. At 4.5 seconds time resumes: show the live footage again, with the cold look fading out linearly from full at 4.5 seconds to none at 4.8 seconds; after that the video is untouched. Don't add any text (if you do, draw it with Pillow, not ffmpeg's drawtext). Keep the size, frame rate, 6 second length and audio, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as time-freeze.py and run:
python3 time-freeze.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Time freeze: the world stops and drains to a cold gray-blue while the product alone keeps moving in full color.
Usage: python3 time-freeze.py input.mp4 output.mp4
Needs ffmpeg, Pillow, numpy, OpenCV and rembg to cut the product out of every frozen frame
(pip install pillow numpy opencv-python-headless "rembg[cpu]"; rembg downloads its u2net model on first use).
"""
import json
import subprocess
import sys
import cv2
import numpy as np
from PIL import Image
from rembg import new_session
FREEZE = 1.5 # second the world stops
RESUME = 4.5 # second time starts again
FADE = 0.3 # seconds the frozen look takes to drain in and to wash back out
SATURATION = 0.15 # color left in the frozen world (0 gray, 1 untouched)
TINT = (0.86, 0.95, 1.12) # red, green, blue multipliers that cool the frozen world
DARKEN = 0.88 # brightness of the frozen world
def clean_plate(rgb, session):
"""The frame with the product painted out, so a moving product never uncovers a frozen copy of itself."""
mask = np.asarray(session.predict(Image.fromarray(rgb))[0])
mask = cv2.dilate((mask > 40).astype(np.uint8) * 255, np.ones((15, 15), np.uint8))
return cv2.inpaint(rgb, mask, 9, cv2.INPAINT_TELEA).astype(np.float32)
def frozen_look(rgb, p):
"""Drain color from rgb, cool it and darken it, by p from 0 (untouched) to 1 (fully frozen)."""
gray = rgb @ np.array([0.299, 0.587, 0.114], np.float32)
cold = (gray[:, :, None] + (rgb - gray[:, :, None]) * SATURATION) * np.array(TINT, np.float32) * DARKEN
return rgb + (np.clip(cold, 0, 255) - rgb) * p
def composite(rgb, t):
"""Before FREEZE and after RESUME the footage plays; in between, the live product over the frozen frame."""
global plate
if t < FREEZE:
return rgb
img = rgb.astype(np.float32)
if t >= RESUME:
p = max(0.0, 1 - (t - RESUME) / FADE)
return np.round(frozen_look(img, p)).astype(np.uint8)
if plate is None:
plate = clean_plate(rgb, session)
p = min(1.0, (t - FREEZE) / FADE)
subject = np.asarray(session.predict(Image.fromarray(rgb))[0], np.float32)[:, :, None] / 255
world = frozen_look(plate, p)
return np.round(world + (img - world) * subject).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)
def render(src, out):
"""Read src frame by frame, composite each one and save to out, keeping the audio."""
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):
rgb = np.frombuffer(raw, np.uint8).reshape(h, w, 3)
writer.stdin.write(composite(rgb, i / fps).tobytes())
i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
sys.exit("ffmpeg failed")
src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
session = new_session("u2net")
plate = None
render(src, out)





