New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

loudness-worklet

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

loudness-worklet

A lightweight and efficient AudioWorklet for real-time loudness measurement in the browser, compliant with the ITU-R BS.1770-5 standard.

latest
Source
npmnpm
Version
1.6.9
Version published
Maintainers
1
Created
Source

Loudness Worklet

npm version license demo

A loudness meter for the Web Audio API, based on the ITU-R BS.1770-5 standard and implemented as an AudioWorkletProcessor.

screenshot

Features

  • Standard Compliant: Strictly follows ITU-R BS.1770-5 for accurate loudness measurement.
  • Comprehensive Metrics: Calculates Momentary, Short-term, and Integrated Loudness, plus Loudness Range (LRA) and True-Peak levels.
  • Versatile Input: Seamlessly supports both live audio streams ("Microphone/WebRTC") and offline file analysis.
  • Zero Dependencies: Lightweight, pure AudioWorklet implementation requiring no external libraries.

Installation

NPM

Install via npm:

npm install loudness-worklet

Use helper functions to create and load the worklet:

import { createLoudnessWorklet } from "loudness-worklet";

const worklet = await createLoudnessWorklet(audioContext);

or

import { LoudnessWorkletNode } from "loudness-worklet";

await LoudnessWorkletNode.loadModule(audioContext);
const worklet = new LoudnessWorkletNode(audioContext);

CDN

Import directly in your browser using jsDelivr or unpkg:

import { createLoudnessWorklet, LoudnessWorkletNode } from "https://cdn.jsdelivr.net/npm/loudness-worklet/+esm";

Download

For strict Content Security Policy (CSP) environments restricting blob: or eval() via script-src and worker-src, or for offline integration, download the pre-built loudness.worklet.js payload.

  • Download the pre-built file from GitHub Releases: loudness.worklet.js.
  • Place loudness.worklet.js in your project directory (e.g., /public/).
await audioContext.audioWorklet.addModule("loudness.worklet.js");
const worklet = new AudioWorkletNode(audioContext, "loudness-processor");

Quick Start

Example

This example shows the easiest way to get started with the loudness-worklet by measuring the loudness of a screen share stream with audio (e.g., a YouTube tab).

<!DOCTYPE html>
<html>
  <body>
    <button>Share Screen</button>
    <pre></pre>
    <script type="module">
      import { createLoudnessWorklet } from "https://cdn.jsdelivr.net/npm/loudness-worklet/+esm";

      const button = document.querySelector("button");
      const pre = document.querySelector("pre");

      button.onclick = async () => {
        // Get the display media stream with audio
        const mediaStream = await navigator.mediaDevices.getDisplayMedia({ audio: true });
        const context = new AudioContext();

        // Create the loudness worklet node automatically
        const worklet = await createLoudnessWorklet(context, {
          processorOptions: {
            interval: 0.02, // every 0.02s a message will be sent
            capacity: 600 // 1 minute of history can be stored
          }
        });

        // Create the audio node from the stream
        const source = new MediaStreamAudioSourceNode(context, { mediaStream });

        worklet.port.onmessage = (event) => {
          pre.textContent = JSON.stringify(event.data, null, 2);
        };

        // Connect the nodes
        source.connect(worklet);
      };
    </script>
  </body>
</html>

File-based measurement

You can measure the loudness of audio files using OfflineAudioContext.

import { LoudnessWorkletNode } from "loudness-worklet";

const input = document.querySelector("input");

input.addEventListener("change", async (event) => {
  const file = event.target.files[0];
  const arrayBuffer = await file.arrayBuffer();
  const audioBuffer = await new AudioContext().decodeAudioData(arrayBuffer);
  const { numberOfChannels, length, sampleRate } = audioBuffer;
  const context = new OfflineAudioContext(numberOfChannels, length, sampleRate);

  await LoudnessWorkletNode.loadModule(context);

  const source = new AudioBufferSourceNode(context, { buffer: audioBuffer });
  const worklet = new LoudnessWorkletNode(context);

  worklet.port.onmessage = (event) => console.log("Loudness Data:", event.data);

  source.connect(worklet).connect(context.destination);
  source.start();

  await context.startRendering();
});

Live-based measurement

Supports all kinds of audio input.

import { createLoudnessWorklet } from "loudness-worklet";

const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
const context = new AudioContext({ sampleRate: 48000 });
const source = context.createMediaStreamSource(mediaStream);
const worklet = await createLoudnessWorklet(context, {
  processorOptions: { interval: 1, capacity: 600 }
});

worklet.port.onmessage = (event) => console.log("Loudness Data:", event.data);
source.connect(worklet);

// worklet.connect(context.destination);
// Optionally connect to destination for monitoring (echo)

Concepts

Contexts

Provide the execution environment for audio processing.

AudioContext

AudioContext is used for real-time audio processing, such as live audio input from a microphone or media stream.

OfflineAudioContext

OfflineAudioContext is used for processing audio data offline, allowing for rendering and analysis without requiring real-time playback.

Nodes

Nodes are the building blocks of an audio graph, representing audio sources, processing modules, and destinations. The following nodes are commonly used as a source input:

AudioBufferSourceNode

AudioBufferSourceNode is used to play audio data stored in an AudioBuffer, typically for pre-recorded audio files.

const arrayBuffer = await file.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
const bufferSource = new AudioBufferSourceNode(audioContext, { buffer: audioBuffer });

MediaStreamAudioSourceNode

MediaStreamAudioSourceNode is used to play audio from a MediaStream, such as a live microphone input or a video element.

const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaStreamSource = new MediaStreamAudioSourceNode(audioContext, { mediaStream });

MediaElementAudioSourceNode

MediaElementAudioSourceNode is used to play audio from an HTML <audio> or <video> element.

const mediaElement = document.querySelector("audio");
const elementSource = new MediaElementAudioSourceNode(audioContext, { mediaElement });

API

Options

The AudioWorkletNode constructor accepts the following options:

Params

OptionTypeRequiredDefaultDescription
processorOptions.intervalnumberNo0.02Message interval in seconds.
processorOptions.capacitynumberNo0Maximum seconds of history to keep. If set to 0, the processor will not limit the history size.

Example

Most of the time, you only need to set processorOptions or leave it empty.

const { numberOfChannels, length, sampleRate } = audioBuffer;
const worklet = new AudioWorkletNode(context, "loudness-processor", {
  processorOptions: {
    capacity: length / sampleRate,
    interval: 0.02
  }
});

Message Format

Measurement results are sent back to the main thread via port.onmessage as a LoudnessSnapshot object:

type LoudnessMeasurements = {
  momentaryLoudness: number;
  shortTermLoudness: number;
  integratedLoudness: number;
  maximumMomentaryLoudness: number;
  maximumShortTermLoudness: number;
  maximumTruePeakLevel: number;
  loudnessRange: number;
};

type LoudnessSnapshot = {
  currentFrame: number;
  currentTime: number;
  currentMeasurements: LoudnessMeasurements[];
};

Details

Units

MetricUnit
momentaryLoudnessLUFS/LKFS
shortTermLoudnessLUFS/LKFS
integratedLoudnessLUFS/LKFS
maximumMomentaryLoudnessLUFS/LKFS
maximumShortTermLoudnessLUFS/LKFS
maximumTruePeakLeveldBTP
loudnessRangeLU

Supported Channels

Supported channel counts: 1, 2, 5, 6, 8, 10, 12, 24

[!NOTE] Channel counts not listed above are weighted at 1.0.

Coefficients

The following coefficients are used for the K-weighting filter:

highshelfhighpass
a1-1.69065929318241-1.99004745483398
a20.732480774215850.99007225036621
b01.535124859586971.0
b1-2.69169618940638-2.0
b21.198392810852851.0

The following FIR filter coefficients are used for true-peak measurement:

Phase 0Phase 1Phase 2Phase 3
0.0017089843750-0.0291748046875-0.0189208984375-0.0083007812500
0.01098632812500.02929687500000.03308105468750.0148925781250
-0.0196533203125-0.0517578125000-0.0582275390625-0.0266113281250
0.03320312500000.08911132812500.10156250000000.0476074218750
-0.0594482421875-0.1665039062500-0.2003173828125-0.1022949218750
0.13732910156250.46508789062500.77978515625000.9721679687500
0.97216796875000.77978515625000.46508789062500.1373291015625
-0.1022949218750-0.2003173828125-0.1665039062500-0.0594482421875
0.04760742187500.10156250000000.08911132812500.0332031250000
-0.0266113281250-0.0582275390625-0.0517578125000-0.0196533203125
0.01489257812500.03308105468750.02929687500000.0109863281250
-0.0083007812500-0.0189208984375-0.02917480468750.0017089843750

Validation

ITU-R BS.2217

Code correctness is verified against the official ITU-R BS.2217 compliance test suite, ensuring strict adherence to the ITU-R BS.1770 specification.

filemeasurementchannels
1770Comp_2_RelGateTest-10.0 LKFS2:white_check_mark:
1770Comp_2_AbsGateTest-69.5 LKFS2:white_check_mark:
1770Comp_2_24LKFS_25Hz_2ch-24.0 LKFS2:white_check_mark:
1770Comp_2_24LKFS_100Hz_2ch-24.0 LKFS2:white_check_mark:
1770Comp_2_24LKFS_500Hz_2ch-24.0 LKFS2:white_check_mark:
1770Comp_2_24LKFS_1000Hz_2ch-24.0 LKFS2:white_check_mark:
1770Comp_2_24LKFS_2000Hz_2ch-24.0 LKFS2:white_check_mark:
1770Comp_2_24LKFS_10000Hz_2ch-24.0 LKFS2:white_check_mark:
1770Comp_2_23LKFS_25Hz_2ch-23.0 LKFS2:white_check_mark:
1770Comp_2_23LKFS_100Hz_2ch-23.0 LKFS2:white_check_mark:
1770Comp_2_23LKFS_500Hz_2ch-23.0 LKFS2:white_check_mark:
1770Comp_2_23LKFS_1000Hz_2ch-23.0 LKFS2:white_check_mark:
1770Comp_2_23LKFS_2000Hz_2ch-23.0 LKFS2:white_check_mark:
1770Comp_2_23LKFS_10000Hz_2ch-23.0 LKFS2:white_check_mark:
1770Comp_2_18LKFS_FrequencySweep-18.0 LKFS1:white_check_mark:
1770Comp_2_24LKFS_SummingTest-24.0 LKFS6:white_check_mark:
1770Comp_2_23LKFS_SummingTest-23.0 LKFS6:white_check_mark:
1770Comp_2_24LKFS_ChannelCheckLeft-24.0 LKFS6:white_check_mark:
1770Comp_2_24LKFS_ChannelCheckRight-24.0 LKFS6:white_check_mark:
1770Comp_2_24LKFS_ChannelCheckCentre-24.0 LKFS6:white_check_mark:
1770Comp_2_24LKFS_ChannelCheckLFE-inf LKFS6:white_check_mark:
1770Comp_2_24LKFS_ChannelCheckLs-24.0 LKFS6:white_check_mark:
1770Comp_2_24LKFS_ChannelCheckRs-24.0 LKFS6:white_check_mark:
1770Comp_2_23LKFS_ChannelCheckLeft-23.0 LKFS6:white_check_mark:
1770Comp_2_23LKFS_ChannelCheckRight-23.0 LKFS6:white_check_mark:
1770Comp_2_23LFKS_ChannelCheckCentre-23.0 LKFS6:white_check_mark:
1770Comp_2_23LKFS_ChannelCheckLFE-inf LKFS6:white_check_mark:
1770Comp_2_23LKFS_ChannelCheckLs-23.0 LKFS6:white_check_mark:
1770Comp_2_23LKFS_ChannelCheckRs-23.0 LKFS6:white_check_mark:
1770-2 Conf 6ch VinCntr-24LKFS-24.0 LKFS6:white_check_mark:
1770-2 Conf 6ch VinL+R-24LKFS-24.0 LKFS6:white_check_mark:
1770-2 Conf 6ch VinL-R-C-24LKFS-24.0 LKFS6:white_check_mark:
1770-2 Conf Stereo VinL+R-24LKFS-24.0 LKFS2:white_check_mark:
1770-2 Conf Mono Voice+Music-24LKFS-24.0 LKFS1:white_check_mark:
1770-2 Conf 6ch VinCntr-23LKFS-23.0 LKFS6:white_check_mark:
1770-2 Conf 6ch VinL+R-23LKFS-23.0 LKFS6:white_check_mark:
1770-2 Conf 6ch VinL-R-C-23LKFS-23.0 LKFS6:white_check_mark:
1770-2 Conf Stereo VinL+R-23LKFS-23.0 LKFS2:white_check_mark:
1770-2 Conf Mono Voice+Music-23LKFS-23.0 LKFS1:white_check_mark:
1770Conf-8channels_24LKFS-24.0 LKFS8:white_check_mark:
1770Conf-8channels_23LKFS-23.0 LKFS8:white_check_mark:
1770Conf-10channels_24LKFS-24.0 LKFS10:white_check_mark:
1770Conf-10channels_23LKFS-23.0 LKFS10:white_check_mark:
1770Conf-12channels_24LKFS-24.0 LKFS12:white_check_mark:
1770Conf-12channels_23LKFS-23.0 LKFS12:white_check_mark:
1770Conf-24channels_24LKFS-24.0 LKFS24:white_check_mark:
1770Conf-24channels_23LKFS-23.0 LKFS24:white_check_mark:

[!TIP] If decodeAudioData fails, it's often due to the browser's specific support for the audio file's format (codec), container, or channel layout, rather than a general API incompatibility. Try a different browser or convert the audio file to a more widely supported format. For example, Chrome has limited support for certain codecs in audio files, while Safari offers broader support. (1770Conf-24channels_24LKFS)

EBU TECH 3341 Minimum requirements test signals

Validated against EBU TECH 3341 minimum requirements for loudness metering, including gating behavior, time scales, and true-peak accuracy.

fileexpected response and accepted tolerances
seq-3341-1-16bitM, S, I = -23.0 ±0.1 LUFS:white_check_mark:
seq-3341-2-16bitM, S, I = -33.0 ±0.1 LUFS:white_check_mark:
seq-3341-3-16bit-v02I = -23.0 ±0.1 LUFS:white_check_mark:
seq-3341-4-16bit-v02I = -23.0 ±0.1 LUFS:white_check_mark:
seq-3341-5-16bit-v02I = -23.0 ±0.1 LUFS:white_check_mark:
seq-3341-6-5channels-16bitI = -23.0 ±0.1 LUFS:white_check_mark:
seq-3341-6-6channels-WAVEEX-16bitI = -23.0 ±0.1 LUFS:white_check_mark:
seq-3341-7_seq-3342-5-24bitI = -23.0 ±0.1 LUFS:white_check_mark:
seq-3341-2011-8_seq-3342-6-24bit-v02I = -23.0 ±0.1 LUFS:white_check_mark:
seq-3341-9-24bitS = -23.0 ±0.1 LUFS, constant after 3 s:white_check_mark:
seq-3341-10-*-24bitMax S = -23.0 ±0.1 LUFS, for each segment:white_check_mark:
seq-3341-11-24bitMax S = -38.0, -37.0, …, -19.0 ±0.1 LUFS, successive values:white_check_mark:
seq-3341-12-24bitM = -23.0 ±0.1 LUFS, constant after 1 s:white_check_mark:
seq-3341-13-*-24bitMax M = -23.0 ±0.1 LUFS, for each segment:white_check_mark:
seq-3341-14-24bitMax M = -38.0, …, -19.0 ±0.1 LUFS, successive values:white_check_mark:
seq-3341-15-24bitMax true-peak = -6.0 +0.2/-0.4 dBTP:white_check_mark:
seq-3341-16-24bitMax true-peak = -6.0 +0.2/-0.4 dBTP:white_check_mark:
seq-3341-17-24bitMax true-peak = -6.0 +0.2/-0.4 dBTP:white_check_mark:
seq-3341-18-24bitMax true-peak = -6.0 +0.2/-0.4 dBTP:white_check_mark:
seq-3341-19-24bitMax true-peak = +3.0 +0.2/-0.4 dBTP:white_check_mark:
seq-3341-20-24bitMax true-peak = 0.0 +0.2/-0.4 dBTP:white_check_mark:
seq-3341-21-24bitMax true-peak = 0.0 +0.2/-0.4 dBTP:white_check_mark:
seq-3341-22-24bitMax true-peak = 0.0 +0.2/-0.4 dBTP:white_check_mark:
seq-3341-23-24bitMax true-peak = 0.0 +0.2/-0.4 dBTP:white_check_mark:

EBU TECH 3342 Minimum requirements test signals

EBU TECH 3342 focuses on the measurement of loudness range.

fileexpected response and accepted tolerances
seq-3342-1-16bitLRA = 10 ±1 LU:white_check_mark:
seq-3342-2-16bitLRA = 5 ±1 LU:white_check_mark:
seq-3342-3-16bitLRA = 20 ±1 LU:white_check_mark:
seq-3342-4-16bitLRA = 15 ±1 LU:white_check_mark:
seq-3341-7_seq-3342-5-24bitLRA = 5 ±1 LU:white_check_mark:
seq-3341-2011-8_seq-3342-6-24bit-v02LRA = 15 ±1 LU:white_check_mark:

Acknowledgments

This project is a learning experiment aimed at exploring audio signal processing and ITU-R BS.1770 loudness measurement standards. I am not an expert in audio engineering or signal processing, and this project was developed as a way to better understand the concepts of audio loudness and implementation techniques. Thanks to the ITU-R BS.1770 standards for providing the theoretical basis for loudness measurement.

License

This project is licensed under the MIT License.

References

Keywords

web-audio

FAQs

Package last updated on 06 Apr 2026

Did you know?

Socket

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.

Install

Related posts