
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
waveform-panel
Advanced tools
A web component that can display simple waveforms or compositions and crops of multiple waveforms. It uses SVG to render the waveforms, with CSS variables for customising styling. It is interactive when hovering by default with simple events for scrubbing.
npm i waveform-panel
or yarn
yarn add waveform-panel
and import somewhere in your bundle:
import 'waveform-panel';
or you can drop the script into any HTML page:
<script src="https://cdn.jsdelivr.net/npm/waveform-panel/dist/index.umd.js"></script>
You will first need a generated waveform to get started. You can read more about this at https://waveform.prototyping.bbc.co.uk/
waveform-data.js is part of a BBC R&D Browser-based audio waveform visualisation software family:
- audiowaveform: C++ program that generates waveform data files from MP3 or WAV format audio.
- audio_waveform-ruby: A Ruby gem that can read and write waveform data files.
- waveform-data.js: JavaScript library that provides access to precomputed waveform data files, or can generate waveform data using the Web Audio API.
- peaks.js: JavaScript UI component for interacting with waveforms.
Extract from bbc/waveform-data.js.
Once you have hosted your .dat files from this process, and you have the JS bundle for waveform-panel, you can
use the web component in your application. (Examples provided by The British Library)
src attribute<waveform-panel src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat"></waveform-panel>
You can also provide a duration, although this will be extracted from the loaded waveform.
<waveform-panel
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat"
duration="3723.4"
></waveform-panel>
sequences attributeThe sequence attribute allows you to add a Media Frag selector to a waveform.
<waveform-panel
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat"
sequence="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat#t=100,1300"
></waveform-panel>
When you provide a src you can also provide an identifier. This could be the Audio resource, or just an internal
identifier that you can use. By default, the URL of the waveform will be the identifier. This identifier should then
be used in the sequence="" attribute. This identifier will also available in events.
<waveform-panel
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat my-identifier"
sequence="my-identifier#t=100,1300"
></waveform-panel>
Identifiers can also be URLs, like a IIIF Canvas - allowing for some basic interoperability with Media Frags used in IIIF Presentation 3 Manifests for AV content.
<waveform-panel
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat https://api.bl.uk/metadata/iiif/ark:/81055/vdc_100052359795.0x000004"
sequence="https://api.bl.uk/metadata/iiif/ark:/81055/vdc_100052359795.0x000004#t=100,1300"
></waveform-panel>
For the rest of the demos - shorter identifiers will be used for clarity.
You can chain multiple sequences together by using | between them.
<waveform-panel
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat first"
sequence="first#t=100,200 | first#t=200,500"
></waveform-panel>
In addition to src="" you can also provide multiple waveforms using the srcset="" property.
Each source is structured as follows:
[waveform-url] [identifier], [waveform-url] [identifier]
With spaces to add an identifier after each, and a comma , (or pipe |) separating sources.
<waveform-panel
srcset="
https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat first,
https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x00001a.dat second,
"
></waveform-panel>
Note: Line breaks are valid, and added for readability.
You can also optionally have a single [identifier] made up of multiple waveforms. This will internally
split the sequence into two distinct sections - but might be closer to the original data modelled.
If you are using targets, the structure changes to be:
[waveform-url] [identifier]#t=[start],[end] | [waveform-url] [identifier]#t=[start],[end]
With spaces to add an identifier with target and only pipes | to separate sources.
<waveform-panel
srcset="
https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat first#t=0,50 |
https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x00001a.dat first#t=50,100 |
"
></waveform-panel>
Note: you have to use a pipe | to split sequences if you include #t= selectors.
You can also create a more complex sequence using srcset="" and sequences="" together.
<waveform-panel
srcset="
https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat first,
https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x00001a.dat second,
"
sequence="
first#t=0,100 |
first#t=100,200 |
second#t=0,400
"
></waveform-panel>
This will use the sequence to build a single waveform from multiple sources. Currently, the amplitude is calculated independently for each input - so a quiet source and relatively loud source together will not clearly reflect this difference.
You can pass in a current-time="" initially to set the time of the component. You can also update this programmatically from javascript as an audio source is playing, for example.
<waveform-panel
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat"
current-time="200"
></waveform-panel>
This will be reflected in the UI.
There is currently only one event that you can listen to: click-waveform. This is dispatched when the waveform is clicked at a specific time.
<waveform-panel
id="waveform"
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat"
current-time="200"
></waveform-panel>
<script>
const $waveform = document.getElementById('waveform');
$waveform.addEventListener('click-waveform', e => {
e.preventDefault(); // Prevent the waveform automatically seeking.
connsole.log(e.detail.time); // Time relative to whole waveform
connsole.log(e.detail.sequenceTime); // Time relative to current sequence
});
</script>
It will return some information in the event.detail property you can use to drive other UIs or <audio/> elements. Annotated example below:
const detail = {
// Details of the sequence clicked.
currentSequence: {
// The start and end times of that sequence.
startTime: 0,
endTime: 3723.4,
id: 'https://api.bl.uk/metadata/iiif/ark:/81055/vdc_100052359795.0x000004',
// Internal identifier.
source: 'https__//api__bl__uk/metadata/iiif/ark__/81055/vdc_100052359795__0x000004__t=0__3723__4__',
// The waveform data
waveform: {
atWidth: 884.5, // The width that the waveform is displayed at
data: {} // Omitted, but the full raw waveform (resampled down to the width)
startPixel: 0, // where across the waveform this starts.
}
},
// Time relative to the whole waveform.
time: 2635.215828151498,
// Percent through the whole waveform
percent: 0.35387224420576596,
// Time relative to the individual sequence.
sequenceTime: 2635.215828151498,
// Where on the waveform clicked.
target: {x: 626, y: 95},
};
<audio /> componentNote: this is currently still under development.
<waveform-panel
id="waveform"
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat my-audio"
current-time="200"
></waveform-panel>
<audio id="audio" src="https://example.org/audio.m4a"></audio>
<script>
const $waveform = document.getElementById('waveform');
const $audio = document.getElementById('audio');
// Syncing the current time
audio.addEventListener('timeupdate', () => {
// note: at the moment you need to calculate the current time from your audio source.
$waveform.currentTime = audio.currentTime;
// Possible future API:
// $waveform.updateSequencedTime({
// 'my-audio': audio.currentTime,
// })
});
// Example click interaction (play on click - otherwise seek)
$waveform.addEventListener('click-waveform', (e) => {
if ($audio.paused) {
e.preventDefault(); // Prevent seeking.
$audio.play();
} else {
$audio.currentTime = e.detail.sequenceTime;
}
})
// Adding buffering visualisation (WIP)
audio.addEventListener('progress', () => {
// Updates the buffered audio.
// You need to specify the identifier of the waveform and bind to a TimeRange
$waveform.reseek({
'my-audio': audio.buffered
});
});
</script>
You can control the following styles using CSS variables, and target like a normal HTML element
waveform-panel {
--waveform-background: #000;
--waveform-base: #8a9aa1;
--waveform-hover: #14a4c3;
--waveform-buffered: #fff;
--waveform-progress: rgba(255, 255, 255, .4);
}
Example light theme:
waveform-panel.light-waveform {
--waveform-background: #eee;
--waveform-base: #8a9aa1;
--waveform-hover: #14a4c3;
--waveform-buffered: #bbd5de;
--waveform-progress: rgba(0, 0, 0, .2);
}
Usage with class:
<waveform-panel
class="light-waveform"
src="https://iiif-waveforms.s3.eu-west-2.amazonaws.com/vdc_100052359795.0x000018.dat"
></waveform-panel>
FAQs
Unknown package
The npm package waveform-panel receives a total of 1,178 weekly downloads. As such, waveform-panel popularity was classified as popular.
We found that waveform-panel demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.