---
title: "How to add a glitch on beat with Claude (tested prompt and script)"
description: "On every kick of the drum loop the picture jolts, tears into sideways bands and splits into red and blue for four frames, then snaps clean until the next beat. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/glitch-on-beat
---

# How to add a glitch on beat with Claude

On every kick of the drum loop the picture jolts, tears into sideways bands and splits into red and blue for four frames, then snaps clean until the next beat.

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 glitch on beat to input.mp4
   Rough tempo, so the beat tracker doesn't lock onto every other beat: 120
   Frames each glitch lasts, starting on the beat's frame: 4
   ```

## 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 glitch on beat 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                                                            |
| ------------ | ------- | ----------------------------------------------------------------------- |
| `BPM_GUESS`  | `120`   | Rough tempo, so the beat tracker doesn't lock onto every other beat.    |
| `LENGTH`     | `4`     | Frames each glitch lasts, starting on the beat's frame.                 |
| `SPLIT`      | `14`    | How far red moves left and blue moves right, in pixels.                 |
| `TEARS`      | `5`     | Horizontal bands torn sideways on each glitch frame.                    |
| `TEAR_SHIFT` | `60`    | Furthest a torn band slides sideways, in pixels.                        |
| `JUMP`       | `10`    | Furthest the whole picture jumps, in pixels.                            |
| `SEED`       | `7`     | Random seed; change it for a different but repeatable pattern of tears. |
| `RATE`       | `22050` | Audio sample rate the beat tracker uses.                                |

## Without the skill

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

```
Add a glitch on every beat to input.mp4. Use librosa to find the beats in its music track (start the beat tracker at 120 BPM and move each beat back to where its drum hit starts), and round each beat to a video frame. On each beat frame and the 3 frames after it (4 frames, about 0.13 seconds), glitch the picture: shift the whole frame by a random amount up to 10 pixels in each direction, slide 5 random horizontal bands (each 8 to 96 pixels tall) sideways by up to 60 pixels, then move the red channel 14 pixels left and the blue channel 14 pixels right (wrapping round the edges). Use a fixed random seed. Leave every other frame untouched. Keep the size, 30fps and the audio. Use ffmpeg and numpy and save it as output.mp4.
```

## Run it without Claude

This is the exact script we tested. Save it as `glitch-on-beat.py` and run:

```
python3 glitch-on-beat.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Glitch on beat: librosa finds the beats in the music and on each one the picture splits into red and blue and tears.

Usage: python3 glitch-on-beat.py input.mp4 output.mp4  (the input needs a music track)
Needs ffmpeg, librosa and numpy (pip install librosa numpy).
"""
import json
import subprocess
import sys

import librosa
import numpy as np

BPM_GUESS = 120   # rough tempo, so the beat tracker doesn't lock onto every other beat
LENGTH = 4        # frames each glitch lasts, starting on the beat's frame
SPLIT = 14        # red moves this many pixels left and blue this many right
TEARS = 5         # horizontal bands torn sideways on each glitch frame
TEAR_SHIFT = 60   # furthest a torn band slides sideways, in pixels
JUMP = 10         # furthest the whole picture jumps, in pixels
SEED = 7          # change for a different (but repeatable) pattern of tears
RATE = 22050      # audio sample rate the beat tracker uses

def probe(path):
    info = json.loads(subprocess.check_output(["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries",
                                               "stream=width,height,r_frame_rate:format=duration", "-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), float(info["format"]["duration"])

def beat_frames(path):
    """Video frame number of each beat, moved back to where its drum hit starts."""
    pcm = subprocess.check_output(["ffmpeg", "-v", "error", "-i", path, "-ac", "1", "-ar", str(RATE), "-f", "f32le", "-"])
    audio = np.frombuffer(pcm, np.float32)
    hop = 256  # analysis step in samples (about 12ms), fine enough to land on the right video frame
    strength = librosa.onset.onset_strength(y=audio, sr=RATE, hop_length=hop)
    _, beats = librosa.beat.beat_track(onset_envelope=strength, sr=RATE, hop_length=hop, start_bpm=BPM_GUESS)
    hits = librosa.frames_to_time(librosa.onset.onset_backtrack(beats, strength), sr=RATE, hop_length=hop)
    return {round(t * fps) for t in hits}

def glitch(frame, rng):
    """Jump the whole picture, slide random bands sideways, then pull red and blue apart."""
    img = np.roll(frame, [rng.integers(-JUMP, JUMP + 1), rng.integers(-JUMP, JUMP + 1)], axis=(0, 1))
    for _ in range(TEARS):
        y = rng.integers(0, h - 8)
        band = slice(y, y + rng.integers(8, h // 10))
        img[band] = np.roll(img[band], rng.integers(-TEAR_SHIFT, TEAR_SHIFT + 1), axis=1)
    img[:, :, 0] = np.roll(img[:, :, 0], -SPLIT, axis=1)
    img[:, :, 2] = np.roll(img[:, :, 2], SPLIT, axis=1)
    return img

src, out = sys.argv[1:3]
w, h, rate, fps, duration = probe(src)
glitching = {b + i for b in beat_frames(src) for i in range(LENGTH)}
rng = np.random.default_rng(SEED)

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((glitch(frame, rng) if i in glitching else frame).tobytes())
    i += 1
writer.stdin.close()
if writer.wait() or reader.wait():
    sys.exit("ffmpeg failed")
```

## More music-synced visuals

- [AI voice orb **AI voice orb**](https://www.recharm.com/effects/ai-voice-orb)
- [Audio-reactive blob **Audio-reactive blob**](https://www.recharm.com/effects/audio-reactive-blob)
- [Audio-reactive particles **Audio-reactive particles**](https://www.recharm.com/effects/audio-reactive-particles)
- [Audio-reactive text **Audio-reactive text**](https://www.recharm.com/effects/audio-reactive-text)
- [Audio waveform **Audio waveform**](https://www.recharm.com/effects/audio-waveform)

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