Package Exports
- realtime-bpm-analyzer
- realtime-bpm-analyzer/dist/index.esm.js
- realtime-bpm-analyzer/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (realtime-bpm-analyzer) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Realtime BPM Analyzer
Welcome to Realtime BPM Analyzer, a powerful and easy-to-use TypeScript/JavaScript library for detecting the beats-per-minute (BPM) of an audio or video source in real-time.
Getting started
To install this module to your project, just launch the command below:
npm install realtime-bpm-analyzerImportant - You need to expose the file located at dist/realtime-bpm-processor.js (already bundled) to your public root diretory. Typically, this file must be available at http://yourdomain/realtime-bpm-processor.js. Here some examples on how to integrate this into your project.
NextJS
// For NextJS check your next.config.js and add this:
// You also need to install copy-webpack-plugin, `npm install copy-webpack-plugin@6.4.1 -D`
// Note that the latest version (11.0.0) didn't worked properly with NextJS 12
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
webpack: config => {
config.plugins.push(
new CopyPlugin({
patterns: [
{
from: './node_modules/realtime-bpm-analyzer/dist/realtime-bpm-processor.js',
to: path.resolve(__dirname, 'public'),
},
],
},
));
return config;
},
};Esbuild
// In order to use the copy plugin of esbuild you will need to use a custom build process.
// This example is based on esbuild(^0.17.7) and esbuild-plugin-copy(^2.0.2).
import * as esbuild from 'esbuild';
import {copy} from 'esbuild-plugin-copy';
const outdir = 'build';
const esbuildConfig: BuildOptions = {
plugins: [
copy({
resolveFrom: 'cwd',
assets: {
from: ['./node_modules/realtime-bpm-analyzer/dist/realtime-bpm-processor.js*'],
to: [`./${outdir}/`],
},
}),
],
};To learn more about how to use the library, you can check out the documentation.
Features
- Dependency-free library that utilizes the Web Audio API to analyze audio or video sources and provide accurate BPM detection.
- Can be used to analyze audio or video nodes, streams as well as files.
- Allows you to compute the BPM while the audio or video is playing.
- Lightweight and easy to use, making it a great option for web-based music production and DJing applications.
Usages
If you encounter issues along the way, remember we have a discord server and a chat !
Realtime/Onfly strategy
Mesure or detect the BPM from a player (Typically if you don't own the audio file) ? The library provide an AudioWorkletProcessor that will compute BPM while the music is played.
This example shows how to deal with a simple audio node.
- An AudioNode to analyze. So something like this:
<audio src="./new_order-blue_monday.mp3" id="track"></audio>- Create the AudioWorkletProcessor with
createRealTimeBpmProcessor, create and pipe the filters to the AudioWorkletNode (realtimeAnalyzerNode).
import { createRealTimeBpmProcessor, getBiquadFilters } from 'realtime-bpm-analyzer';
const realtimeAnalyzerNode = await createRealTimeBpmProcessor(audioContext);
// Set the source with the HTML Audio Node
const track = document.getElementById('track');
const source = audioContext.createMediaElementSource(track);
// The library provides built in biquad filters, so no need to configure them
const {lowpass, highpass} = getBiquadFilters(audioContext);
// Connect nodes together
source.connect(lowpass).connect(highpass).connect(realtimeAnalyzerNode);
source.connect(audioContext.destination);
realtimeAnalyzerNode.port.onmessage = (event) => {
if (event.data.message === 'BPM') {
console.log('BPM', event.data.result);
}
if (event.data.message === 'BPM_STABLE') {
console.log('BPM_STABLE', event.data.result);
}
};Continuous Analysis strategy
Analyze the BPM from a stream or a source where you can't determine the start/end of a music.
- Streams can be played with AudioNode, so the approch is quite similar to the Realtime/Onfly strategy.
<audio src="https://ssl1.viastreaming.net:7005/;listen.mp3" id="track"></audio>NB: Thank you IbizaSonica for the stream.
- As for the Realtime/Onfly strategy, except that we need to turn on the
continuousAnalysisflag to periodically RESET collected data.
import { createRealTimeBpmProcessor, getBiquadFilters } from 'realtime-bpm-analyzer';
const realtimeAnalyzerNode = await createRealTimeBpmProcessor(audioContext);
// Set the source with the HTML Audio Node
const track = document.getElementById('track');
const source = audioContext.createMediaElementSource(track);
// The library provides built in biquad filters, so no need to configure them
const {lowpass, highpass} = getBiquadFilters(audioContext);
// Connect nodes together
source.connect(lowpass).connect(highpass).connect(realtimeAnalyzerNode);
source.connect(audioContext.destination);
// Set continuousAnalysis to true
realtimeAnalyzerNode.port.postMessage({
message: 'ASYNC_CONFIGURATION',
parameters: {
continuousAnalysis: true,
stabilizationTime: 20_000, // Default value is 20_000ms after what the library will automatically delete all collected data and restart analysing BPM
}
})
realtimeAnalyzerNode.port.onmessage = (event) => {
if (event.data.message === 'BPM') {
console.log('BPM', event.data.result);
}
if (event.data.message === 'BPM_STABLE') {
console.log('BPM_STABLE', event.data.result);
}
};Local/Offline strategy
Analyze the BPM from files located in your desktop, tablet or mobile !
- Import the library
import * as realtimeBpm from 'realtime-bpm-analyzer';- Use an
input[type=file]to get the files you want.
<input type="file" accept="wav,mp3" onChange={event => this.onFileChange(event)}/>- You can listen the
changeevent like so, and analyze the BPM of the selected files. You don't need to be connected to Internet for this to work.
function onFileChange(event) {
// Get the first file from the list
const file = event.target.files[0];
const reader = new FileReader();
reader.addEventListener('load', () => {
const audioContext = new window.AudioContext();
// The file is uploaded, now we decode it
audioContext.decodeAudioData(reader.result, audioBuffer => {
// The result is passed to the analyzer
realtimeBpm.analyzeFullBuffer(audioBuffer).then(topCandidates => {
// Do something with the BPM
console.log('topCandidates', topCandidates);
});
});
});
reader.readAsArrayBuffer(file);
};Roadmap
- Add confidence level of Tempo
- Combine Amplitude Thresholding strategy with others to improve BPM accuracy
- Improve the continous analysis in order to ignore drops and cuts
- Monitore memory usage
Let us know what is your most wanted feature by opening an issue.
Development
The test suite is built on top of karma and is very practical to test new features. Before running tests switch the singleRun property of karma.config.js to leave the browser open after the tests.
npm install
npm run prepare
npm testTests & Coverage
To launch the test suite, just launch the command below:
open http://localhost:9876
npm testNote that tests requires real human gesture to be successfully run!
Credits
This library was inspired by the Tornqvist project, which was also based on Joe Sullivan's algorithm. Thank you to both of them.