I'm looking to detect the tempo of an audio file in python 3.6, but I don't really understand the doc about aubio. Would someone please indicate how to extract the tempo with aubio or another library?
Asked
Active
Viewed 4,653 times
3
-
have you seen this https://aubio.org/doc/0.4.0/tempo_8h.html? – Liam Mar 21 '17 at 18:01
-
There already is an example of this, in Python, here, called demo_bpm_extract.py: https://github.com/aubio/aubio/tree/master/python/demos – Random Davis Mar 21 '17 at 18:02
2 Answers
9
Updated
This command will give you the tempo estimate of the entire file (available in 0.4.5
):
aubio tempo foo.wav
There is a simple demo in aubio's python/demos
: demo_bpm_extract.py.
The most important part is the following two lines, which compute the periods between each consecutive beats (np.diff
), convert these periods in bpm (60./
), and takes the median (np.median
) as the most likely bpm candidate for this series of beats:
#!/usr/bin/env python
import numpy as np
bpms = 60./np.diff(beats)
median_bpm = np.median(bpms)
Note how the median is better suited than the mean here, since it will always give an estimate which exists in the original population bpms
.

piem
- 390
- 2
- 11
-
5it feels somewhat ironic to get downvoted as i'm the upstream author. a comment on this would have been appreciated. – piem Mar 23 '17 at 08:10
-
thanks for the answer, I upvoted you. But anyway, aubio isn't very good at detecting tempo/bpm it seems. I just tried it with a few songs and the values are way off, for example it gives `Smokey Robinson - Cruisin'` a bpm score of 168.3 which can't be true. Any song with live music or ambient noise is also very wrong. Any suggestions for alternative lib? – supersan May 04 '18 at 18:22
-
@supersan did you find a good alternative lib? I've experienced the same thing where the results aren't ideal. – Patrick Mar 02 '20 at 11:52
-
1@Patrick sorry I never did though i barely remember any details because it was a long time back. If I were to do it now I'd probably try doing it using machine learning. The first step would to be find an accurate bpm dataset and songs using which you can train the model. Maybe it will be a nice weekend project for me. I'll update you if I ever get the chance to work on it. – supersan Mar 02 '20 at 13:06
-
3
I found this code by Paul Brossier that could help you, here it is:
#! /usr/bin/env python
from aubio import source, tempo
from numpy import median, diff
def get_file_bpm(path, params = None):
""" Calculate the beats per minute (bpm) of a given file.
path: path to the file
param: dictionary of parameters
"""
if params is None:
params = {}
try:
win_s = params['win_s']
samplerate = params['samplerate']
hop_s = params['hop_s']
except KeyError:
"""
# super fast
samplerate, win_s, hop_s = 4000, 128, 64
# fast
samplerate, win_s, hop_s = 8000, 512, 128
"""
# default:
samplerate, win_s, hop_s = 44100, 1024, 512
s = source(path, samplerate, hop_s)
samplerate = s.samplerate
o = tempo("specdiff", win_s, hop_s, samplerate)
# List of beats, in samples
beats = []
# Total number of frames read
total_frames = 0
while True:
samples, read = s()
is_beat = o(samples)
if is_beat:
this_beat = o.get_last_s()
beats.append(this_beat)
#if o.get_confidence() > .2 and len(beats) > 2.:
# break
total_frames += read
if read < hop_s:
break
# Convert to periods and to bpm
if len(beats) > 1:
if len(beats) < 4:
print("few beats found in {:s}".format(path))
bpms = 60./diff(beats)
b = median(bpms)
else:
b = 0
print("not enough beats found in {:s}".format(path))
return b
if __name__ == '__main__':
import sys
for f in sys.argv[1:]:
bpm = get_file_bpm(f)
print("{:6s} {:s}".format("{:2f}".format(bpm), f))
this is the key part:
bpms = 60./np.diff(beats)
median_bpm = np.median(bpms)

Liam
- 6,009
- 4
- 39
- 53
-
you forgot to mention your source, and the indentation got messed up somehow. ;-) pointing to the original resource seemed more appropriate here. also, I added some insights about the conversion from beat locations to bpm. – piem Mar 22 '17 at 16:34