WaveformGen
Instant-render waveforms from pre-computed peaks.
A Node CLI that decodes audio files at build time and writes normalized waveform data as JSON. Players render instantly with zero client-side decode, BPM detection, markers, batch processing, and support for MP3, WAV, FLAC, OGG.
$ npm i @arraypress/waveform-gen A build-time tool — no runtime, no browser API, pure JSON output.
The problem
Waveforms take time to render.
Every time a player encounters new audio, it must decode the file in the browser, analyze it, and extract peaks — all before the waveform appears.
Without WaveformGen
⏱ Seconds of latency per track
With WaveformGen
⚡ Waveform paints immediately
Try it
Generate peaks in your browser.
Drop in an audio file and watch the exact peaks JSON appear — decoded with the Web Audio API and the same windowed extraction the CLI uses. Nothing is uploaded. The waveform-gen CLI does this offline at build time (batch, BPM, no decode in the visitor's browser) — this is just the same algorithm, live.
Capabilities
Everything you need for pre-computed waveforms.
Batch processing, format support, tempo detection, and flexible output — all from one CLI.
Pre-computed peaks
Scan every frame offline and store normalized amplitudes as JSON — players render instantly, no client decode.
BPM detection
Automatic energy-based tempo extraction (60–200 BPM). Returns an integer when stable, null otherwise.
Batch & recursive
Process entire directories at once. Supports MP3, WAV, FLAC, OGG with a single command.
Flexible samples
Choose resolution per file: 200 peaks for coarse grids, 1800+ for fine detail. Higher = larger JSON.
Markers (sidecar)
Auto-detect .markers.txt files next to each audio — timestamps and labels land straight in the JSON.
Library + CLI
Use the command line for builds, or call generatePeaks() directly from a Node script.
Usage
Run from the command line or Node.
Point the CLI at audio files (glob or directory), and it writes normalized peaks to JSON in seconds. Optionally detect BPM and merge markers from sidecar files.
# One-off run: batch-generate one JSON per file
waveform-gen ./audio/*.mp3 --output ./waveforms/
# Scan a directory recursively
waveform-gen ./audio/ --recursive --output ./waveforms/
# With BPM detection
waveform-gen ./audio/ --recursive --output ./waveforms/ --bpm
# Lower resolution (coarser peaks, smaller JSON)
waveform-gen song.mp3 --samples 400 --output ./waveforms/ {
"peaks": [0.2, 0.37, 0.41, 0.55, 1.0, 0.82, 0.71, 0.44, 0.28],
"bpm": 120,
"markers": [
{ "time": 0, "label": "Intro" },
{ "time": 30, "label": "Verse 1" },
{ "time": 60, "label": "Chorus" }
]
} Node API
Call generatePeaks() from a build script.
For custom pipelines: import the library, pass file paths and options, get back normalized peaks and (optionally) detected BPM. Build a manifest, wire it to your bundler, or pipe into a database.
import { generatePeaks } from '@arraypress/waveform-gen';
const { peaks, bpm } = await generatePeaks('./song.mp3', {
samples: 1800, // peaks array length
precision: 2, // decimal places
detectBPM: true, // extract tempo
});
// peaks: number[] (normalized 0..1, max is 1.0)
// bpm: number | null (integer when found, null if not) Getting started
Add to your build in three steps.
Install as a dev dependency, add a script, and wire it to your build pipeline. WaveformGen pre-computes everything — the player just fetches and renders.
// Install as a dev dependency
npm install -D @arraypress/waveform-gen
// Add a build script to package.json
{
"scripts": {
"gen": "waveform-gen ./public/audio/ --recursive --output ./public/waveforms/ --samples 1800 --bpm",
"prebuild": "npm run gen"
}
}
// Run once or wire it to your build pipeline
npm run gen