---
title: "How to add a lens flare with Claude (tested prompt and script)"
description: "A warm sun blooms in the top-right corner with ten sharp rays and a faint rainbow ring, and a line of soft glowing circles and a hollow ring runs from it diagonally across the bottle to the bottom-left corner. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/lens-flare
---

# How to add a lens flare with Claude

A warm sun blooms in the top-right corner with ten sharp rays and a faint rainbow ring, and a line of soft glowing circles and a hollow ring runs from it diagonally across the bottle to the bottom-left corner.

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 lens flare to input.mp4
   Ghosts: 4 reflections
   ```

## 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 lens flare 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                                                                                             |
| ----------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `SUN`                   | `(0.80, 0.14)`                    | Where the light source sits, 0-1 across and down the frame.                                              |
| `START, FADE_IN`        | `0.8, 0.6`                        | Second the flare starts to bloom, and how many seconds it takes.                                         |
| `SUN_COLOR, GLOW_COLOR` | `(255, 244, 214), (255, 140, 40)` | Colors of the hot center and rays, and of the glow around them.                                          |
| `CORE`                  | `0.07`                            | Radius of the hot center, as a share of the frame width.                                                 |
| `RAYS`                  | `10`                              | Number of light rays around the sun.                                                                     |
| `HALO`                  | `0.32`                            | Radius of the rainbow ring around the sun, as a share of the frame width.                                |
| `GHOSTS`                | `4 reflections`                   | Each reflection's place along the line through the frame center, radius, color and shape (disc or ring). |

## Without the skill

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

```
Add a lens flare to input.mp4 with Python (numpy) and ffmpeg. The light source is a point 80% across and 14% down the frame; W is the frame width and r the distance in pixels from the source. Build one light layer (RGB, 0-1) from: a warm white (255, 244, 214) hot center exp(-(r/(0.07*W))^2) plus 10 rays of the same color, 0.7 * (0.5 + 0.5*cos(10*angle))^16 * exp(-r/(0.35*W)), with center plus rays capped at 1; an orange (255, 140, 40) glow 0.8 * exp(-r/(0.25*W)); and a faint rainbow ring of radius 0.32*W, strength 0.35 * exp(-q^2) with q = (r - 0.32*W)/(0.03*W), colored 0.4 + 0.6 * (clip(q, 0, 1), 1 - |q|, clip(-q, 0, 1)) so it runs red outside to blue inside. Add four lens reflections at 0.45 strength, on the line from the source through the frame center, at 0.5, 1.3, 1.7 and 2.2 times the distance from the source to the center: an amber (255, 190, 90) disc of radius 0.03*W, a teal (90, 230, 210) disc of radius 0.07*W, a violet (170, 120, 255) hollow ring of radius 0.11*W whose rim is 12% of its radius thick, and a green (140, 255, 140) disc of radius 0.04*W, all with 3-pixel soft edges. Clip the layer to 1. Leave every frame before 0.8 seconds untouched; from 0.8 to 1.4 seconds the flare's strength rises from 0 to 1 with a smoothstep, then it stays to the end with a slight flicker (multiply by 1 - 0.04*sin(2*pi*4*t)). Combine strength * layer with each frame by a screen blend (1 - (1 - frame) * (1 - light), values 0-1). There's no text to draw (if you add any, draw it with Pillow, not ffmpeg's drawtext). Keep the size, 30fps and the audio, and save it as output.mp4.
```

## Run it without Claude

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

```
python3 lens-flare.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Lens flare: a warm sun blooms in the top-right corner with rays, a halo ring and a chain of colored reflections.

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

import numpy as np

SUN = (0.80, 0.14)            # where the light source sits (0-1 across and down the frame)
START, FADE_IN = 0.8, 0.6     # second the flare starts to bloom, and how many seconds it takes
SUN_COLOR = (255, 244, 214)   # the hot center and the rays: warm white
GLOW_COLOR = (255, 140, 40)   # the glow around the sun: orange
CORE = 0.07                   # radius of the hot center, as a share of the frame width
RAYS = 10                     # number of light rays around the sun
HALO = 0.32                   # radius of the faint rainbow ring around the sun, as a share of the frame width
# reflections on the line from the sun through the frame center:
# (distance along it, 1 = the frame center; radius as a share of the width; color; "disc" or "ring")
GHOSTS = [(0.5, 0.03, (255, 190, 90), "disc"), (1.3, 0.07, (90, 230, 210), "disc"),
          (1.7, 0.11, (170, 120, 255), "ring"), (2.2, 0.04, (140, 255, 140), "disc")]

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 flare():
    """The whole flare as an RGB light layer (0-1) at full strength."""
    y, x = np.mgrid[0:h, 0:w].astype(np.float32)
    sx, sy = SUN[0] * w, SUN[1] * h
    dx, dy = x - sx, y - sy
    r = np.hypot(dx, dy)
    core = np.exp(-(r / (CORE * w)) ** 2)
    rays = 0.7 * (0.5 + 0.5 * np.cos(RAYS * np.arctan2(dy, dx))) ** 16 * np.exp(-r / (0.35 * w))
    glow = 0.8 * np.exp(-r / (0.25 * w))
    layer = np.minimum(core + rays, 1)[..., None] * rgb(SUN_COLOR) + glow[..., None] * rgb(GLOW_COLOR)
    ring_pos = (r - HALO * w) / (0.03 * w)       # -1..1 across the halo ring, red outside to blue inside
    hue = np.stack([np.clip(ring_pos, 0, 1), 1 - np.abs(ring_pos), np.clip(-ring_pos, 0, 1)], axis=-1)
    layer += 0.35 * np.exp(-ring_pos ** 2)[..., None] * (0.4 + 0.6 * hue)
    for k, radius, color, shape in GHOSTS:
        gx, gy = sx + k * (w / 2 - sx), sy + k * (h / 2 - sy)
        edge = radius * w - np.hypot(x - gx, y - gy)  # pixels inside the reflection's rim
        disc = np.clip(edge / 3, 0, 1)
        if shape == "ring":
            disc *= np.clip((0.12 * radius * w - edge) / 3, 0, 1)
        layer += 0.45 * disc[..., None] * rgb(color)
    return np.minimum(layer, 1)

def rgb(color):
    return np.array(color, np.float32) / 255

src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
light = flare()
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", out],
                          stdin=subprocess.PIPE)
size, i = w * h * 3, 0
while raw := reader.stdout.read(size):
    t = i / fps
    p = np.clip((t - START) / FADE_IN, 0, 1)
    strength = p * p * (3 - 2 * p) * (1 - 0.04 * np.sin(2 * np.pi * 4 * t))  # blooms in, then flickers slightly
    if strength > 0:
        frame = np.frombuffer(raw, np.uint8).reshape(h, w, 3) / 255.0
        raw = ((1 - (1 - frame) * (1 - strength * light)) * 255).round().astype(np.uint8).tobytes()  # screen blend
    writer.stdin.write(raw)
    i += 1
writer.stdin.close()
if writer.wait() or reader.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)
