---
title: "How to add a pixel sorting with Claude (tested prompt and script)"
description: "From 1 to 5 seconds the bright backdrop and label smear into jagged horizontal streaks as each bright run of pixels is reordered dark to bright, while the dark dropper and purple glass stay put. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/pixel-sorting
---

# How to add a pixel sorting with Claude

From 1 to 5 seconds the bright backdrop and label smear into jagged horizontal streaks as each bright run of pixels is reordered dark to bright, while the dark dropper and purple glass stay put.

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 pixel sorting to input.mp4
   Seconds the sorting runs: 1.0, 5.0
   Seconds the streaks take to spread at the start and to pull back at the end: 0.6
   ```

## 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 pixel sorting 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, END` | `1.0, 5.0` | Seconds the sorting runs.                                                                        |
| `RAMP`       | `0.6`      | Seconds the streaks take to spread at the start and to pull back at the end.                     |
| `FROM, TO`   | `225, 195` | Brightness cut-off at the edges of the ramp and at full strength; lower sorts more of the frame. |
| `FPS`        | `30`       | Output frame rate.                                                                               |

## Without the skill

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

```
Add a pixel sorting effect to input.mp4 using Python with numpy and ffmpeg, frame by frame at 30fps. From 1.0 to 5.0 seconds, in every row of the frame find each run of neighboring pixels whose brightness (0.299 R + 0.587 G + 0.114 B) is above a cut-off, and sort the pixels inside each run by brightness, darkest on the left; leave every pixel at or below the cut-off where it is. The cut-off eases (smoothstep) from 225 down to 195 over 1.0 to 1.6 seconds, holds at 195, then eases back up to 225 over 4.4 to 5.0 seconds. Leave frames before 1.0 and from 5.0 seconds on untouched. Keep the audio and save it as output.mp4 (H.264, yuv420p).
```

## Run it without Claude

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

```
python3 pixel-sorting.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Pixel sorting: across the bright parts of each row, pixels are reordered dark to bright into long horizontal streaks.

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

import numpy as np

START, END = 1.0, 5.0    # seconds the sorting runs
RAMP = 0.6               # seconds the streaks take to spread at the start and to pull back at the end
FROM, TO = 225, 195      # brightness cut-off (0-255) at the start of the ramp and at full strength;
                         # only runs of pixels brighter than the cut-off get sorted
FPS = 30                 # output frame rate

def probe(path):
    info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
                                               "stream=width,height", "-of", "json", path]))
    return info["streams"][0]["width"], info["streams"][0]["height"]

def threshold(t):
    """The brightness cut-off at time t, or None outside the effect. Lower cut-off = more of the frame sorted."""
    if not START <= t < END:
        return None
    p = min(t - START, END - t, RAMP) / RAMP
    p = p * p * (3 - 2 * p)   # ease in and out
    return FROM + (TO - FROM) * p

def pixel_sort(img, cut):
    """Sort every run of pixels brighter than cut along its row, darkest first, leaving other pixels in place."""
    luma = img @ np.array([0.299, 0.587, 0.114])
    bright = luma > cut
    # a new segment starts at every pixel that isn't bright and at the first pixel of each bright run
    starts = ~bright | np.pad(~bright[:, :-1], ((0, 0), (1, 0)), constant_values=True)
    segment = np.cumsum(starts, axis=1)
    # sorting by (segment, brightness) keeps segments where they are and orders pixels inside each one
    order = np.argsort(segment * 256 + np.where(bright, luma, 0), axis=1, kind="stable")
    return np.take_along_axis(img, order[:, :, None], axis=1)

src, out = sys.argv[1:3]
w, h = probe(src)
dec = subprocess.Popen(["ffmpeg", "-v", "error", "-i", src, "-vf", f"fps={FPS}", "-f", "rawvideo", "-pix_fmt", "rgb24", "-"],
                       stdout=subprocess.PIPE)
enc = subprocess.Popen(["ffmpeg", "-y", "-v", "error", "-f", "rawvideo", "-pix_fmt", "rgb24", "-s", f"{w}x{h}",
                        "-r", str(FPS), "-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:
    data = dec.stdout.read(w * h * 3)
    if len(data) < w * h * 3:
        break
    img = np.frombuffer(data, np.uint8).reshape(h, w, 3)
    cut = threshold(i / FPS)
    enc.stdin.write((img if cut is None else pixel_sort(img, cut)).tobytes())
    i += 1
enc.stdin.close()
if enc.wait() or dec.wait():
    sys.exit("ffmpeg failed")
```

## More distortion and glitch

- [Anaglyph 3D **Anaglyph 3D**](https://www.recharm.com/effects/anaglyph-3d)
- [Black hole **Black hole**](https://www.recharm.com/effects/black-hole)
- [Bulge and pinch **Bulge and pinch**](https://www.recharm.com/effects/bulge-pinch)
- [Datamosh **Datamosh**](https://www.recharm.com/effects/datamosh)
- [Disintegration **Disintegration**](https://www.recharm.com/effects/disintegration)

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