Skip to main content

Audio analysis CLI: SuperFlux onsets + RNN/DBN beats and downbeats, with streaming NDJSON logs.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zigify_madmom-1.1.0.tar.gz (30.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zigify_madmom-1.1.0-cp312-cp312-macosx_11_0_arm64.whl (30.9 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

File details

Details for the file zigify_madmom-1.1.0.tar.gz.

File metadata

  • Download URL: zigify_madmom-1.1.0.tar.gz
  • Upload date:
  • Size: 30.4 MB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for zigify_madmom-1.1.0.tar.gz
Algorithm Hash digest
SHA256 237f7f3872d9a49f928883f9558d43195b793541498238ba7e4f229ee09800e5
MD5 501cdd40b5873ea2e93759f7194e3713
BLAKE2b-256 e084aa093dbeba09f3119d5b2ce541245684c44020d41671d0237273e65a00bb

See more details on using hashes here.

File details

Details for the file zigify_madmom-1.1.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

  • Download URL: zigify_madmom-1.1.0-cp312-cp312-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 30.9 MB
  • Tags: CPython 3.12, macOS 11.0+ ARM64
  • Uploaded using 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}

File hashes

Hashes for zigify_madmom-1.1.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f5bf03359f756c341cf31869116f3aad833c158fc60afa4e7c33485133676b74
MD5 5b6a557a414ace8f1c8aaf56d7d5ae50
BLAKE2b-256 f8073fc4e24f0d5279d204adbbd4c34fbbd54b8a301794091165ffc8427b9838

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page