Files
admin 9bf56a806b Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 01:10:00 +01:00

9.2 KiB

@suaveplan/audio-codecs - Universal audio codec registry: decode/encode plugin loader with format detection, progressive streaming decode, native WAV/AIFF/CAF codecs, and lazy-loaded WASM codecs for MP3/FLAC/Ogg/Opus/AAC/WebM/QOA. Universal with runtime-gated node:fs access.

Universal audio codec registry: decode/encode plugin loader with magic-byte format detection, progressive streaming decode, native WAV/AIFF/CAF codecs, and lazy-loaded WASM codecs for MP3/FLAC/Ogg/Opus/AAC/WebM/QOA. Universal — no browser-only or Node-only APIs at module scope; node:fs/promises is reached only via runtime-gated dynamic import().

Documentation tree

  • aac — Lazy AAC codec — decode-only wrapper over @audio/decode-aac WASM module loaded on first use.
  • aiff — Native pure-JS AIFF (Audio Interchange File Format) decoder, decode-only.
  • caf — Native pure-JS CAF (Apple Core Audio Format) decoder, decode-only.
  • flac — Lazy FLAC codec — thin wrapper over @audio/decode-flac WASM module loaded on first use.
  • mp3 — Lazy MP3 codec — thin wrapper that defers decode/encode to the @audio/decode-mp3 WASM module loaded via dynamic `impo…
  • ogg-vorbis — Lazy Ogg Vorbis codec — decode-only wrapper over @audio/decode-ogg-vorbis WASM module loaded on first use.
  • opus — Lazy Opus codec — wrapper over @audio/decode-opus WASM module loaded on first use.
  • qoa — Lazy QOA (Quite OK Audio) codec — wrapper over @audio/decode-qoa WASM module loaded on first use.
  • wasm-base — Shared factory for the seven lazy WASM-backed codec wrappers.
  • wav — Native pure-JS WAV codec implementing the full AudioCodec contract — decode, encode, and both streaming factories — w…
  • webm — Lazy WebM-audio codec — decode-only wrapper over @audio/decode-webm WASM module loaded on first use.
  • decode — Universal decode entry point — the single function callers use to turn any Source into a decoded AudioDocument.
    • decode-source — Universal decode entry point — the single function callers use to turn any Source into a decoded AudioDocument.
  • detect — Format detection and source-resolution helpers — the runtime-gated entry point that turns any Source (string path, UR…
    • detect-format — Format detection and source-resolution helpers — the runtime-gated entry point that turns any Source (string path, UR…
  • encode — Universal encode entry point — encode an AudioDocument to bytes and write them to any Destination (file path, Writa…
    • encode-to — Universal encode entry point — encode an AudioDocument to bytes and write them to any Destination (file path, Writa…
  • error-codes — Stable error-code registry for @suaveplan/audio-codecs. Every fault raised by the package is an AudioCodecsError ca…
    • error-codes — Stable error-code registry for @suaveplan/audio-codecs. Every fault raised by the package is an AudioCodecsError ca…
  • registry — In-memory plugin registry that owns audio-codec lookup and dispatch for the whole package.
    • registry — In-memory plugin registry that owns audio-codec lookup and dispatch for the whole package.
  • stream-decoder — TransformStream<Uint8Array, AudioPage> factory — composes a chunked byte stream into an AudioPage stream by driving…
  • stream-encoder — TransformStream<readonly Float32Array[], Uint8Array> factory — composes a PCM-block stream into encoded bytes by driv…

Install

bun add @suaveplan/audio-codecs @suaveplan/audio-core

WASM codecs are optionalDependencies — install only the ones you need:

bun add @audio/decode-mp3 @audio/decode-flac @audio/decode-opus

Quick start

import { decodeSource, encodeTo } from "@suaveplan/audio-codecs";

// Decode any source
const doc = await decodeSource(wavBytes);

// Encode any document to any registered format
await encodeTo(doc, "/tmp/out.wav", "wav", { bitDepth: 16, format: "pcm" });

Modules

Subpath Purpose
./registry/registry CodecRegistry — plugin lookup + dispatch + OTel instrumentation
./decode/decode-source decodeSource, progressiveDecode — universal decode entry
./encode/encode-to encodeTo — universal encode entry, writes to path/stream/callback
./detect/detect-format detectSource, resolveSource — runtime-gated source resolution
./stream/stream-decoder createDecodeTransform — TransformStream<Uint8Array, AudioPage>
./stream/stream-encoder createEncodeTransform — TransformStream<Float32Array[], Uint8Array>
./codecs/wav Native WAV codec — decode + encode + streaming
./codecs/aiff Native AIFF/AIFC decoder (decode-only)
./codecs/caf Native CAF (Core Audio Format) decoder (decode-only)
./codecs/mp3, flac, ogg-vorbis, opus, aac, webm, qoa Lazy WASM codec wrappers — optionalDependency loaded on first use
./codecs/wasm-base createWasmCodec factory shared by every WASM wrapper
./error-codes AudioCodecsError, AUDIO_CODECS_CODES registry (7 stable codes)

Codecs at a glance

Codec Native Decode Encode Streaming Magic
WAV ✅ ✅ ✅ ✅ RIFF … WAVE
AIFF/AIFC ✅ ✅ ❌ ❌ FORM … AIFF/AIFC
CAF ✅ ✅ ❌ ❌ caff
MP3 WASM ✅ ✅ ❌ ID3v2 / MPEG sync
FLAC WASM ✅ ✅ ❌ fLaC
Ogg Vorbis WASM ✅ ❌ ❌ OggS
Opus WASM ✅ ✅ ❌ OggS
AAC WASM ✅ ❌ ❌ ADTS sync
WebM (audio) WASM ✅ ❌ ❌ EBML header
QOA WASM ✅ ✅ ❌ qoaf

Source variants accepted

decodeSource, progressiveDecode, and detectSource all accept any of:

  • string — bare path (server: fs.readFile; browser: fetch), file:// URI (server only), or http(s): / data: / blob: string (any runtime: fetch).
  • URL instance — resolved via fetch.
  • ArrayBuffer / Uint8Array — consumed directly.
  • ReadableStream<Uint8Array> — drained on demand.

Destination variants accepted

encodeTo accepts any of:

  • string file path — written via runtime-gated node:fs/promises.writeFile.
  • WritableStream<Uint8Array> — one chunk write then close.
  • (chunk: Uint8Array) => void callback — single invocation with the full encoded payload.

Error model

Every fault is an AudioCodecsError carrying one of seven stable codes:

  • AUDIO_CODECS.UNKNOWN_FORMAT — detection found no codec.
  • AUDIO_CODECS.DECODE_FAILED — codec rejected input.
  • AUDIO_CODECS.ENCODE_FAILED — codec rejected document.
  • AUDIO_CODECS.STREAM_ERROR — abort or stream-only failure.
  • AUDIO_CODECS.NOT_SUPPORTED — operation unavailable for codec (e.g. encode for AIFF) or optionalDependency not installed.
  • AUDIO_CODECS.INVALID_SOURCE — unrecognised source / destination or Zod boundary validation failure.
  • AUDIO_CODECS.BUDGET_EXCEEDED — projected memory > caller's budget.

Original errors are preserved on error.cause; additional triage data lives on error.context.

Verification

bunx turbo lint typecheck test --filter=@suaveplan/audio-codecs
bunx turbo test:coverage --filter=@suaveplan/audio-codecs

Spec & change history

  • Design change: enterprise-audio-codecs/
  • Canonical spec (after archive): audio-codecs/spec.md