Skip to content

Getting Started

WaveformGen is a Node CLI and ESM library that decodes audio files and writes normalized waveform peak data as JSON. Pre-generating peaks at build time means the player renders instantly — no client-side audio decode, no fetch-and-analyze on page load.

The JSON it produces drops straight into the player’s waveform option (or data-waveform / data-wb-waveform attributes), so the bars look identical to a live in-browser decode.

CLI

waveform-gen ./audio/*.mp3 --output ./waveforms/ — batch-generate one JSON per file.

Library

generatePeaks(filePath, options) — the single public export, returns a Promise.

Run it on demand with npx, install globally for a reusable waveform-gen command, or add it as a dev dependency to call the library from a build script.

Terminal window
# One-off, no install
npx @arraypress/waveform-gen ./audio/*.mp3 --output ./waveforms/
# Global CLI
npm install -g @arraypress/waveform-gen
# As a build dependency (library + CLI)
npm install -D @arraypress/waveform-gen

Requirements: Node.js 18+, ESM only ("type": "module"). The only runtime dependency is audio-decode.

Terminal window
waveform-gen <files|directories...> [options]

Positional arguments are audio files and/or directories. Anything starting with - must be a known flag — an unknown one stops the run with exit code 2. Value flags take --flag value or --flag=value. Use -- to end flag parsing, so later arguments are paths even if they start with - (a lone - is always a path).

Terminal window
# Generate one JSON per file into ./waveforms/
waveform-gen ./audio/*.mp3 --output ./waveforms/
# Scan a directory tree
waveform-gen ./audio/ --recursive --output ./waveforms/
# Lower resolution + tempo detection
waveform-gen song.mp3 --samples 400 --bpm
# Print the peaks array to stdout for piping
waveform-gen song.mp3 --format inline
Flag Default Type Description
--samples <n> 1800 integer Number of peaks (array length) generated per file. Higher = finer detail, larger JSON. Must be an integer of 1 or more, or the run exits 1.
--precision <n> 2 integer Decimal places each peak is rounded to. Must be an integer (negative = unrounded), or the run exits 1.
--output <dir> same dir as each input path Output directory. A file found inside a directory input keeps its path relative to that directory (out/a/intro.json), with folders created as needed; file arguments write straight into <dir> (2.0.0+).
--format <type> json json | inline json writes a <name>.json file; inline prints peaks to stdout — a bare array for a single file argument, or one object keyed by path for several files or any directory (2.0.0+). Any other value exits 1.
--bpm false flag Run BPM detection and write an integer "bpm" into the JSON (only when a tempo is found).
--recursive false flag Scan passed directories recursively. Default scans the top level only.
--quiet false flag Suppress progress and the summary line. Errors always go to stderr (2.0.0+).
--help, -h — flag Print help and exit(0). Also shown when run with zero arguments.
-- — — End of flags: every later argument is an input path.

Boolean flags (--bpm, --recursive, --quiet) take no value — --bpm=true is a usage error (exit 2).

Both the CLI (--samples) and the library generatePeaks() default to 1800 peaks — the SoundCloud-scale resolution that keeps wide / high-DPI waveforms crisp.

Situation Behavior
--help / -h / no args Prints help, exit(0).
Every file generated exit(0).
Unknown flag, flag missing its value, value on a boolean flag [WaveformGen] … (see --help), exit(2) before anything runs.
Invalid flag value (--samples 0, --samples abc, --format xml) Error message, exit(1) before anything runs.
No audio files resolved [WaveformGen] No audio files found., exit(1).
Fatal / uncaught error [WaveformGen] Fatal error: …, exit(1).
A single file fails to decode, or its output path is already taken Reported on stderr (❌ name: message), run continues, then exit(1) (2.0.0+).
Input path doesn’t exist or can’t be read [WaveformGen] Skipping … on stderr, run continues, then exit(1) (2.0.0+).
File argument with a non-audio extension Ignored silently.

Per-file failures never abort a batch — a run over 100 files where 3 fail still writes the other 97 — but the run then exits 1, so a prebuild step fails instead of shipping with missing JSON (2.0.0+; earlier versions exited 0). Errors go to stderr even with --quiet. Without --quiet, a closing Done: N generated, M failed line summarises the run. Every log and error is prefixed [WaveformGen].