Files
2026-05-27 23:29:53 +01:00

154 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks: enterprise-audio-codecs
**Change ID**: enterprise-audio-codecs
**Package**: `@suaveplan/audio-codecs`
**Target path**: `packages/media/audio/audio-codecs/`
**Prerequisite packages on Verdaccio**: `@suaveplan/audio-core`, `@suaveplan/audio-metadata`, `@suaveplan/streams`, `@suaveplan/error`, `@suaveplan/types`
---
## 0. Pre-flight (non-negotiable)
- [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each)
- [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
- [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest.
## 1. Scaffold
- [ ] Create directory `packages/media/audio/audio-codecs/` with `src/`, `tests/`, `src/__benchmarks__/`, and all feature subdirectories per the layout in `proposal.md`.
- [ ] Write `package.json` at version `0.1.0` with `"type": "module"`, `"sideEffects": false`, full `exports` map, deps: `@suaveplan/audio-core workspace:^`, `@suaveplan/audio-metadata workspace:^`, `@suaveplan/streams workspace:^`, `@suaveplan/error workspace:^`, `@suaveplan/types workspace:^`, `zod catalog:forms`, `@opentelemetry/api catalog:observability`.
- [ ] Declare optional peer deps / `optionalDependencies` for WASM codec packages (`@audio/decode-mp3`, `@audio/decode-flac`, etc.).
- [ ] Write `tsconfig.json` extending `@suaveplan/typescript-config/library.json`.
- [ ] Write `vitest.config.ts` using `createTestConfig()` from `@suaveplan/testing/config`.
- [ ] Add `lint`, `typecheck`, `test`, `test:coverage`, `build`, `docs:check` scripts.
---
## 2. Types + errors
- [ ] Write `src/registry/registry.types.ts` — `AudioCodec`, `DecodeResult`, `StreamingDecoder`, `StreamingEncoder`, `CodecRegistryOptions`.
- [ ] Write `src/registry/registry.md`.
- [ ] Write `src/decode/decode-source.types.ts` — `Source`, `DecodeSourceOpts`, `DecodeOpts`.
- [ ] Write `src/decode/decode-source.md`.
- [ ] Write `src/encode/encode-to.types.ts` — `Destination`, `EncodeOpts`.
- [ ] Write `src/encode/encode-to.md`.
- [ ] Write `src/stream/stream-decoder.types.ts` — streaming decoder config types.
- [ ] Write `src/stream/stream-decoder.md`.
- [ ] Write `src/stream/stream-encoder.types.ts` — streaming encoder config types.
- [ ] Write `src/stream/stream-encoder.md`.
- [ ] Write `src/error-codes.ts` — `AudioCodecErrorCode`, `AUDIO_CODEC_ERROR_METADATA`, `registerAudioCodecErrorCodes()`.
- [ ] Write Zod schemas for every public options object (`DecodeOptsSchema`, `EncodeOptsSchema`, `DecodeSourceOptsSchema`, `AudioCodecSchema`, `StreamingDecoderSchema`, `StreamingEncoderSchema`).
---
## 3. Format detection
- [ ] Implement `detectSource(source)` — read first `HEADER_SIZE` (256KB) bytes, resolve string sources to `fetch()` or `fs/promises.readFile()` based on runtime, return format + bytes/reader.
- [ ] Integrate `@suaveplan/audio-metadata` magic-byte detection.
- [ ] Write `src/detect/detect-format.test.ts`.
- [ ] Write `src/detect/detect-format.md`.
---
## 4. CodecRegistry
- [ ] Implement `CodecRegistry.register()` / `unregister()` / `detect()`.
- [ ] Implement `CodecRegistry.decode(source, opts)` — dispatch to codec, return `AudioDocument`.
- [ ] Implement `CodecRegistry.encode(doc, format, opts)` — dispatch to codec, return `Uint8Array`.
- [ ] Implement `CodecRegistry.decodeStream()` — `ReadableStream<Uint8Array>` → `ReadableStream<AudioPage>` via `StreamingDecoder`.
- [ ] Implement `CodecRegistry.encodeStream()` — `AudioDocument` → `ReadableStream<Uint8Array>` via `StreamingEncoder`.
- [ ] Wire OTel span on `codec.decode` / `codec.encode` + counters + histograms.
- [ ] Write `src/registry/registry.test.ts`.
- [ ] Write `src/registry/registry.md`.
---
## 5. Built-in codecs (native)
- [ ] Implement `WavCodec` — native WAV decode/encode with streaming support, no external deps.
- [ ] Write `src/codecs/wav.test.ts` — round-trip, header validation, streaming chunks.
- [ ] Write `src/codecs/wav.md`.
- [ ] Implement `AiffCodec` — native AIFF decode (no encode), no external deps.
- [ ] Implement `CafCodec` — native CAF decode (no encode), no external deps.
---
## 6. Built-in codecs (WASM wrappers)
- [ ] Implement `Mp3Codec` — dynamic `import('@audio/decode-mp3')` wrapper, decode + encode + streaming.
- [ ] Write `src/codecs/mp3.test.ts` using deterministic fixtures (no network mocks).
- [ ] Write `src/codecs/mp3.md`.
- [ ] Implement `FlacCodec` — dynamic `import('@audio/decode-flac')` wrapper, decode + encode + streaming.
- [ ] Write `src/codecs/flac.test.ts`.
- [ ] Write `src/codecs/flac.md`.
- [ ] Implement `OggVorbisCodec`, `OpusCodec`, `AacCodec`, `WebMCodec`, `QoaCodec` — decode wrappers with dynamic imports, optional streaming where supported.
---
## 7. Universal decode entry point
- [ ] Implement `decodeSource(source, opts)` — resolve source, detect format, dispatch to `CodecRegistry.decode`, support `notify` / `ondata` callbacks, page pre-allocation, memory budget.
- [ ] Implement source resolution rules: `http/https/data/blob` → `fetch()`; `file:` → `fs/promises.readFile()`; other string → runtime-determined.
- [ ] Write `src/decode/decode-source.test.ts`.
- [ ] Write `src/decode/decode-source.md`.
---
## 8. Universal encode entry point
- [ ] Implement `encodeTo(doc, destination, format, opts)` — encode then write to file path, `WritableStream`, or callback.
- [ ] Write `src/encode/encode-to.test.ts`.
- [ ] Write `src/encode/encode-to.md`.
---
## 9. Progressive streaming decode
- [ ] Implement `progressiveDecode()` — fill `AudioDocument.pages` as chunks arrive via `StreamingDecoder` or fallback full-decode.
- [ ] Implement `pageAccumulator()` — push decoded PCM into pages, call `notify` on first page, call `ondata` per block.
- [ ] Return usable `AudioDocument` immediately (before decode completes) with edits extending as pages arrive.
- [ ] Write `src/stream/stream-decoder.test.ts`.
- [ ] Write `src/stream/stream-decoder.md`.
---
## 10. Stream encoder
- [ ] Implement `createEncodeTransform()` — `TransformStream<Float32Array[], Uint8Array>` using `StreamingEncoder`.
- [ ] Write `src/stream/stream-encoder.test.ts`.
- [ ] Write `src/stream/stream-encoder.md`.
---
## 11. Memory budget
- [ ] Implement memory budget enforcement in `decodeSource` and `progressiveDecode` — project bytes from `sampleRate × channels × duration × 4` and throw `AudioCodecError(AUDIO_CODECS.BUDGET_EXCEEDED)` if over `budget`.
- [ ] Write budget tests in `decode-source.test.ts`.
---
## 12. Benchmarks
- [ ] Write `src/__benchmarks__/decode.bench.ts` — decode 5-minute stereo WAV (native) and MP3 (WASM).
- [ ] Write `src/__benchmarks__/encode.bench.ts` — encode 5-minute stereo WAV and FLAC.
- [ ] Write `src/__benchmarks__/stream-decode.bench.ts` — progressive stream decode 5-minute MP3.
---
## 13. Integration + property tests
- [ ] Write `tests/integration.test.ts` — full round-trip: `decodeSource` → run edits → `encodeTo` → file written.
- [ ] Write `tests/property.test.ts` (fast-check) — decode-then-encode round-trip for WAV/FLAC yields identical PCM; `detect` returns correct format for known magic bytes; streaming decode total samples equals non-streaming decode total samples.
---
## 14. Docs + verify + publish
- [ ] All co-located `.md` files (≥200 words each).
- [ ] Write `README.md` at package root.
- [ ] `bunx turbo lint typecheck test --filter=@suaveplan/audio-codecs` — green.
- [ ] `bunx turbo test:coverage --filter=@suaveplan/audio-codecs` — 100%.
- [ ] `bun scripts/publish.ts --package @suaveplan/audio-codecs`.
- [ ] Fold `specs/audio-codecs/spec.md` into `openspec/specs/audio-codecs/spec.md`.
- [ ] Archive change folder to `openspec/archive/2026-05-14-enterprise-audio-codecs/`.