---
title: "How to add an equalizer icon with Claude (tested prompt and script)"
description: "A dark \"now playing\" card slides up near the bottom, and four little yellow bars beside the song title bounce up and down in time with the beat. Install one skill and ask Claude Code, or run the Python script we tested yourself."
url: https://www.recharm.com/effects/equalizer-icon
---

# How to add an equalizer icon with Claude

A dark "now playing" card slides up near the bottom, and four little yellow bars beside the song title bounce up and down in time with the 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 an equalizer icon to input.mp4
   Title, artist: Golden Hour, Summer Drive
   ```

## 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 an equalizer icon 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                                        |
| --------------- | --------------------------- | --------------------------------------------------- |
| `TITLE, ARTIST` | `Golden Hour, Summer Drive` | The song title and the line under it.               |
| `START`         | `0.5`                       | Second the card slides in.                          |
| `BPM`           | `120`                       | Tempo the bars bounce to; set it to your track's.   |
| `SPEEDS`        | `(1.0, 1.5, 0.75, 1.25)`    | Bounces per beat for each of the four bars.         |
| `LOW`           | `0.25`                      | Shortest a bar gets, as a share of its full height. |
| `BAR_COLOR`     | `(255, 205, 40)`            | Bar color.                                          |
| `Y`             | `0.84`                      | Card center, as a share of the frame height.        |

## Without the skill

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

```
Add a "now playing" card with an animated equalizer icon to input.mp4 (540x960, 30fps, a 120 BPM drum loop). The card is a dark (18, 18, 22) rounded pill at 84% opacity, 80% of the frame width by 9% of the frame height (432x86 pixels), fully rounded ends, centered horizontally with its center 84% of the way down. On it, starting 1.15 card-heights from its left edge, draw "Golden Hour" in bold white at 30% of the card height, its middle at 38% down the card, and under it "Summer Drive" in bold gray (185, 185, 195) at 21% of the card height, its middle at 70% down the card. At the card's left draw four yellow (255, 205, 40) bars with rounded ends, each 10% of the card height wide with gaps of 6.5% of the card height, the first starting 38% of the card height from the card's left edge, all standing on a shared baseline so that a full bar (48% of the card height) is centered vertically in the card. Bar i's height is full x (0.25 + 0.75 x |cos(pi x (beat x speed_i + phase_i))|), where beat = seconds x 120 / 60, speeds are 1.0, 1.5, 0.75, 1.25 and phases 0, 0.35, 0.6, 0.2, so the first bar is full height on every beat and at its shortest halfway between beats. Nothing is on screen before 0.5 seconds; the card then fades in while sliding up from 5% of the frame height lower over 0.4 seconds with an ease-out (1 - (1 - p)^3), and stays to the end. Use Python with Pillow to draw the card, text and bars (don't rely on ffmpeg's drawtext filter) and ffmpeg to put them on the video, keep the audio, and save it as output.mp4.
```

## Run it without Claude

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

```
python3 equalizer-icon.py input.mp4 output.mp4
```

```
#!/usr/bin/env python3
"""Equalizer icon: a "now playing" card slides up with four yellow bars bouncing to the beat beside the song title.

Usage: python3 equalizer-icon.py input.mp4 output.mp4
Needs ffmpeg and Pillow (pip install pillow).
"""
import json
import math
import subprocess
import sys
from pathlib import Path

from PIL import Image, ImageDraw, ImageFont

TITLE, ARTIST = "Golden Hour", "Summer Drive"
START = 0.5                       # second the card slides in
SLIDE = 0.4                       # seconds the slide takes
BPM = 120                         # tempo the bars bounce to
SPEEDS = (1.0, 1.5, 0.75, 1.25)   # bounces per beat, one per bar
PHASES = (0.0, 0.35, 0.6, 0.2)    # where each bar starts in its bounce (0-1)
LOW = 0.25                        # shortest a bar gets, as a share of its full height
BAR_COLOR = (255, 205, 40)        # bar color
CARD_W, CARD_H = 0.80, 0.09       # card size as shares of the frame width and height
Y = 0.84                          # card center (0 = top, 1 = bottom)
FONTS = ["/System/Library/Fonts/Supplemental/Arial Bold.ttf",     # macOS
         "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",  # Linux
         "C:/Windows/Fonts/arialbd.ttf"]                          # Windows
FONT_FILE = next((f for f in FONTS if Path(f).exists()), None) or sys.exit("No bold font found: add one to FONTS")

def card():
    """The dark rounded card with the title and artist, and the box where the bars go."""
    cw, ch = round(w * CARD_W), round(h * CARD_H)
    img = Image.new("RGBA", (cw, ch))
    draw = ImageDraw.Draw(img)
    draw.rounded_rectangle([0, 0, cw - 1, ch - 1], radius=ch // 2, fill=(18, 18, 22, 215))
    text_x = round(ch * 1.15)
    draw.text((text_x, ch * 0.38), TITLE, font=ImageFont.truetype(FONT_FILE, round(ch * 0.30)), anchor="lm", fill="white")
    draw.text((text_x, ch * 0.70), ARTIST, font=ImageFont.truetype(FONT_FILE, round(ch * 0.21)), anchor="lm",
              fill=(185, 185, 195))
    return img

def bars(img, t):
    """Four bars standing on a shared baseline at the card's left, each bouncing at its own speed."""
    ch = img.height
    draw = ImageDraw.Draw(img)
    full = ch * 0.48
    bar_w, gap = ch * 0.10, ch * 0.065
    x = ch * 0.38
    base = ch / 2 + full / 2
    beat = t * BPM / 60
    for speed, phase in zip(SPEEDS, PHASES):
        level = LOW + (1 - LOW) * abs(math.cos(math.pi * (beat * speed + phase)))
        draw.rounded_rectangle([x, base - full * level, x + bar_w, base], radius=bar_w / 2, fill=BAR_COLOR)
        x += bar_w + gap

def overlay(t):
    img = Image.new("RGBA", (w, h))
    p = min(max((t - START) / SLIDE, 0), 1)
    if p == 0:
        return img
    ease = 1 - (1 - p) ** 3
    c = base_card.copy()
    bars(c, t)
    c.putalpha(c.getchannel("A").point(lambda a: round(a * ease)))
    img.alpha_composite(c, (round((w - c.width) / 2), round(h * Y - c.height / 2 + (1 - ease) * h * 0.05)))
    return img

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 render(src, out):
    """Draw overlay(t) on every frame of src and save to out, keeping the audio."""
    ff = subprocess.Popen(["ffmpeg", "-y", "-v", "error", "-i", src,
                           "-f", "rawvideo", "-pix_fmt", "rgba", "-s", f"{w}x{h}", "-r", rate, "-i", "-",
                           "-filter_complex", "[0:v][1:v]overlay=shortest=1,format=yuv420p[v]",
                           "-map", "[v]", "-map", "0:a?", "-c:v", "libx264", "-crf", "18", "-c:a", "copy", out],
                          stdin=subprocess.PIPE)
    for i in range(math.ceil(duration * fps)):
        ff.stdin.write(overlay(i / fps).tobytes())
    ff.stdin.close()
    if ff.wait():
        sys.exit("ffmpeg failed")

src, out = sys.argv[1:3]
w, h, rate, fps, duration = probe(src)
base_card = card()
render(src, out)
```

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