Files
skills/docs/media/audio/audio-codecs/README.md
2026-05-29 08:20:56 +01:00

145 lines
9.2 KiB
Markdown

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