---
title: "How to add a prism light with Claude (tested prompt and script)"
description: "Rose, green and violet ghost copies of the shot fan out to the upper right, edges split into red and blue fringes, and a soft rainbow band sweeps diagonally across the frame. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/prism-light
---

# How to add a prism light with Claude

Rose, green and violet ghost copies of the shot fan out to the upper right, edges split into red and blue fringes, and a soft rainbow band sweeps diagonally across the frame.

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 prism light to input.mp4
   Ghosts: rose, green, violet
   ```

## 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 prism light 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.5`                 | Second the prism light fades in.                                        |
| `FRINGE`        | `8`                   | Pixels the red and blue channels move apart, each way.                  |
| `GHOSTS`        | `rose, green, violet` | Tint of each ghost copy; add or remove colors for more or fewer copies. |
| `GHOST_STEP`    | `(36, -12)`           | How far each ghost sits from the one before, in pixels right and down.  |
| `GHOST_OPACITY` | `0.14`                | Strength of each ghost copy.                                            |
| `BAND_OPACITY`  | `0.45`                | Strength of the rainbow band.                                           |
| `SWEEP`         | `2.5`                 | Seconds the rainbow band takes to cross the frame.                      |

## Without the skill

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

```
Add a prism light effect to input.mp4, fading in from 0.5 to 0.9 seconds and staying to the end. Work on each frame with Python and numpy, with ffmpeg reading and writing the video. 1) Color fringe: shift the red channel 8 pixels left and the blue channel 8 pixels right, repeating edge pixels into the gap. 2) Ghosts: add three copies of the original frame, offset 36, 72 and 108 pixels right and 12, 24 and 36 pixels up, tinted rose (255, 90, 160), green (110, 255, 140) and violet (110, 130, 255). Tint a copy by multiplying each channel by 1 + 0.8 x (2 x tint/255 - 1), and add 0.14 x (tinted copy - original frame) for each. 3) Rainbow band: a diagonal band running from top right to bottom left, 30% of the frame diagonal wide (measured along (x + y) / (width + height)), whose hue runs through one full cycle across it (red, green, blue, back to red; channel c = 0.5 + 0.5 x cos(2 pi x (position - c/3)) for c = 0, 1, 2), at strength 0.45 at its center falling off as exp(-(2.5 x offset / width)^2). It sweeps from the top-left corner to the bottom-right corner every 2.5 seconds starting at 0.5 seconds. Apply it by multiplying each channel by 1 + strength x (2 x band color - 1). Leave the first 0.5 seconds untouched, keep the size, 30fps and the audio, and save it as output.mp4. There's no text to draw.
```

## Run it without Claude

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

```
python3 prism-light.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Prism light: rainbow-tinted ghost copies, color-fringed edges and a rainbow band that sweeps across the frame.

Usage: python3 prism-light.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 prism light fades in
FADE = 0.4                 # seconds the fade-in takes
FRINGE = 8                 # pixels the red channel moves left and the blue channel moves right
GHOSTS = [(255, 90, 160), (110, 255, 140), (110, 130, 255)]  # tint of each ghost copy: rose, green, violet
GHOST_STEP = (36, -12)     # pixels each ghost sits from the one before (right, down)
GHOST_OPACITY = 0.14       # strength of each ghost copy
BAND_WIDTH = 0.3           # rainbow band width as a share of the frame diagonal
BAND_OPACITY = 0.45        # strength of the rainbow band at its center
SWEEP = 2.5                # seconds the band takes to cross the frame, top left to bottom right

def shift(img, dx, dy):
    """Move an image dx pixels right and dy pixels down, repeating the edge pixels into the gap."""
    h, w = img.shape[:2]
    ys = np.clip(np.arange(h) - dy, 0, h - 1)
    xs = np.clip(np.arange(w) - dx, 0, w - 1)
    return img[ys][:, xs]

def tint(img, color, amount):
    """Push img's colors toward color (0-1 RGB) by amount, keeping its detail: 1 doubles the matching channels."""
    return img * (1 + amount * (2 * color - 1))

def rainbow_band(t):
    """The rainbow band at time t: colors (h, w, 3) and how strong it is at each pixel (h, w, 1)."""
    pos = -BAND_WIDTH + ((t - START) / SWEEP % 1) * (1 + 2 * BAND_WIDTH)
    across = (diag - pos) / BAND_WIDTH                        # -0.5..0.5 inside the band
    hue = (across + 0.5)[..., None]
    colors = 0.5 + 0.5 * np.cos(2 * np.pi * (hue - np.array([0, 1 / 3, 2 / 3])))
    strength = np.exp(-(across * 2.5) ** 2)[..., None]
    return colors, strength

def prism(frame, t):
    amount = np.clip((t - START) / FADE, 0, 1)
    if amount == 0:
        return frame
    img = frame / 255
    out = img.copy()
    out[..., 0] = shift(img[..., 0], -FRINGE, 0)
    out[..., 2] = shift(img[..., 2], FRINGE, 0)
    for k, color in enumerate(GHOSTS, 1):
        ghost = tint(shift(img, GHOST_STEP[0] * k, GHOST_STEP[1] * k), np.array(color) / 255, 0.8)
        out += (ghost - img) * GHOST_OPACITY
    colors, strength = rainbow_band(t)
    out = tint(out, colors, strength * BAND_OPACITY)
    out = img + (out - img) * amount
    return (out * 255).round().clip(0, 255).astype(np.uint8)

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)
y, x = np.mgrid[0:h, 0:w]
diag = (x + y) / (w + h)                                      # 0 at the top left, 1 at the bottom right

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 True:
    raw = reader.stdout.read(w * h * 3)
    if len(raw) < w * h * 3:
        break
    frame = np.frombuffer(raw, np.uint8).reshape(h, w, 3)
    writer.stdin.write(prism(frame, i / fps).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)
- [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)
