
Security News
Deno Goes the Way of the Dinosaur
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.
Zero-dependency blind audio watermarking for WAV files, with a measured support envelope. Runs on Node.js 22+ and Bun.
Audio watermarking for Node.js, Bun, and the browser.
Try the demo · API reference · Measured results · Contributing
WaveRune embeds a 32-bit identifier in WAV audio and reads it back using a key. Detection does not need the original recording. Use it to experiment with audio identification, add watermarks to a WAV workflow, or study a small, inspectable signal-processing implementation.
The package has zero runtime dependencies, includes TypeScript declarations, and provides both a library and a command-line tool. The browser demo processes files locally; nothing is uploaded.
Recovery depends on the audio. In the recorded-audio benchmark, the current detector recovered 24 of 27 clean, full-length trials across nine files. Short clips and edited audio are less reliable. See limits and measured results before relying on it in a workflow.
npm install waverune
For the command-line tool:
npm install -g waverune
# Or run without a global installation:
npx waverune --help
Bun users can use bun add waverune and bunx waverune.
Install the standalone CLI without installing a JavaScript runtime.
macOS and Linux
# macOS and Linux: installs ~/.local/bin/waverune
curl -fsSL https://raw.githubusercontent.com/hamedniroomand/waverune/main/install.sh | bash
Windows (x64)
# Installs %LOCALAPPDATA%\Programs\waverune\waverune.exe and adds it to your user PATH
powershell -ExecutionPolicy Bypass -c "irm https://raw.githubusercontent.com/hamedniroomand/waverune/main/install.ps1 | iex"
Both scripts download the archive for your platform from the latest
GitHub Release, check
its SHA-256 against the release's SHA256SUMS.txt, and install the executable.
The Bun runtime is included in the executable.
On macOS and Linux, the installer prints a command to add the install directory
to PATH if needed. Add that line to your shell profile and open a new terminal.
On Windows, the installer updates your user PATH; open a new terminal to use it.
Then check the installation:
waverune --version
waverune --help
Set these environment variables before running the installer:
| Variable | Purpose | Default |
|---|---|---|
WAVERUNE_VERSION | Release tag to download, such as v0.3.1 | Latest release |
WAVERUNE_BIN_DIR | Directory for the executable | ~/.local/bin on macOS/Linux; %LOCALAPPDATA%\Programs\waverune on Windows |
For example, on macOS or Linux, pass the settings to bash, which runs the installer:
curl -fsSL https://raw.githubusercontent.com/hamedniroomand/waverune/main/install.sh | WAVERUNE_VERSION=v0.3.1 WAVERUNE_BIN_DIR="$HOME/.local/bin" bash
In PowerShell, set the variables in the current session:
$env:WAVERUNE_VERSION = "v0.3.1"
$env:WAVERUNE_BIN_DIR = "$env:LOCALAPPDATA\Programs\waverune"
irm https://raw.githubusercontent.com/hamedniroomand/waverune/main/install.ps1 | iex
The installers need a release of v0.3.1 or later. Earlier releases ship the
executables uncompressed, without the archives that the installers download.
Run the installer again to update or replace an existing installation. If you
previously set WAVERUNE_VERSION, set it to latest to get the newest release.
| Environment | Support |
|---|---|
| Node.js | 22 or later; CI tests Node.js 22 and 24 |
| Bun | 1.4 or later |
| Browser demo | Local WAV processing, up to 120 seconds per file |
| Standalone executables | macOS ARM64/x64, Linux ARM64/x64, Windows x64 |
The package is ESM only. Standalone executables are published with each
GitHub Release as
waverune-<os>-<arch>.tar.gz (macOS, Linux) and waverune-windows-x64.zip,
each holding one executable that embeds its runtime; the install scripts above
fetch and verify them for you.
Embed an identifier, save the file, and verify the saved audio:
import { detect, embed, readWavFile, writeWavFile } from 'waverune';
const key = 'my-watermark-key';
const payload = 42n;
const original = await readWavFile('input.wav');
const marked = embed(original, { key, payload });
await writeWavFile('marked.wav', marked);
const saved = await readWavFile('marked.wav');
const result = detect(saved, { key });
if (result.detected && result.payload === payload) {
console.log('Verified watermark:', result.payload.toString());
} else {
console.log('The saved file did not recover the requested identifier.');
}
The default payload is an unsigned 32-bit integer (0n to 4294967295n).
Keep the key to detect the watermark later. embed returns a new audio buffer
without changing the input.
Use decodeWav and encodeWav for byte arrays, or PerceptualWatermarker
for custom settings. See the API reference for options, errors,
and detection diagnostics.
waverune embed input.wav -o marked.wav --id 42 --key my-watermark-key
waverune detect marked.wav --key my-watermark-key
waverune metrics input.wav marked.wav
embed reads the saved file back and checks that the recovered identifier
matches the one requested. If verification fails, it reports the failure and
keeps the output file for inspection. Add --json for machine-readable output.
| Exit code | Meaning |
|---|---|
0 | Command succeeded; detection accepted a watermark, or embedding verified |
1 | Invalid input or another error |
2 | Detection did not accept a watermark |
3 | Embedding completed, but the saved file failed verification |
See the CLI reference for all commands and flags.
Open the demo, choose a WAV file, and enter a key. Embed a new identifier to compare and download the output, or detect a watermark in an existing file. A blank identifier generates a random one.
The demo accepts files up to 120 seconds. Processing can pause the page, especially for longer or stereo recordings. The library and CLI do not impose this duration cap.
WaveRune uses classical signal processing: a keyed signal is spread across frequency slots under a simplified masking model, then recovered through spectral correlation. It needs no model downloads. Read how it works for the algorithm and acceptance rule.
The following are recorded benchmark results for the v0.3 detector, not recovery guarantees for other recordings:
| Test set | Result |
|---|---|
| Clean synthetic audio, 20 key/payload pairs on each of two fixtures | 40/40 exact recoveries |
| The same synthetic trials after a 16-bit WAV round trip | 40/40 exact recoveries |
| Synthetic sample-rate conversions through macOS Core Audio | 50/50 exact recoveries |
| Clean recorded audio, three pairs across nine files | 24/27 exact recoveries |
| Prefix removal on eligible recorded files | 119/119 exact recoveries |
| Recorded-audio excerpts of 5 seconds or less | 115/329 exact recoveries |
| Synthetic rejection tests with unmarked audio, wrong keys, and silence | 0 acceptances in 585 trials |
The reliability report includes the inputs, commands, per-file results, and comparisons with the previous detector.
correlationScore is not a probability. Acceptance
requires the sync pattern and checksum to match exactly.Use Bun for installation, testing, and builds:
git clone https://github.com/hamedniroomand/waverune.git
cd waverune
bun install
bun run demo
The local demo runs at http://localhost:3000. To build its self-contained
HTML file, run bun run demo:build; the output is dist-demo/index.html.
bun test
bun run typecheck
bun run lint
bun run format:check
bun run build
bun run test:node
bun run test:interop
bun run check:pack
bun run build:binaries cross-compiles the standalone executables into
release/. The release workflow runs it on every version tag, compresses the
executables, writes SHA256SUMS.txt, and uploads them to the GitHub Release
that the install scripts read.
The test suite takes several minutes. Resampling tests require sox or
macOS afconvert. If neither is available, explicitly skip that check with
WAVERUNE_ALLOW_SKIP_RESAMPLE=1 bun test.
The contribution guide covers the project layout, validation, and useful details to include in bug reports. Benchmark commands and methodology are in the reliability report.
Bug reports, documentation improvements, and tests with reproducible audio cases are welcome. Check existing issues or read CONTRIBUTING.md to get started.
If WaveRune is useful to you, a GitHub star helps other developers find it.
WaveRune draws inspiration from Perth, particularly the idea of spreading watermark energy under a masking threshold. It is an independent DSP implementation and is not compatible with Perth's watermark format.
MIT, by Hamed Niroomand.
FAQs
Zero-dependency blind audio watermarking for WAV files, with a measured support envelope. Runs on Node.js 22+ and Bun.
We found that waverune demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.

Security News
On Front Lines’ Early Adopters: CISO podcast, Andrew Becherer shares lessons from Datadog, weighs the long-term costs of AI-built tools, and explains how founders can actually gain a CISO’s trust.