Timestamped structural analysis of a music file for scene and edit planning.
track-analyst runs a music file through librosa and writes a
markdown report describing the track's structure, energy arc, key, BPM, beat drops, and
transient hits — a readable cut sheet you can keep next to your editor or DAW.
It also outputs JSON if you'd rather pipe it into your own tooling.
Hand-annotating a song to plan an edit is tedious: scrub, mark, scrub, mark. This tool gives you a machine-readable map of the track in seconds — section bounds, BPM, energy curve, and exact timestamps for every notable hit.
Typical use cases:
- Scene planning for music videos, VRChat films, AMVs, dance choreography
- Cut sheets for editors — beat drops, transient hits, energy arcs
- DJ / set prep — quickly seeing where the breaks and drops sit
- Quick exploration — get a sense of a track's structure without scrubbing the waveform
pip install git+https://github.com/thevoidwolf/track-analyst.gitOr clone and install editable:
git clone https://github.com/thevoidwolf/track-analyst.git
cd track-analyst
pip install -e .Requires Python 3.9+. Pulls in librosa, numpy, and scipy.
Note:
librosaneedsffmpeg(or a decoder backend likesoundfile) to read MP3. Most systems have one already; if not:apt install ffmpeg/brew install ffmpeg.
# Print markdown report to stdout
track-analyst song.mp3
# Write to file
track-analyst song.mp3 -o song.analysis.md
# Ask for more (or fewer) structural sections
track-analyst song.mp3 --segments 12
# JSON output for downstream tooling
track-analyst song.mp3 --format json -o song.analysis.jsonYou can also invoke it as a module:
python -m track_analyst song.mp3| Flag | Default | What it does |
|---|---|---|
file |
— | Audio file (MP3, WAV, FLAC, OGG, …) |
-o, --output |
stdout | Write report to this path |
--segments N |
8 |
Target number of structural sections |
--format {markdown,json} |
markdown |
Output format |
--version |
— | Print version and exit |
- Tempo & beat grid — global BPM and per-beat timestamps
- Estimated key — pitch class (C, C#, D, …); does not distinguish major/minor
- Structural sections — beat-synced MFCC + agglomerative clustering picks regions of consistent sonic character (e.g. "intro", "verse", "drop", "outro" — though the tool doesn't label them, just bounds them)
- Energy arc — RMS loudness in 10-second windows, drawn as ASCII bars
- Sub-bass energy — 20–200 Hz band, useful for spotting drops and bass-heavy moments
- Spectral brightness — high-frequency content, proxy for "bright" vs. "dark" passages
- Harmonic / percussive character — each section is tagged
Melodic/Driving/Percussivebased on H/P ratio - Beat drops & energy surges — sudden RMS increases (good cut points)
- Transient hits — top 10% of onsets by strength, ≥0.5s spacing
- Bar map — every 4 bars, so you can correlate scene numbers to bar numbers
A real, full report is checked in at
examples/run-amok.analysis.md. Abbreviated below.
# Track Analysis: `night-drive.mp3`
## Overview
| | |
|---|---|
| **Duration** | 03:42.18 (222s) |
| **BPM** | 128.0 |
| **Est. Key** | F# *(pitch class only — not major/minor)* |
| **Detected Beats** | 472 |
## Structure
| # | Start → End | Dur | Energy | Bass | Brightness | BPM | Character |
|---|-------------|-----|--------|------|------------|-----|-----------|
| 1 | 00:00.00 → 00:16.00 | 16s | Low | Low | Dark | 128 | Melodic |
| 2 | 00:16.00 → 00:48.00 | 32s | Med-Low | Mid | Mid | 128 | Driving |
| 3 | 00:48.00 → 01:20.00 | 32s | High | High | Bright | 128 | Percussive |
| 4 | 01:20.00 → 02:08.00 | 48s | PEAK | High | Bright | 128 | Driving |
| … | … | … | … | … | … | … | … |
## Energy Map *(10s windows)*
`00:00.00` ██░░░░░░░░ Low
`00:10.00` ████░░░░░░ Med-Low
`00:20.00` ██████░░░░ Medium ♦
`00:30.00` ████████░░ Med-High ♦
`00:40.00` ██████████ PEAK ♦
…
## Notable Events
| Timestamp | Event | Intensity |
|-----------|-------|-----------|
| `00:48.12` | ⚡ Energy surge | ████████ |
| `01:20.04` | 🔨 Strong transient hit | ███████░ |
| `02:08.50` | ⚡ Energy surge | ██████░░ |- Key detection is pitch-class only — doesn't tell you major vs. minor, and chromagram estimates can be wrong on noisy or atonal material.
- Section boundaries are approximations. They're acoustic-similarity clusters, not labeled song parts; expect to nudge them by ear.
- Beat tracking assumes 4/4-ish music. Free time, polyrhythmic, or extreme tempo-change tracks will confuse it.
- Voice-only or non-musical audio (speech, ambience) gives noisy/unhelpful output.
from track_analyst import analyze, to_markdown
import json
data = analyze("song.mp3", n_segments=10)
print(to_markdown(data)) # markdown report
print(json.dumps(data, indent=2)) # raw structured dataanalyze() returns a dict with filename, duration, bpm, key, total_beats,
segments, drops, transients, timeline, and bar_markers.
Issues and PRs welcome — especially:
- Major/minor key detection (Krumhansl-Schmuckler or similar)
- Per-section labelling (intro / verse / drop / break / outro)
- A small test fixture and a CI check
- Faster paths for long tracks
Keep changes scoped and avoid pulling in heavy ML deps unless they meaningfully improve output quality.
MIT © 2026 voidwolf