Livechord Beat Refiner
> Bidirectional Transformer that refines a prior beat tracker's output > (beatthis, madmom, or librosa) using full-context audio features. > Drops in as a post-processing pass to fix phase drift and bar misalignment...
Model source
- Kind
- Other
- File size
- 12.2 MB
- Version
- vRevision faa1ce0
- Updated
- Oct 6, 2026
- Downloads
- 5
- Source
- Hugging Face
Source description
livechord-beat-refiner
Bidirectional Transformer that refines a prior beat tracker's output (beat_this, madmom, or librosa) using full-context audio features. Drops in as a post-processing pass to fix phase drift and bar misalignment without re-running the expensive front-end model.
πΉ Try it live
This model powers the beat / bar grid behind the chord ribbon, 88-key waterfall, and AI accompaniment at livechord.org β upload an MP3 and play along on a virtual piano with chord cards that follow the music.
Quickstart
pip install livechord-beat-refiner
from livechord_beat_refiner import refine
# 1. Run any beat tracker (beat_this, madmom, librosa, ...) β beats / downbeats lists
# 2. Pass them to refine() together with the audio file:
out = refine(
audio_path="song.flac",
beats=[0.0, 0.52, 1.05, 1.57, ...], # seconds
downbeats=[0.0, 2.10, 4.21, ...], # seconds
)
print(out["refined_beats"]) # list[float] β refined beat times
print(out["refined_downbeats"]) # list[float]
print(out["applied"]) # bool β False if model couldn't run; input echoed back
The checkpoint is downloaded from this Hub repo on first call (cached
under ~/.cache/huggingface/hub). To use a local file, pass
checkpoint_path="path/to/model.safetensors".
What the model does
audio (22050 Hz, mono)
β
βΌ
[ CQT 84 + chroma 12 + onset + RMS ] β 98 audio channels
[ initial beat grid ] β 1 channel (from prior tracker)
[ initial downbeat grid ] β 1 channel
β concat β (T, 100)
βΌ
[ Linear(100β256) + sinusoidal pos enc ]
β
βΌ
[ TransformerEncoder Γ 6 (d=256, h=4, ffn=512, GELU, pre-LN) ]
β
βΌ ββββββββββββββ
ββββββββββββββββ€ beat head ββββ sigmoid β peak-pick β beat times (s)
β ββββββββββββββ
β ββββββββββββββ
ββββββββββββββββ€ db head ββββ sigmoid β peak-pick β downbeat times (s)
β ββββββββββββββ
β ββββββββββββββ
ββββββββββββββββ€ cb head ββββ aux supervision (not production-ready, see Limitations)
ββββββββββββββ
- Parameters: β 3.0 M
- Frame rate: 10.766 fps (sr=22050, hop=2048)
- Max audio length: β 15 min (longer truncated)
- Inference budget: ~1.8 s per minute of audio on CPU; ~0.3 s/min on a recent NVIDIA GPU.
Why a refiner
State-of-the-art beat trackers (beat_this, madmom) are strong on percussive genres but drift in three failure modes that show up over and over in real-world libraries:
- Phase shift on slow ballads β the tracker locks onto an offbeat or jumps half a beat partway through.
- Doubletime / halftime confusion β pop ballads tracked at 138 BPM that are actually 69 BPM.
- Bar misalignment β beats are right, downbeats off by one.
Re-running the front-end tracker rarely helps (same audio, same answer). The refiner sees both the audio AND the prior tracker's grid as input hints, then re-emits a cleaner grid by attending across the full song with chord-boundary cues as auxiliary supervision.
Metrics
Held-out test set: 7,389 songs (15% stratified holdout from a 13,017-song corpus). Tolerance: Β±1 frame β Β±93 ms (mir_eval-style F-measure; standard is 70 ms).
Headline (gold-quality subset, n=510)
Songs whose prior-tracker output passed coefficient-of-variation < 0.05 AND
chord-change alignment β₯ 0.5 filters β i.e. the most reliable references.
| Metric | F1 | Precision | Recall |
|---|---|---|---|
| Beat | 0.920 | 0.910 | 0.933 |
| Downbeat | 0.936 | 0.925 | 0.952 |
Full holdout (n=7,389)
| Metric | F1 | Precision | Recall |
|---|---|---|---|
| Beat | 0.881 | 0.859 | 0.914 |
| Downbeat | 0.914 | 0.906 | 0.930 |
The "skip" quality bucket (6,087 / 7,389 songs) consists of tracks whose prior-tracker reference didn't pass the gold/ok filters, so their "labels" are noisy by construction. The lower full-holdout F1 reflects label noise, not model regression β quality is monotonic (gold > ok > skip), which is the structural sanity check.
Per-bucket
| beat_quality | n | beat F1 | downbeat F1 |
|---|---|---|---|
| gold | 510 | 0.920 | 0.936 |
| ok | 792 | 0.906 | 0.925 |
| skip | 6,087 | 0.874 | 0.910 |
Reproduce with the eval script in the LiveChord repo.
Note on baseline
The training corpus uses each song's own prior-tracker output as the supervision target whenever that output passed the filter. So the F1 reported here measures how well the refiner preserves correct beats while also absorbing chord-boundary auxiliary signal β not "refiner > beat_this" head to head. An independent ground-truth comparison (MIREX Beatles, GTZAN_rhythm) is on the v2 roadmap.
Training data
- Corpus: 13,017 songs from a personal music library, predominantly East Asian pop, Western pop / rock / R&B, jazz standards, and a smaller classical / folk tail.
- Labels: prior-tracker output (beat_this
final0checkpoint) filtered to gold / ok quality bands by coefficient-of-variation and chord-alignment heuristics. - Split: 70% train / 15% val / 15% test, stratified by (beat_quality Γ chord_quality).
- Augmentation: random initial-grid corruption during training (jitter / drop / insert / phase-shift) so the model learns to denoise rather than copy the input grid verbatim.
Limitations
- Chord-boundary head is auxiliary supervision, not a production target. cb F1 on gold = 0.243. v1 didn't tune class weights or peak-picking thresholds for this head; treat the cb output as exploratory.
- No genre rebalancing. Folk / classical / EDM are underrepresented vs pop; performance there is more variable.
- Long songs (> 15 min) are truncated. v1 has no chunked-overlap inference. If you need this, please file a GitHub issue.
- Label noise. Because labels are filtered prior-tracker output, the model inherits any systematic biases that survived the filter.
How to use with beat_this
beat_this (CPJKU 2024) is a strong
front-end choice, especially for percussive genres. Pipeline:
from beat_this.inference import File2Beats
from livechord_beat_refiner import refine
# Front-end (GPU-friendly, run once per song)
predictor = File2Beats(checkpoint_path="final0", device="cuda", float16=True)
init_beats, init_downbeats = predictor("song.flac")
# Refine
out = refine(
audio_path="song.flac",
beats=init_beats,
downbeats=init_downbeats,
)
final_beats, final_downbeats = out["refined_beats"], out["refined_downbeats"]
Citation
@misc{livechord-beat-refiner,
title = {livechord-beat-refiner: a bidirectional Transformer for
beat / downbeat / chord-boundary refinement},
author = {LiveChord Project},
year = {2026},
url = {https://huggingface.co/livechord-music/livechord-beat-refiner},
note = {Refines beat\_this / madmom / librosa output using full
audio context. Trained on 13,017 songs.},
}
License
Apache License 2.0 β code AND weights. The training data is not redistributed; only the trained model artifact is released.
The LiveChord product (full FastAPI server, frontend, and AI pipeline) is released separately under AGPL v3 at github.com/JJ110112/LiveChord. This package is the standalone inference release.
Related
- livechord-bar-arbitrator β
companion phase-correction post-processor that runs after this model to
fix bar / beats-per-bar / doubletime confusion using
chords[]as an additional signal. - CPJKU/beat_this β recommended upstream beat tracker.
- livechord.org β the live application this model powers.
Sources
1 source
Sources
1 sourceVerified Aug 22
Model artifacts
1 artifact
Model artifacts
1 artifactSource excerpts
2 excerpts
Source excerpts
2 excerpts--- license: apache-2.0 library_name: pytorch tags: - music - music-information-retrieval - beat-tracking - downbeat-tracking - chord-recognition - audio - transformer pipeline_tag: audio-classification model-index: - name: livechord-beat-refiner results: - task: type: beat-tracking name: Beat tracking refinement metrics: - type: f1 value: 0.920 name: Beat F1 (gold-quality holdout, Β±93ms) - type: f1 value: 0.936 name: Downbeat F1 (gold-quality holdout, Β±93ms) - type: f1 value: 0.881 name: Beat F1 (full holdout, Β±93ms) - type: f1 value: 0.914 name: Downbeat F1 (full holdout, Β±93ms) --- # livechord-beat-refiner > Bidirectional Transformer that refines a prior beat tracker's output > (beat_this, madmom, or librosa) using full-context audio features. > Drops in as a post-processing pass to fix phase drift and bar misalignment > without re-running the expensive front-end model. ## πΉ Try it live This model powers the beat / bar grid behind the chord ribbon, 88-key waterfall, and AI accompaniment at **[livechord.org](https://livechord.org?utm_source=huggingface&utm_medium=model_card&utm_campaign=beat_refiner)** β upload an MP3 and play along on a virtual piano with chord cards that follow the music. ## Quickstart ```bash pip install livechord-beat-refiner ``` ```python from livechord_beat_refiner import refine # 1. Run any beat tracker (beat_this, madmom, librosa, ...) β beats / downbeats lists # 2. Pass them to refine() together with the audio file: out = refine( audio_path="song.flac", beats=[0.0, 0.52, 1.05, 1.57, ...], # seconds downbeats=[0.0, 2.10, 4.21, ...], # seconds ) print(out["refined_beats"]) # list[float] β refined beat times print(out["refined_downbeats"]) # list[float] print(out["applied"]) # bool β False if model couldn't run; input echoed back ``` The checkpoint is downloaded from this Hub repo on first call (cached under `~/.cache/huggingface/hub`). To use a local file, pass `checkpoint_path="path/to/model.safetensors"`. ## What the model does ``` audio (22050 Hz, mono) β βΌ [ CQT 84 + chroma 12 + onset + RMS ] β 98 audio channels [ initial beat grid ] β 1 channel (from prior tracker) [ initial downbeat grid ] β 1 channel β concat β (T, 100) βΌ [ Linear(100β256) + sinusoidal pos enc ] β βΌ [ TransformerEncoder Γ 6 (d=256, h=4, ffn=512, GELU, pre-LN) ] β βΌ ββββββββββββββ ββββββββββββββββ€ beat head...
Source context: 5 downloads Β· 0 likes Β· Pipeline audio-classification Β· Library pytorch Β· Repo livechord-music/livechord-beat-refiner
