---
title: "How to add falling leaves with Claude (tested prompt and script)"
description: "Orange, red and gold maple leaves drop in from the top edge and tumble past the product, rocking from side to side and flipping edge-on as they fall. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/falling-leaves
---

# How to add falling leaves with Claude

Orange, red and gold maple leaves drop in from the top edge and tumble past the product, rocking from side to side and flipping edge-on as they fall.

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 falling leaves to input.mp4
   Second the first leaves appear at the top edge: 0.3
   Number of leaves: 30
   ```

## 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 falling leaves 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 leaves appear at the top edge.           |
| `COUNT`  | `30`                                              | Number of leaves.                                         |
| `SIZE`   | `(44, 76)`                                        | Smallest and largest leaf, in pixels across.              |
| `SPEED`  | `(0.16, 0.26)`                                    | Fall speed range, in frame heights per second.            |
| `SWAY`   | `40`                                              | Side-to-side swing, in pixels.                            |
| `SPIN`   | `70`                                              | How far a leaf rocks either way as it swings, in degrees. |
| `COLORS` | `[(232, 110, 24), (196, 38, 28), (238, 176, 32)]` | Leaf colors: orange, red and gold.                        |
| `SEED`   | `5`                                               | Change for a different fall of leaves.                    |

## Without the skill

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

```
Add falling autumn leaves to input.mp4 (540x960). Draw a maple leaf with Pillow: a polygon whose right half runs, in units of half the leaf's width with the tip at the top, through (0, -1), (0.14, -0.72), (0.32, -0.82), (0.26, -0.44), (0.64, -0.64), (0.58, -0.38), (0.94, -0.30), (0.72, -0.10), (0.84, 0.08), (0.44, 0.10), (0.52, 0.38), (0.14, 0.24), (0.05, 0.50), mirrored for the left half, with a stem and five veins from a point just below the middle drawn in the fill color at 60% brightness. Make 30 leaves, cycling through orange (232, 110, 24), red (196, 38, 28) and gold (238, 176, 32), each 44 to 76 pixels across (random), placed at a random 4% to 96% across and 5% to 80% of the frame height above the top edge. From 0.3 seconds each leaf falls at a steady random 0.16 to 0.26 frame heights per second, swings 40 pixels side to side once every 2.2 to 3.6 seconds while rocking up to 70 degrees with the swing, and tumbles by squashing its width with the absolute cosine of a 1.5 to 3 second cycle (never below 20%); half the leaves hang upside down. A leaf that falls off the bottom comes back in above the top, so leaves keep falling to the end. Leave the frames before 0.3 seconds untouched. Use Python with Pillow and numpy, compositing onto the video frames with ffmpeg (don't use ffmpeg's drawtext filter, draw any text with Pillow), keep the audio, and save it as output.mp4.
```

## Run it without Claude

This is the exact script we tested. Save it as `falling-leaves.py` and run:

```
python3 falling-leaves.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Falling leaves: orange, red and gold maple leaves tumble down the frame, spinning and swaying as they fall.

Usage: python3 falling-leaves.py input.mp4 output.mp4
Needs ffmpeg, Pillow and numpy (pip install pillow numpy).
"""
import json
import math
import subprocess
import sys

import numpy as np
from PIL import Image, ImageDraw

START = 0.3                                              # second the first leaves appear at the top edge
COUNT = 30                                               # number of leaves
SIZE = (44, 76)                                          # smallest and largest leaf, in pixels across
SPEED = (0.16, 0.26)                                     # fall speed range, in frame heights per second
SWAY = 40                                                # side-to-side swing, in pixels
SPIN = 70                                                # how far a leaf rocks either way as it swings, in degrees
COLORS = [(232, 110, 24), (196, 38, 28), (238, 176, 32)] # leaf colors: orange, red and gold
SEED = 5                                                 # change for a different fall of leaves

# one half of a maple leaf, tip at the top and stem at the bottom, in units of half the leaf's width
HALF_LEAF = [(0, -1.0), (0.14, -0.72), (0.32, -0.82), (0.26, -0.44), (0.64, -0.64), (0.58, -0.38),
             (0.94, -0.30), (0.72, -0.10), (0.84, 0.08), (0.44, 0.10), (0.52, 0.38), (0.14, 0.24), (0.05, 0.50)]

def leaf(color, size=160):
    """A flat maple leaf with a darker stem and veins, drawn large so it stays smooth when scaled down."""
    outline = HALF_LEAF + [(-x, y) for x, y in reversed(HALF_LEAF)]
    c = size / 2
    img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
    draw = ImageDraw.Draw(img)
    draw.polygon([(c + x * c * 0.95, c + y * c * 0.95) for x, y in outline], fill=color + (255,))
    vein = tuple(round(v * 0.6) for v in color) + (255,)
    base = (c, c + 0.42 * c)
    for x, y in [(0, -0.9), (0.6, -0.55), (-0.6, -0.55), (0.75, 0.0), (-0.75, 0.0)]:
        draw.line([base, (c + x * c * 0.95, c + y * c * 0.95)], fill=vein, width=max(2, size // 60))
    draw.line([base, (c, size - 1)], fill=vein, width=max(3, size // 40))
    return img.crop(img.getbbox())

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)
rng = np.random.default_rng(SEED)
sprites = [leaf(c) for c in COLORS]
leaves = [{"sprite": sprites[k % len(sprites)], "size": rng.uniform(*SIZE), "x": rng.uniform(0.04, 0.96) * w,
           "y": -rng.uniform(0.05, 0.8) * h, "speed": rng.uniform(*SPEED) * h, "swing": rng.uniform(2.2, 3.6),
           "flip": rng.uniform(1.5, 3.0), "phase": rng.uniform(0, 2 * math.pi)}
          for k in range(COUNT)]

def layer(t):
    """Every leaf at time t on a transparent frame."""
    canvas = Image.new("RGBA", (w, h), (0, 0, 0, 0))
    age = t - START
    span = h * 1.15                                      # a leaf that falls off the bottom comes back in at the top
    for p in leaves:
        y = p["y"] + p["speed"] * age
        if y > h * 1.07:
            y = (y + 0.08 * h) % span - 0.08 * h
        swing = math.sin(2 * math.pi * age / p["swing"] + p["phase"])
        x = p["x"] + SWAY * swing
        turn = abs(math.cos(2 * math.pi * age / p["flip"] + p["phase"]))   # tumbling: seen edge-on now and then
        s = p["size"] / p["sprite"].width
        sprite = p["sprite"].resize((max(2, round(p["sprite"].width * s * max(turn, 0.2))),
                                     max(2, round(p["sprite"].height * s))), Image.LANCZOS)
        sprite = sprite.rotate(SPIN * swing + 180 * (p["phase"] > math.pi), expand=True, resample=Image.BICUBIC)
        canvas.paste(sprite, (round(x - sprite.width / 2), round(y - sprite.height / 2)), sprite)
    return canvas

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).convert("RGBA")
        img.alpha_composite(layer(t))
        raw = img.convert("RGB").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)
