Gathering detailed insights and metrics for waveform-data
Gathering detailed insights and metrics for waveform-data
Gathering detailed insights and metrics for waveform-data
Gathering detailed insights and metrics for waveform-data
npm install waveform-data
90.5
Supply Chain
100
Quality
80.1
Maintenance
100
Vulnerability
81.3
License
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
1,038 Stars
349 Commits
103 Forks
47 Watching
3 Branches
92 Contributors
Updated on 14 Nov 2024
JavaScript (100%)
Cumulative downloads
Total Downloads
Last day
29.1%
2,305
Compared to previous day
Last week
3.1%
11,374
Compared to previous week
Last month
-38.6%
49,432
Compared to previous month
Last year
60.5%
754,046
Compared to previous year
29
waveform-data.js is a JavaScript library for creating zoomable representations of audio waveforms to enable visualisation of audio content.
waveform-data.js is part of a BBC R&D Browser-based audio waveform visualisation software family:
We use these projects within the BBC in applications such as the BBC World Service Radio Archive and browser-based editing and sharing tools for BBC content editors.
Use npm
to install waveform-data.js
, for both Node.js and browser-based
applications:
1npm install --save waveform-data
waveform-data.js is available as a UMD
module so it can be used from a <script>
tag, or as a RequireJS or CommonJS
module. See dist/waveform-data.js and dist/waveform-data.min.js.
Simply add waveform-data.js in a script
tag in your HTML page:
1<!DOCTYPE html> 2<html> 3 <body> 4 <script src="/path/to/waveform-data.js"></script> 5 <script> 6 var waveform = new WaveformData(...); 7 </script> 8 </body> 9</html>
An ES6 module build is provided for use with bundlers such as Webpack and Rollup. See dist/waveform-data.esm.js.
1import WaveformData from 'waveform-data';
The UMD bundle can be used with RequireJS:
1define(['WaveformData'], function(WaveformData) { 2 // ... 3});
A CommonJS build is provided for use with Node.js. See dist/waveform-data.cjs.js.
1const WaveformData = require('waveform-data');
You can create and initialise a WaveformData
object from
waveform data in either binary or JSON format, using the
Fetch API, as follows.
Use audiowaveform to generate binary format waveform data, using a command such as:
1audiowaveform -i track.mp3 -o track.dat -b 8 -z 256
Copy the waveform data file track.dat
to your web server, then use the
following code in your web application to request the waveform data:
1fetch('https://example.com/waveforms/track.dat') 2 .then(response => response.arrayBuffer()) 3 .then(buffer => WaveformData.create(buffer)) 4 .then(waveform => { 5 console.log(`Waveform has ${waveform.channels} channels`); 6 console.log(`Waveform has length ${waveform.length} points`); 7 });
Alternatively, audiowaveform can generate waveform data in JSON format:
1audiowaveform -i track.mp3 -o track.json -b 8 -z 256
Use the following code to request the waveform data:
1fetch('https://example.com/waveforms/track.json') 2 .then(response => response.json()) 3 .then(json => WaveformData.create(json)) 4 .then(waveform => { 5 console.log(`Waveform has ${waveform.channels} channels`); 6 console.log(`Waveform has length ${waveform.length} points`); 7 });
You can also create waveform data from audio in the browser, using the Web Audio API.
As input, you can either use an ArrayBuffer
containing the original encoded
audio (e.g., in MP3, Ogg Vorbis, or WAV format), or an AudioBuffer
containing
the decoded audio samples.
Note that this approach is generally less efficient than pre-processing the audio server-side, using audiowaveform.
Waveform data is created in two steps:
If you pass an ArrayBuffer
containing encoded audio, the audio is decoded
using the Web Audio API's decodeAudioData
method. This must done on the browser's UI thread, so will be a blocking operation.
The decoded audio is processed to produce the waveform data. To avoid further
blocking the browser's UI thread, by default this step is done using a
Web Worker,
if supported by the browser. You can disable the worker and run the processing
in the main thread by setting disable_worker
to true
in the options.
1const audioContext = new AudioContext(); 2 3fetch('https://example.com/audio/track.ogg') 4 .then(response => response.arrayBuffer()) 5 .then(buffer => { 6 const options = { 7 audio_context: audioContext, 8 array_buffer: buffer, 9 scale: 128 10 }; 11 12 return new Promise((resolve, reject) => { 13 WaveformData.createFromAudio(options, (err, waveform) => { 14 if (err) { 15 reject(err); 16 } 17 else { 18 resolve(waveform); 19 } 20 }); 21 }); 22 }) 23 .then(waveform => { 24 console.log(`Waveform has ${waveform.channels} channels`); 25 console.log(`Waveform has length ${waveform.length} points`); 26 });
If you have an AudioBuffer
containing decoded audio samples, e.g., from
AudioContext.decodeAudioData
then you can pass this directly to WaveformData.createFromAudio
:
1const audioContext = new AudioContext(); 2 3audioContext.decodeAudioData(arrayBuffer) 4 .then((audioBuffer) => { 5 const options = { 6 audio_context: audioContext, 7 audio_buffer: audioBuffer, 8 scale: 128 9 }; 10 11 return new Promise((resolve, reject) => { 12 WaveformData.createFromAudio(options, (err, waveform) => { 13 if (err) { 14 reject(err); 15 } 16 else { 17 resolve(waveform); 18 } 19 }); 20 }); 21 }) 22 .then(waveform => { 23 console.log(`Waveform has ${waveform.channels} channels`); 24 console.log(`Waveform has length ${waveform.length} points`); 25 });
Once you've created a WaveformData
object, you can use it to draw a waveform
image, using the
Canvas API or
a visualization library such as D3.js.
1const waveform = WaveformData.create(raw_data); 2 3const scaleY = (amplitude, height) => { 4 const range = 256; 5 const offset = 128; 6 7 return height - ((amplitude + offset) * height) / range; 8} 9 10const ctx = canvas.getContext('2d'); 11ctx.beginPath(); 12 13const channel = waveform.channel(0); 14 15// Loop forwards, drawing the upper half of the waveform 16for (let x = 0; x < waveform.length; x++) { 17 const val = channel.max_sample(x); 18 19 ctx.lineTo(x + 0.5, scaleY(val, canvas.height) + 0.5); 20} 21 22// Loop backwards, drawing the lower half of the waveform 23for (let x = waveform.length - 1; x >= 0; x--) { 24 const val = channel.min_sample(x); 25 26 ctx.lineTo(x + 0.5, scaleY(val, canvas.height) + 0.5); 27} 28 29ctx.closePath(); 30ctx.stroke(); 31ctx.fill();
See demo/d3.html.
1<div id="waveform-container"></div>
1const waveform = WaveformData.create(raw_data); 2const channel = waveform.channel(0); 3const container = d3.select('#waveform-container'); 4const x = d3.scaleLinear(); 5const y = d3.scaleLinear(); 6const offsetX = 100; 7 8const min = channel.min_array(); 9const max = channel.max_array(); 10 11x.domain([0, waveform.length]).rangeRound([0, 1000]); 12y.domain([d3.min(min), d3.max(max)]).rangeRound([offsetX, -offsetX]); 13 14const area = d3.svg.area() 15 .x((d, i) => x(i)) 16 .y0((d, i) => y(min[i])) 17 .y1((d, i) => y(d)); 18 19const graph = container.append('svg') 20 .style('width', '1000px') 21 .style('height', '200px') 22 .datum(max) 23 .append('path') 24 .attr('transform', () => `translate(0, ${offsetX})`) 25 .attr('d', area) 26 .attr('stroke', 'black'); 27
You can use waveform-data.js to consume or generate waveform data from a Node.js application, e.g., a web server.
1const WaveformData = require('waveform-data'); 2const express = require('express'); 3const fs = require('fs'); 4const app = express(); 5 6app.get('/waveforms/:id.json', (req, res) => { 7 res.set('Content-Type', 'application/json'); 8 9 fs.createReadStream(`path/to/${req.params.id}.json`) 10 .pipe(res); 11});
The following example shows a Node.js command-line application that requests waveform data from a web API and resamples it to a width of 2000 pixels.
1#!/usr/bin/env node 2 3// Save as: app/bin/cli-resampler.js 4 5const WaveformData = require('waveform-data'); 6const request = require('superagent'); 7const args = require('yargs').argv; 8 9request.get(`https://api.example.com/waveforms/${args.waveformid}.json`) 10 .then(response => { 11 const waveform = WaveformData.create(response.body); 12 const resampledWaveform = waveform.resample({ width: 2000 }); 13 const channel = resampledWaveform.channel(0); 14 15 process.stdout.write(JSON.stringify({ 16 min: channel.min_array(), 17 max: channel.max_array() 18 })); 19});
Usage: ./app/bin/cli-resampler.js --waveformid=1337
The file format used and consumed by WaveformData
is documented here as part of the audiowaveform project.
Please refer here for full API documentation.
Any browser supporting ECMAScript 5 will be enough to use the library -
think Array.forEach
:
To develop the code, install Node.js and
npm. After obtaining the waveform-data.js source code,
run npm install
to install Node.js package dependencies.
This library was written by:
Thank you to all our contributors.
This program contains code adapted from Audacity, used with permission.
See LICENSE for details.
Every contribution is welcomed, either it's code, idea or a merci!
Guidelines are provided and every commit is tested against unit tests using Karma runner and the Chai assertion library.
Copyright 2024 British Broadcasting Corporation
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 3
Details
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no SAST tool detected
Details
Reason
Found 0/30 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
Reason
security policy file not detected
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
12 existing vulnerabilities detected
Details
Score
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More