# BeatNet: joint beat, downbeat and tempo tracking in Python

> BeatNet is the implementation of an ISMIR 2021 paper, and the point of the paper is that beats, downbeats, tempo and meter are not four separate problems. The library trains one recurrent network on all of them and runs the inference through a two-stage cascade particle filter, which is what lets the same code work on a live microphone and on a file, online or offline.

**mjhydri/BeatNet** — BeatNet is state-of-the-art (Real-Time) and Offline joint music beat, downbeat, tempo, and meter tracking system using CRNN and particle filtering.  (ISMIR 2021's paper implementation).

- Repository: https://github.com/mjhydri/BeatNet
- Stars: 525 · Forks: 83
- Language: Python
- License: CC-BY-4.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/mjhydri-beatnet

## One model for four musical quantities

BeatNet is described as a state-of-the-art AI-based Python library for joint music beat, downbeat, tempo and meter tracking, and the repository description puts it more plainly: a real-time and offline joint music beat, downbeat, tempo and meter tracking system using a CRNN and particle filtering.

The repository is the implementation of the ISMIR 2021 paper, whose arXiv version is 2108.03576. The README says the repository contains the user package and the source code of the Monte Carlo particle filtering inference model of the system, and the badges show that the online beat tracking and online downbeat tracking entries are marked as the state of the art on the Ballroom and GTZAN datasets and on the rock corpus.

The design decision that defines the project is the word joint in that description. A conventional system chains separate components: a tempo estimator, a beat tracker that uses it, and a downbeat tracker on top of that, with each stage's errors feeding the next. BeatNet instead predicts all of them from one network, which is what makes a single forward pass produce beats, downbeats, a tempo estimate and a meter estimate together, and what lets the same model run causally for real time use and non-causally offline.

The licence is CC BY 4.0, which is unusual for a software package and worth noticing: it is the research paper's licence rather than the MIT or Apache that most libraries use, so the terms around redistribution and attribution apply to the code as well as the paper. The author is Mojtaba Heydari, the package is on PyPI as BeatNet, and the last push to the repository was on 2026-04-13.

## Four operating modes for the same algorithm

The four modes are the part of the API that most affects how you use the library, because they are the same system at different speeds.

Streaming mode captures streaming audio directly from the microphone. That is the live use case, and the input requirement is stated plainly: feed the system with as loud an input as possible to leverage the maximum streaming performance, given that all the models are trained on datasets containing mastered songs.

Real-time mode reads audio files and processes them in real time, yielding immediate results. The file is played back at its own speed and the beats are reported as they happen.

Online mode is similar to real-time mode and employs the same causal algorithm for track processing, but instead of reading the files in real time it reads them faster, while still producing identical outcomes to the real-time mode.

Offline mode infers beats and downbeats in an offline fashion.

So there are really two axes. Streaming versus file input, and causal versus non-causal inference. The online mode is the interesting one, because it is the same causal algorithm as real time but running as fast as the machine allows, which means you can process a ten minute track in far less than ten minutes and get the answer you would have got in real time.

The distinction that matters is that the causal modes cannot use the future of the audio, and the offline mode can. That is a real difference in output, and it is why the offline mode exists at all rather than the online mode simply being used everywhere.

## Particle filtering for causal, a dynamic Bayesian network for offline

The inference model parameter chooses between two approaches, and the README explains the reasoning.

PF stands for Particle Filtering for causal inferences, and DBN stands for Dynamic Bayesian Network for non-causal usages. In addition to the proposed online inference, the authors added madmom's DBN beat and downbeat inference model for the offline usages.

Then there is the note that matters for anybody comparing performance: the offline model still utilises BeatNet's neural network rather than that of madmom, which leads to better performance and significantly faster results.

So the DBN path is not madmom's network with BeatNet's inference. It is BeatNet's network, which produces the activations, with a dynamic Bayesian network layered on top to turn those into a beat and downbeat sequence. The reason is that the neural network is the expensive part to train and the part the paper contributed, and reusing it means the offline path does not need a second set of weights or a second training run, while the DBN handles the non-causal inference that the particle filter cannot do.

The other thing to note is that the offline path therefore depends on madmom being installed, which is why the installation notes call out both Librosa and Madmom as prerequisites. For an offline-only user that is a heavy dependency to inherit for one component, and it is worth checking what you actually need.

## Input, output and the parameters that matter

The interface is described in a way that makes the contract clear.

The system input is a raw audio waveform object or a directory. Using the audio directory as the system input makes the system automatically resample the audio file to 22050 Hz, whereas in the case of using an audio object as the input you must make sure that the audio sample rate is equal to 22050 Hz. That asymmetry is worth remembering, because passing a 44.1 kHz waveform gives a wrong answer rather than an error.

The system output is a vector including beats and downbeats columns, respectively, with the shape of a numpy array with num_beats rows and 2 columns.

The parameters are a short list. The model parameter is a scalar in the range one to three, to select which of the pre-trained CRNN models to use. The mode parameter is the string that determines the working mode, one of stream, realtime, online and offline. The inference model parameter is PF or DBN as described. The plot parameter is a list of strings, and it can include activations, beat_particles and downbeat_particles, with the advice that to speed up plotting the figures, rather than new plots per frame, the previous plots get updated, and that to secure realtime results it is recommended not to plot or to have as few plots as possible.

The thread parameter decides whether the inference runs on the main thread or another one, which matters for a streaming setup where the microphone callback should not be blocked by inference. And the device parameter selects Cuda or cpu, with cpu as the default.

The usage examples are short, and the streaming one is the whole interface in three lines:

```python
from BeatNet.BeatNet import BeatNet

estimator = BeatNet(1, mode='stream', inference_model='PF', plot=[], thread=False)

Output = estimator.process()
```

The same three lines with mode set to realtime, online or offline are the entire difference between the four ways of running the system.

## Installation, and the dependency weight it brings

There are two install routes, and the second is the one to use if you want the source rather than the published wheel.

```bash
pip install BeatNet
```

or, directly from the repository:

```bash
pip install git+https://github.com/mjhydri/BeatNet
```

Before installing, the README says to make sure that Librosa and Madmom are installed. Pyaudio is also needed, since it is the Python binding for PortAudio that handles audio streaming, and there is a note that if it is not installed you either install it through pip on Mac OS and Linux or download an appropriate wheel for Windows, with the download page linked.

The dependency list in setup.py shows how much is being pulled in: numpy at 1.21.0 or newer, cython, librosa at 0.8.0 or newer, scipy, mido, pytest, madmom at 0.16.1 or newer, torch at 1.9.0 or newer, Matplotlib, tensorboard and pyyaml. The build system in pyproject.toml requires setuptools, wheel, numpy, numba and cython.

Two details in the packaging are unusual for a modern library. The build requirements include numpy, numba and cython, which means those are compiled during the build rather than only being runtime dependencies, and the setup.py still imports distutils.cmd to define a custom make_reqs command that exports the requirements list to a requirements.txt file. That is a pattern from the era when the author started the project, and it is preserved.

The package version is 1.2.0, the layout is a src/ directory, and all pre-trained models are included in the models folder, which is what makes the pip install usable without a separate model download.

## The training pipeline, and what it lets you reproduce

New in v1.2.0, the official training pipeline is included. You can train the BeatNet CRNN from scratch on your own data, or reproduce the paper's results using the provided training scripts, dataset handlers and test suite.

That is a significant addition for a research repository, because until then the useful artefact was the inference code and the pre-trained weights, and anybody wanting to train on their own data had to reconstruct the training setup from the paper.

The dataset handlers are the part worth looking at. A joint beat and downbeat model needs training data with beat and downbeat annotations, which for the standard research datasets means annotations derived from a metrical structure rather than from clicks, and the code to load and align them is not trivial. Handlers that ship with the repository mean the alignment logic is the same one the authors used, which is what makes a reproduction attempt meaningful.

The test suite is bundled for the same reason. A result that differs from the paper by a margin is either a bug or a difference in the data pipeline, and having the evaluation code in the repository is what lets you tell the two apart.

The repository layout is small and conventional: src/ for the package, test/ for the tests, dist/ for built artefacts, a setup.py alongside a pyproject.toml, a MANIFEST.in for packaging, and a LICENSE file for the CC BY terms.

## Where BeatNet is the wrong tool

There are cases where this system is the wrong answer, and they come from what it optimises for.

The first is a simple beat tracker. If you need tap tempo or a click track, or a beat grid for a visualisation, the joint model and the particle filter are more machinery than the job needs, and a lighter library or a spectral flux tracker will do it with less setup.

The second is material that is not mastered. The README's own advice for streaming is to feed the system as loudly as possible for the maximum performance, given that all the models are trained on datasets containing mastered songs. That is an admission that the training distribution is commercial studio material, and a field recording, a rehearsal in a room, or a phone recording of a gig is a different distribution. The model will still produce beats, and they will sometimes be wrong in a way that no amount of tuning fixes, because the issue is the training data rather than the inference.

The third is the offline dependency. If you only want offline beat and downbeat tracking, the DBN path requires madmom, which is a large dependency to install for one component, and the README's claim is that this path is faster and better than madmom's own model, which is an argument for keeping BeatNet rather than an argument for dropping madmom.

The alternative approach is madmom on its own, which has a mature offline beat and downbeat tracker and a broad set of pre-trained models, and it is the sensible choice for offline-only work. The difference in approach is the joint model against a chain of separate models: BeatNet predicts all four quantities from one network and can run causally for live use, while madmom's offline path is a well-tested pipeline that gives you beats and downbeats and nothing about meter or a causal mode, and which in exchange brings a decade of accumulated models and a far larger community around it.

## Conclusion

BeatNet suits a researcher who needs downbeats and meter as well as beats, who needs the result while the audio is still playing rather than after the file has been processed, and who wants to retrain the model on their own data. It does not suit somebody who only needs a beat tracker for a click track or a visualisation, since the joint model and the particle filter are more machinery than that requires, and it does not suit field recordings, because the models were trained on mastered material. Check three things before you rely on it: that your audio is at 22050 Hz, since the directory input resamples it and the waveform input does not, that the operating mode matches what you need, since the online and realtime modes give identical results at different speeds, and whether the streaming accuracy suits your recording conditions, because the README advises feeding the microphone as loudly as possible for the best results. The last push to the repository was on 2026-04-13 and the current package version is 1.2.0.

## FAQ

### What is BeatNet?

It is a Python library for joint music beat, downbeat, tempo and meter tracking, implementing the ISMIR 2021 paper with a CRNN and an efficient two-stage cascade particle filtering algorithm. The same model serves real-time and offline use, and the package is published on PyPI as BeatNet under a CC BY 4.0 licence.

### What are BeatNet's four operating modes?

Streaming captures audio directly from the microphone, real-time reads audio files and processes them in real time yielding immediate results, online uses the same causal algorithm but reads files faster while producing identical outcomes, and offline infers beats and downbeats in a non-causal fashion.

### What do the PF and DBN inference models do?

PF is particle filtering for causal inference and is the system's own contribution, while DBN is madmom's dynamic Bayesian network for non-causal offline usage. The offline path still uses BeatNet's neural network rather than madmom's, which the README says leads to better performance and significantly faster results.

### What sample rate does BeatNet need?

22050 Hz. When the input is an audio directory the system resamples the files automatically, but when you pass a waveform object you must make sure the sample rate is already 22050 Hz, otherwise the output is wrong rather than an error.

### Can I train BeatNet myself?

Yes. Since version 1.2.0 the official training pipeline is included, so you can train the CRNN from scratch on your own data or reproduce the paper's results using the provided training scripts, dataset handlers and test suite.

## Sources

- [Issues](https://github.com/mjhydri/BeatNet/issues)
- [License: CC-BY-4.0](https://github.com/mjhydri/BeatNet/blob/main/LICENSE)
- [mjhydri/BeatNet on GitHub](https://github.com/mjhydri/BeatNet)
- [README](https://github.com/mjhydri/BeatNet/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mjhydri-beatnet
