---
title: "How to add bokeh lights with Claude (tested prompt and script)"
description: "See-through circles of gold and pink light, soft-edged like out-of-focus fairy lights, fade in over the bottle and float slowly upward. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/bokeh-lights
---

# How to add bokeh lights with Claude

See-through circles of gold and pink light, soft-edged like out-of-focus fairy lights, fade in over the bottle and float slowly upward.

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 bokeh lights to input.mp4
   Second the lights start to fade in, and how many seconds the fade takes: 0.5, 0.6
   Number of circles: 24
   ```

## 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 bokeh lights 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, FADE` | `0.5, 0.6`                                         | Second the lights start to fade in, and how many seconds the fade takes. |
| `COUNT`       | `24`                                               | Number of circles.                                                       |
| `RADIUS`      | `(20, 72)`                                         | Smallest and largest circle radius, in pixels.                           |
| `RISE`        | `(25, 70)`                                         | Slowest and fastest upward drift, in pixels per second.                  |
| `OPACITY`     | `(0.3, 0.65)`                                      | How solid the faintest and strongest circles are (0-1).                  |
| `COLORS`      | `(255, 185, 60), (255, 110, 170), (255, 215, 120)` | The colors the circles cycle through.                                    |
| `SEED`        | `7`                                                | Change for a different arrangement of circles.                           |

## Without the skill

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

```
Add bokeh lights to input.mp4: 24 soft, see-through circles of light with radii between 20 and 72 pixels, cycling through three colors: gold (255, 185, 60), pink (255, 110, 170) and pale gold (255, 215, 120). Give each circle an opacity between 0.3 and 0.65, even across its middle, rising to 1.0x that opacity at the rim from 0.7x at the center (like a lens), fading out over the outer 20% of the radius, with a faint glow (0.25x the opacity) just outside the edge. Scatter them over the whole frame and blend them over the video normally (not added or screened). Each drifts upward at its own speed between 25 and 70 pixels per second, wrapping round from the top to the bottom, sways 20 pixels side to side over 3 to 6 seconds, and twinkles between 60% and 100% of its opacity every 1.7 seconds. Leave the frames before 0.5 seconds untouched, then fade the lights in from 0.5 to 1.1 seconds and keep them to the end. Use Python with numpy to draw and blend the circles and ffmpeg to read and write the video, keep the audio, and save it as output.mp4.
```

## Run it without Claude

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

```
python3 bokeh-lights.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Bokeh lights: soft out-of-focus circles of warm gold and pink light fade in and drift slowly up the frame.

Usage: python3 bokeh-lights.py input.mp4 output.mp4
Needs ffmpeg and numpy (pip install numpy).
"""
import json
import subprocess
import sys

import numpy as np

START = 0.5          # second the lights start to fade in
FADE = 0.6           # seconds the fade-in takes
COUNT = 24           # number of circles
RADIUS = (20, 72)    # smallest and largest circle radius, in pixels
RISE = (25, 70)      # slowest and fastest upward drift, in pixels per second
OPACITY = (0.3, 0.65)  # how solid the faintest and strongest circles are (0-1)
COLORS = [(255, 185, 60), (255, 110, 170), (255, 215, 120)]  # warm gold, pink, pale gold
SEED = 7             # change for a different arrangement

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 disc(r, opacity):
    """How solid one bokeh circle is at each pixel (0-1): even inside, a stronger rim, a soft edge and a faint
    glow around it. The sprite reaches 1.5 radii out from the center, to leave room for the glow."""
    g = round(1.5 * r)
    y, x = np.mgrid[-g:g + 1, -g:g + 1].astype(np.float32)
    d = np.hypot(x, y) / r
    edge = np.clip((1 - d) / 0.2, 0, 1)         # fades out over the outer 20% of the radius
    body = 0.7 + 0.3 * np.minimum(d, 1) ** 4    # rim a little stronger than the middle, like a lens
    glow = 0.25 * np.exp(-((d - 0.9) / 0.3) ** 2)
    return (np.maximum(edge * body, glow) * opacity)[..., None]

def lights(t):
    """The light layer at time t: its color and how solid it is at each pixel, or None before START."""
    color = np.zeros((h, w, 3), np.float32)
    alpha = np.zeros((h, w, 1), np.float32)
    fade = np.clip((t - START) / FADE, 0, 1)
    if fade == 0:
        return None
    for c in circles:
        r = c["sprite"].shape[0] // 2
        cx = round(c["x"] + 20 * np.sin(2 * np.pi * t / c["sway"] + c["phase"]))
        cy = round((c["y"] - c["rise"] * t) % (h + 2 * r) - r)  # wraps from the top back to the bottom
        twinkle = 0.8 + 0.2 * np.sin(2 * np.pi * t / 1.7 + c["phase"])
        x0, y0, x1, y1 = max(cx - r, 0), max(cy - r, 0), min(cx + r + 1, w), min(cy + r + 1, h)
        if x0 < x1 and y0 < y1:
            a = c["sprite"][y0 - (cy - r):y1 - (cy - r), x0 - (cx - r):x1 - (cx - r)] * twinkle
            color[y0:y1, x0:x1] = color[y0:y1, x0:x1] * (1 - a) + c["color"] * a  # premultiplied "over"
            alpha[y0:y1, x0:x1] = alpha[y0:y1, x0:x1] * (1 - a) + a
    return color * fade, alpha * fade

src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
rng = np.random.default_rng(SEED)
circles = []
for i in range(COUNT):
    r = int(rng.uniform(*RADIUS))
    circles.append({"x": rng.uniform(0, w), "y": rng.uniform(0, h + 2 * r), "rise": rng.uniform(*RISE),
                    "sway": rng.uniform(3, 6), "phase": rng.uniform(0, 2 * np.pi),
                    "color": np.array(COLORS[i % len(COLORS)], np.float32), "sprite": disc(r, rng.uniform(*OPACITY))})

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):
    img = np.frombuffer(raw, np.uint8).reshape(h, w, 3)
    layer = lights(i / fps)
    if layer is not None:
        color, alpha = layer
        img = (img * (1 - alpha) + color).astype(np.uint8)
    writer.stdin.write(img.tobytes())
    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)
- [Camera flash **Camera flash**](https://www.recharm.com/effects/camera-flash)
- [Confetti **Confetti**](https://www.recharm.com/effects/confetti)

## 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)
