Skip to main content

Music structural segmentation for the Zigify pipeline (MSAF olda + scluster)

Project description

zigify-msaf

Music structural segmentation for the Zigify pipeline. A thin CLI wrapper around MSAF that pins to the olda boundary detector and scluster labeler — the combination that scored best in evaluation against hand-annotated ground truth.

Install

uvx zigify-msaf <audio>          # ephemeral, recommended
uv pip install zigify-msaf       # into a project

uvx resolves and caches a dedicated environment on first run; subsequent calls cold-start in ~100 ms.

Use

zigify-msaf path/to/track.mp3
zigify-msaf track.mp3 --out track.segments.json
zigify-msaf track.mp3 --feature mfcc --verbose

stdout is newline-delimited JSON: progress events first, then a single final result line. stderr carries human-readable logs from msaf/librosa (silenced by default; pass --verbose to surface them).

Output schema

Each line on stdout is one JSON object. The shape of the final result line:

{
  "type": "result",
  "source": "path/to/track.mp3",
  "duration": 357.98,
  "tempo": 117.45,
  "feature": "pcp",
  "boundaryAlgo": "olda",
  "labelAlgo": "scluster",
  "nSegments": 12,
  "nClusters": 5,
  "segments": [
    { "start": 0.0,   "end": 18.1, "duration": 18.1, "cluster": "S4" },
    { "start": 18.1,  "end": 38.5, "duration": 20.4, "cluster": "S2" }
  ],
  "elapsed": 12.3
}

Earlier lines look like:

{"type":"stage","name":"loading","message":"reading track.mp3"}
{"type":"stage","name":"tempo","message":"estimating bpm"}
{"type":"stage","name":"features","message":"extracting pcp"}
{"type":"stage","name":"boundaries","message":"olda"}
{"type":"stage","name":"labels","message":"scluster"}

On failure the tool emits a single {"type": "error", ...} line and exits non-zero.

Calling from Node / TypeScript

import { spawn } from 'node:child_process'
import { createInterface } from 'node:readline'

const proc = spawn('uvx', ['zigify-msaf', audioPath], { stdio: ['ignore', 'pipe', 'pipe'] })
const rl = createInterface({ input: proc.stdout })

let result: SegmentResult | undefined
for await (const line of rl) {
  const evt = JSON.parse(line)
  if (evt.type === 'stage') console.log(`[${evt.name}] ${evt.message ?? ''}`)
  if (evt.type === 'result') result = evt
  if (evt.type === 'error') throw new Error(evt.message)
}

Algorithm choice

Evaluated against a 14-boundary ground truth on Michael Jackson — Thriller (tolerance ±5 s):

Boundary algo Hits Miss Spurious
olda 9 4 2
foote 9 4 6
sf (default) 6 7 5
cnmf 5 8 2
scluster 4 9 10
vmo 12 1 457

olda wins precision and ties for recall. Scluster labels group the segments into ~5 clusters that align with verse/chorus/outro structure on test tracks.

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_msaf-0.1.0.tar.gz (5.5 kB view details)

Uploaded Source

Built Distribution

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

zigify_msaf-0.1.0-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

File details

Details for the file zigify_msaf-0.1.0.tar.gz.

File metadata

  • Download URL: zigify_msaf-0.1.0.tar.gz
  • Upload date:
  • Size: 5.5 kB
  • 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_msaf-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d9714a7da45c412b719db81b96e9158aa6ec0aa6b3afef44185bebdae16406b8
MD5 c1e9e3ceb6f517677b0cc2693621a3a1
BLAKE2b-256 356768c83f52d40f7686da2f2389c5a1b6594c8bb71f94cc6c7aed7d8c4f6025

See more details on using hashes here.

File details

Details for the file zigify_msaf-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: zigify_msaf-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.6 kB
  • Tags: Python 3
  • 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_msaf-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a82735b69b137c37037f911cd9e0554d9c16971aa7a463ce938dafba0e5dd50b
MD5 1555d05f523c3cd4ba852243144761b5
BLAKE2b-256 05227e719444c81ff0b488c53ac27d33390a1659a986ecb2c52a9eb2dcd88f6f

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