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 drunk vision to input.mp4 Second the effect starts: 1.0 Seconds it lasts: 3.0
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 drunk vision 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 |
|---|---|---|
START | 1.0 | Second the effect starts. |
LENGTH | 3.0 | Seconds it lasts. |
EASE | 0.5 | Seconds it takes to build up at the start and fade out at the end. |
TILT | 5 | Degrees the picture sways each way. |
SWAY | 1.6 | Seconds for one full sway, left and back. |
DOUBLE | 0.09 | How far apart the two copies drift at most, as a share of the frame width. |
BLUR | 6 | Strongest blur radius, in pixels. |
ZOOM | 1.24 | Scale-up at full strength, so the tilted picture never shows its edges. Raise it if you raise TILT or DOUBLE. |
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 drunk vision effect to input.mp4 from 1.0 to 4.0 seconds; before 1.0 and after 4.0 seconds the video is unchanged. Strength k eases from 0 to 1 over the first 0.5 seconds and back to 0 over the last 0.5 seconds (smoothstep k = u²(3 − 2u), where u = min(t − 1, 4 − t, 0.5) / 0.5). With s = t − 1.0 in each frame: (1) tilt angle = 5° × k × sin(2π s / 1.6); (2) scale the picture up by 1 + 0.24 × k around the center so the tilted frame never shows an edge; (3) make two copies of the frame, each rotated and scaled around the center, one tilted by the full angle and moved left by g pixels, the other tilted by 0.8 × the angle and moved right by g pixels, where g = k × 0.09 × frame width × (0.6 + 0.4 × sin(2π s / 1.1)) / 2, and mix them 50/50 so you see double; (4) Gaussian-blur the mix with radius k × 6 × (0.55 + 0.45 × sin(2π s / 1.3)) pixels. Use Python with Pillow and ffmpeg, keep the size, frame rate and audio, and save it as output.mp4.Run it without Claude
This is the exact script we tested. Save it as drunk-vision.py and run:
python3 drunk-vision.py input.mp4 output.mp4Show the script
#!/usr/bin/env python3
"""Drunk vision: for three seconds the picture sways side to side, splits into two drifting copies and blurs in and out.
Usage: python3 drunk-vision.py input.mp4 output.mp4
Needs ffmpeg and Pillow (pip install pillow).
"""
import json
import math
import subprocess
import sys
from PIL import Image, ImageChops, ImageFilter
START = 1.0 # second the effect starts
LENGTH = 3.0 # seconds it lasts
EASE = 0.5 # seconds it takes to build up at the start and fade out at the end
TILT = 5 # degrees the picture sways each way
SWAY = 1.6 # seconds for one full sway, left and back
DOUBLE = 0.09 # how far apart the two copies drift at most, as a share of the frame width
BLUR = 6 # strongest blur radius, in pixels
ZOOM = 1.24 # scale-up at full strength, so the tilted picture never shows its edges
def strength(t):
"""0 outside the effect, easing up to 1 and back down over EASE seconds at each end."""
u = min(t - START, START + LENGTH - t, EASE) / EASE
u = max(u, 0)
return u * u * (3 - 2 * u)
def tilted(img, angle, zoom, dx):
"""The frame turned by `angle` degrees and scaled by `zoom` around its center, then moved dx pixels across."""
a = math.radians(angle)
c, s = math.cos(a) / zoom, math.sin(a) / zoom
cx, cy = w / 2, h / 2
# each output pixel (x, y) reads from the input at (c*x + s*y + e, -s*x + c*y + f)
e = cx - c * (cx + dx) - s * cy
f = cy + s * (cx + dx) - c * cy
return img.transform((w, h), Image.AFFINE, (c, s, e, -s, c, f), resample=Image.BICUBIC)
def drunk(img, t):
k = strength(t)
angle = k * TILT * math.sin(2 * math.pi * (t - START) / SWAY)
zoom = 1 + (ZOOM - 1) * k
gap = k * DOUBLE * w * (0.6 + 0.4 * math.sin(2 * math.pi * (t - START) / 1.1)) / 2
left = tilted(img, angle, zoom, -gap)
right = tilted(img, angle * 0.8, zoom, gap)
double = ImageChops.blend(left, right, 0.5)
radius = k * BLUR * (0.55 + 0.45 * math.sin(2 * math.pi * (t - START) / 1.3))
return double.filter(ImageFilter.GaussianBlur(radius))
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)
src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
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):
t = i / fps
if START < t < START + LENGTH:
raw = drunk(Image.frombytes("RGB", (w, h), raw), t).tobytes()
writer.stdin.write(raw)
i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
sys.exit("ffmpeg failed")





