---
title: "How to add a money rain with Claude (tested prompt and script)"
description: "Green dollar bills pour down from the top edge and keep falling past the product to the end, spinning and flipping edge-on as they drop. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/money-rain
---

# How to add a money rain with Claude

Green dollar bills pour down from the top edge and keep falling past the product to the end, spinning and flipping edge-on as they drop.

Made by the script on this page, from our own test clip.

## Get this effect

1. ### Switch to Code in your [Claude Desktop App](https://claude.com/download)

2. ### Install the skill (once)

   ```
   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/skills
   ```

3. ### Ask for the effect

   ```
   Add a money rain to input.mp4
   Second the first notes drop in at the top edge: 0.3
   Banknotes in the shower: 40
   ```

## 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 money rain 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`             | `0.3`                                          | Second the first notes drop in at the top edge.   |
| `COUNT`             | `40`                                           | Banknotes in the shower.                          |
| `SIZE`              | `(0.20, 0.30)`                                 | Note length range, as a share of the frame width. |
| `SPEED`             | `(0.30, 0.46)`                                 | Fall speed range, in frame heights per second.    |
| `SPIN`              | `90`                                           | Fastest spin, in degrees per second.              |
| `SWAY`              | `0.04`                                         | Side-to-side drift as a share of the frame width. |
| `GREEN, PAPER, INK` | `(70, 150, 80), (246, 248, 236), (25, 80, 40)` | Note face, border and dollar sign colors.         |

## Without the skill

Don’t want to install the skill? Paste this prompt into Claude Code and Claude writes the script itself.

```
Add a money rain to input.mp4. Draw a banknote with Pillow: a 300x130 pixel rounded rectangle in off-white (246, 248, 236), a green (70, 150, 80) face inset 9 pixels, a thin dark green (25, 80, 40) line 15 pixels in, a pale green (150, 205, 140) oval 88x80 pixels in the middle with a dark green "$" in bold type, and "100" in off-white in each corner. Rain 40 of these notes down the frame starting at 0.3 seconds: each is scaled to 20% to 30% of the frame width long (bigger notes fall faster, 0.30 to 0.46 frame heights per second, and are drawn in front), placed at random from 5% to 95% across, and queued evenly from 8% to 138% of the frame height above the top edge so they enter one after another. Spin each note at up to 90 degrees per second either way from a random starting angle, squash its height with |cos| over a 1.2 to 2.4 second cycle (never below 12%) so it looks like it flips over, and sway it side to side by 4% of the frame width over 1.8 to 3.2 seconds. A note that falls 15% past the bottom comes back in at the top, so the shower keeps going to the end. Nothing shows before 0.3 seconds and the notes take until about 2 seconds to reach the bottom half. Use Python with numpy and 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 `money-rain.py` and run:

```
python3 money-rain.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Money rain: green banknotes shower down from the top of the frame, spinning and flipping as they fall.

Usage: python3 money-rain.py input.mp4 output.mp4
Needs ffmpeg, numpy and Pillow (pip install numpy pillow).
"""
import json
import math
import subprocess
import sys
from pathlib import Path

import numpy as np
from PIL import Image, ImageDraw, ImageFont

START = 0.3                     # second the first notes drop in at the top edge
COUNT = 40                      # banknotes in the shower
SIZE = (0.20, 0.30)             # note length range, as a share of the frame width
SPEED = (0.30, 0.46)            # fall speed range, in frame heights per second (bigger notes fall faster)
SPIN = 90                       # fastest spin, in degrees per second either way
SWAY = 0.04                     # side-to-side drift as a share of the frame width
GREEN = (70, 150, 80)           # note color
PAPER = (246, 248, 236)         # border and numbers
INK = (25, 80, 40)              # dollar sign and inner line
SEED = 11                       # change for a different shower
FONTS = ["/System/Library/Fonts/Supplemental/Arial 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 banknote(w=300, h=130):
    """A flat note: paper border, green face, a pale oval with a dollar sign and 100 in the corners."""
    img = Image.new("RGBA", (w, h))
    draw = ImageDraw.Draw(img)
    draw.rounded_rectangle([0, 0, w - 1, h - 1], radius=6, fill=PAPER)
    draw.rectangle([9, 9, w - 10, h - 10], fill=GREEN)
    draw.rectangle([15, 15, w - 16, h - 16], outline=INK, width=2)
    draw.ellipse([w / 2 - 44, h / 2 - 40, w / 2 + 44, h / 2 + 40], fill=(150, 205, 140), outline=INK, width=3)
    draw.text((w / 2, h / 2 + 2), "$", font=ImageFont.truetype(FONT_FILE, 64), anchor="mm", fill=INK)
    small = ImageFont.truetype(FONT_FILE, 24)
    for x, y, anchor in [(24, 22, "lt"), (w - 24, 22, "rt"), (24, h - 22, "lb"), (w - 24, h - 22, "rb")]:
        draw.text((x, y), "100", font=small, anchor=anchor, fill=PAPER)
    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"])

src, out = sys.argv[1:3]
w, h, rate, fps, duration = probe(src)
note = banknote()
rng = np.random.default_rng(SEED)
notes = []
for k in range(COUNT):                                   # notes queue up evenly above the frame
    depth = rng.uniform(0, 1)                            # 0 = far (small, slow), 1 = near (big, fast)
    length = (SIZE[0] + depth * (SIZE[1] - SIZE[0])) * w
    notes.append({"sprite": note.resize((round(length), round(length * note.height / note.width)), Image.LANCZOS),
                  "x": rng.uniform(0.05, 0.95) * w, "y": -(0.08 + 1.3 * k / COUNT) * h,
                  "speed": (SPEED[0] + depth * (SPEED[1] - SPEED[0])) * h, "spin": rng.uniform(-SPIN, SPIN),
                  "angle": rng.uniform(0, 360), "flip": rng.uniform(1.2, 2.4), "sway": rng.uniform(1.8, 3.2),
                  "phase": rng.uniform(0, 2 * math.pi), "depth": depth})
notes.sort(key=lambda n: n["depth"])                     # draw far notes first so near ones cover them

def draw_notes(img, t):
    """Paste every note at its place at time t onto the frame."""
    age = t - START
    span = h * 1.3                                       # a note that falls off the bottom comes back in at the top
    for n in notes:
        y = n["y"] + n["speed"] * age
        if y > h * 1.15:
            y = (y + 0.15 * h) % span - 0.15 * h
        x = n["x"] + SWAY * w * math.sin(2 * math.pi * age / n["sway"] + n["phase"])
        turn = abs(math.cos(2 * math.pi * age / n["flip"] + n["phase"]))   # flipping over: squashed when edge-on
        sprite = n["sprite"].resize((n["sprite"].width, max(2, round(n["sprite"].height * max(turn, 0.12)))),
                                    Image.LANCZOS)
        sprite = sprite.rotate(n["angle"] + n["spin"] * age, expand=True, resample=Image.BICUBIC)
        img.paste(sprite, (round(x - sprite.width / 2), round(y - sprite.height / 2)), sprite)

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 t >= START:
        img = Image.frombytes("RGB", (w, h), raw)
        draw_notes(img, t)
        raw = img.tobytes()
    writer.stdin.write(raw)
    i += 1
writer.stdin.close()
if reader.wait() or writer.wait():
    sys.exit("ffmpeg failed")
```

## More overlays and light

- [Anamorphic streak **Anamorphic streak**](https://www.recharm.com/effects/anamorphic-streak)
- [Aurora **Aurora**](https://www.recharm.com/effects/aurora)
- [Blood splatter **Blood splatter**](https://www.recharm.com/effects/blood-splatter)
- [Bokeh lights **Bokeh lights**](https://www.recharm.com/effects/bokeh-lights)
- [Camera flash **Camera flash**](https://www.recharm.com/effects/camera-flash)

## Find 3x _winning ads_

Recharm cuts your ad footage into tagged, searchable clips: hooks, testimonials, product shots. Find the shots that win, add the effect with Claude, and ship 3x more ad edits.

[Start 14-day free trial](https://www.recharm.com/get-started)
