---
title: "How to add a background blur with Claude (tested prompt and script)"
description: "Half a second in, the holographic backdrop and the acrylic block under the bottle melt into a soft, creamy blur while the purple serum bottle stays crisp down to the small print on its label. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/background-blur
---

# How to add a background blur with Claude

Half a second in, the holographic backdrop and the acrylic block under the bottle melt into a soft, creamy blur while the purple serum bottle stays crisp down to the small print on its label.

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 background blur to input.mp4
   Background blur (Gaussian sigma) as a share of the frame width: 16 px on a 540-wide video: 0.03
   Second the background starts to go soft: 0.5
   ```

## 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 background blur 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                                                                               |
| ------------ | ------- | ------------------------------------------------------------------------------------------ |
| `BLUR`       | `0.03`  | Background blur (Gaussian sigma) as a share of the frame width: 16 px on a 540-wide video. |
| `START`      | `0.5`   | Second the background starts to go soft.                                                   |
| `EASE`       | `0.5`   | Seconds it takes to reach full blur.                                                       |
| `EDGE`       | `1.5`   | Softness of the cut-out's edge in pixels.                                                  |
| `MASK_EVERY` | `2`     | Cut the product out on every Nth frame and reuse it in between.                            |

## Without the skill

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

```
Blur the background of input.mp4 (540x960, the camera circles a purple serum bottle standing on an acrylic block) like a portrait-mode lens, keeping the bottle sharp. Leave the video untouched before 0.5 seconds. From 0.5 seconds, cut the bottle (with its dropper cap) out of every frame with rembg (u2net model), or every second frame and reuse the cut-out in between, and soften the cut-out's edge with a 1.5 px Gaussian blur. Paint the bottle out of the frame first by filling its area from the surrounding backdrop, so the blur doesn't spread a purple halo, then Gaussian-blur that plate; the blur's sigma eases from 0 to 16 px (3% of the frame width) between 0.5 and 1.0 seconds with a smoothstep curve and stays at 16 px to the end. Everything that isn't the bottle goes soft, the acrylic block included. Put the untouched bottle back on top through its cut-out. Use Python with OpenCV and numpy for the blur and ffmpeg to read and write the frames (no text is drawn; 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 `background-blur.py` and run:

```
python3 background-blur.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Background blur: everything behind the product melts into a soft, creamy blur while the product itself stays pin sharp.

Usage: python3 background-blur.py input.mp4 output.mp4
Needs ffmpeg, OpenCV, numpy, Pillow and rembg to cut the product out of every frame
(pip install opencv-python-headless numpy pillow "rembg[cpu]"; rembg downloads its u2net model on first use).
"""
import json
import subprocess
import sys

import cv2
import numpy as np
from PIL import Image
from rembg import new_session

BLUR = 0.03      # background blur (Gaussian sigma) as a share of the frame width: 16 px on a 540-wide video
START = 0.5      # second the background starts to go soft
EASE = 0.5       # seconds it takes to reach full blur
EDGE = 1.5       # softness of the cut-out's edge in pixels
MASK_EVERY = 2   # cut the product out on every Nth frame and reuse it in between (the camera moves slowly)

def blur(img, sigma):
    return cv2.GaussianBlur(img, (0, 0), sigma, borderType=cv2.BORDER_REFLECT) if sigma > 0.3 else img

def amount(t):
    """0 before START, easing to 1 over EASE seconds."""
    p = min(max((t - START) / EASE, 0), 1)
    return p * p * (3 - 2 * p)

def cutout(rgb):
    """The product's matte, 0-1, with a slightly softened edge."""
    return blur(np.asarray(session.predict(Image.fromarray(rgb))[0], np.float32) / 255, EDGE)

def portrait(rgb, mask, t):
    """Blur the backdrop with the product painted out of it, then put the sharp product back on top."""
    img = rgb.astype(np.float32)
    # fill the product's hole from the backdrop around it (worked out at quarter size, it's only a rough fill),
    # so the blur doesn't smear a halo of the product's colors
    keep = 1 - cv2.dilate(mask, np.ones((9, 9), np.uint8))
    small = cv2.resize(np.dstack([img * keep[:, :, None], keep]), (w // 4, h // 4), interpolation=cv2.INTER_AREA)
    small = blur(small, w * 0.0125)
    fill = cv2.resize(small[:, :, :3] / np.maximum(small[:, :, 3:], 1e-3), (w, h))
    backdrop = blur(img * keep[:, :, None] + fill * (1 - keep[:, :, None]), BLUR * w * amount(t))
    m = mask[:, :, None]
    return (img * m + backdrop * (1 - m)).clip(0, 255).round().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)

def render(src, out):
    """Read src frame by frame, blur each one's background and save to out, keeping the audio."""
    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, mask = 0, None
    while raw := reader.stdout.read(w * h * 3):
        rgb = np.frombuffer(raw, np.uint8).reshape(h, w, 3)
        t = i / fps
        if t >= START and (mask is None or i % MASK_EVERY == 0):
            mask = cutout(rgb)
        writer.stdin.write((rgb if t < START else portrait(rgb, mask, t)).tobytes())
        i += 1
    writer.stdin.close()
    if reader.wait() or writer.wait():
        sys.exit("ffmpeg failed")

src, out = sys.argv[1:3]
w, h, rate, fps = probe(src)
session = new_session("u2net")
render(src, out)
```

## More motion and camera

- [2.5D parallax photo **2.5D parallax photo**](https://www.recharm.com/effects/2-5d-parallax-photo)
- [Back-and-forth loop **Back-and-forth loop**](https://www.recharm.com/effects/back-and-forth-loop)
- [Bullet time **Bullet time**](https://www.recharm.com/effects/bullet-time)
- [Cinemagraph **Cinemagraph**](https://www.recharm.com/effects/cinemagraph)
- [Clone effect **Clone effect**](https://www.recharm.com/effects/clone-effect)

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