Skip to main content

zigify-madmom

Audio analysis CLI: percussive onsets, beats, and downbeats for a single audio file, packaged as a uvx-runnable tool with a streaming JSON protocol so other processes (Node, Bun, anything) can consume progress events live and capture the final result cleanly.

Built on madmom: SuperFlux ODF on the HPSS percussive component, adaptive peak picking, density-aware NMS, an energy-rescue pass, and madmom's RNN/DBN beat & downbeat trackers.

Install / run

# one-shot, no install
uvx zigify-madmom path/to/audio.mp3 > result.json

# project-local (in a uv project)
uv add zigify-madmom

# pip
pip install zigify-madmom

Heads up — madmom on PyPI is stale. The last PyPI release of madmom (0.16.1, 2018) does not work with NumPy >= 2. This package declares madmom as a regular dependency for PyPI compliance, but in practice you'll want the current main branch from CPJKU/madmom. When using uv, the bundled [tool.uv.sources] in pyproject.toml already does this for you. With plain pip, install the git version yourself first:

pip install "madmom @ git+https://github.com/CPJKU/madmom"
pip install zigify-madmom

CLI

zigify-madmom AUDIO [--config FILE] [--write-viewer] [--viewer-dir DIR]
              [--stdin-suffix .wav] [--print-defaults]
  • AUDIO — path to an audio file, or - to read raw bytes from stdin (buffered to a temp file because madmom's beat trackers expect a path).
  • --config FILE — JSON config file. Keys are deep-merged over the defaults; omit to use defaults. See --print-defaults for the schema.
  • --write-viewer — also write <stem>.png, <stem>.html, <stem>.json next to the audio. The HTML is a self-contained player with a synced cursor over the saved plot.
  • --viewer-dir DIR — override where viewer files go (default: alongside the audio file).
  • --stdin-suffix — extension for the temp file when reading stdin (default .wav); set to match your input format if needed.
  • --print-defaults — print the default config as JSON and exit. Use as a starting template:
    zigify-madmom --print-defaults > my-config.json
    

Examples

# defaults, capture payload to a file
zigify-madmom audio.mp3 > out.json

# custom config + viewer files
zigify-madmom audio.mp3 --config tuned.json --write-viewer

# pipe from ffmpeg
ffmpeg -i input.flac -f wav - | zigify-madmom - --stdin-suffix .wav > out.json

Streaming protocol

The CLI splits its output across two streams so a parent process can display progress live and still parse the final result:

Stream Format Purpose
stderr NDJSON, one per line Progress / log events
stdout One JSON object Final analysis payload

Every stderr line is a complete JSON object with at minimum level and msg, plus optional fields like stage, counters, paths. Errors come through the same channel with "level": "error" and a traceback field; the process exits non-zero.

// stderr — observed live
{"level":"info","msg":"Loading audio","stage":"load","path":"audio.mp3"}
{"level":"info","msg":"Computing SuperFlux ODF","stage":"odf","hpss":true}
{"level":"info","msg":"Onset NMS complete","stage":"onset_nms","primary":560,"raw":949,"culled":389}
{"level":"info","msg":"Energy rescue complete","stage":"onset_rescue","energy":360}
{"level":"info","msg":"Tracking beats","stage":"beats"}
{"level":"info","msg":"Tracking downbeats","stage":"downbeats"}
{"level":"info","msg":"Tempo computed","stage":"tempo","bpm_med":100.0,"bpm_min":71.4,"bpm_max":107.1}
{"level":"info","msg":"Done","stage":"done"}
// stdout — single JSON object at end
{
  "meta": {
    "file": "audio.mp3",
    "duration_s": 242.98,
    "fps": 100,
    "mode": "HPSS+SuperFlux",
    "tempo_bpm": 100.0,
    "tempo_range_bpm": [71.4, 107.1],
    "beats_per_bar_candidates": [4, 4]
  },
  "bars": [
    { "index": 1, "start_s": 0.123, "end_s": 2.521,
      "beats": [0.123, 0.722, 1.323, 1.922],
      "rms_db": -18.4, "odf_energy": 0.27 }
  ],
  "beats":     [0.123, 0.722, 1.323, /* ... */],
  "downbeats": [0.123, 2.521, /* ... */],
  "onsets":         [{ "t": 0.42, "strength": 0.61 }, /* ... */],
  "onsets_energy":  [{ "t": 0.45, "strength": 0.18 }, /* ... */]
}

Consuming from TypeScript

import { spawn } from "node:child_process";
import { createInterface } from "node:readline";

const proc = spawn("zigify-madmom", ["audio.mp3", "--config", "cfg.json"]);

const rl = createInterface({ input: proc.stderr });
rl.on("line", (line) => {
  const evt = JSON.parse(line);
  console.log(`[${evt.stage ?? evt.level}] ${evt.msg}`);
});

let stdout = "";
proc.stdout.on("data", (chunk) => (stdout += chunk));

proc.on("close", (code) => {
  if (code !== 0) throw new Error(`exit ${code}`);
  const payload = JSON.parse(stdout);
  // payload.meta, payload.bars, payload.beats, ...
});

Exit codes

Code Meaning
0 Success
1 Analysis error (see stderr traceback)
2 Bad arguments / missing file / config parse error
130 Interrupted (Ctrl+C)

Config

The full default config is available via zigify-madmom --print-defaults. Top-level keys:

  • fps — analysis frame rate (default 100)
  • use_hpss — gate the ODF on the HPSS percussive component (default true)
  • hpss.{masking_p, harmonic_filter, percussive_filter} — HPSS knobs
  • onset.{offset, pre_avg_s, post_avg_s, combine_s, nms_quiet_s, nms_loud_s, rescue_min_density, rescue_min_strength, rescue_min_spacing_s} — peak picking, density-adaptive NMS, and the energy-rescue pass
  • beats.beats_per_bar — candidate meters for the DBN downbeat tracker
  • viewer.{png_px_per_minute, png_dpi, png_min_width_in} — only used with --write-viewer

Partial configs are deep-merged; only override what you want to change.

{
  "use_hpss": false,
  "onset": { "offset": 0.15, "nms_loud_s": 0.25 }
}

Programmatic use

from zigify_madmom import analyze, load_config

cfg = load_config(None)   # defaults; pass a path to override
result = analyze("audio.mp3", cfg)
payload = result["payload"]

analyze() accepts an optional log callable for custom progress reporting: analyze(path, cfg, log=lambda msg, **kw: ...).

Development

git clone <repo>
cd zigify-madmom
uv sync
uv run zigify-madmom audio/your-track.mp3

License

MIT — see LICENSE.

Metadata

Release files for zigify-madmom 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zigify-madmom 1.1.0
File Size Uploaded
zigify_madmom-1.1.0.tar.gz 30.4 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for zigify-madmom 1.1.0
File Interpreter ABI Platform
zigify_madmom-1.1.0-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details

Total release size: 61.3 MB

Release files / zigify_madmom-1.1.0.tar.gz

Download URL zigify_madmom-1.1.0.tar.gz
Size 30.4 MB
Tags Source
SHA-256 checksum
How to use checksums
237f7f3872d9a49f928883f9558d43195b793541498238ba7e4f229ee09800e5
BLAKE2b-256 checksum
How to use checksums
e084aa093dbeba09f3119d5b2ce541245684c44020d41671d0237273e65a00bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / zigify_madmom-1.1.0-cp312-cp312-macosx_11_0_arm64.whl

Download URL zigify_madmom-1.1.0-cp312-cp312-macosx_11_0_arm64.whl
Size 30.9 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f5bf03359f756c341cf31869116f3aad833c158fc60afa4e7c33485133676b74
BLAKE2b-256 checksum
How to use checksums
f8073fc4e24f0d5279d204adbbd4c34fbbd54b8a301794091165ffc8427b9838
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page