8.0 KiB
8.0 KiB
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 statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin 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.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory
packages/media/audio/audio-codecs/withsrc/,tests/,src/__benchmarks__/, and all feature subdirectories per the layout inproposal.md. - Write
package.jsonat version0.1.0with"type": "module","sideEffects": false, fullexportsmap, 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 /
optionalDependenciesfor WASM codec packages (@audio/decode-mp3,@audio/decode-flac, etc.). - Write
tsconfig.jsonextending@suaveplan/typescript-config/library.json. - Write
vitest.config.tsusingcreateTestConfig()from@suaveplan/testing/config. - Add
lint,typecheck,test,test:coverage,build,docs:checkscripts.
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 firstHEADER_SIZE(256KB) bytes, resolve string sources tofetch()orfs/promises.readFile()based on runtime, return format + bytes/reader. - Integrate
@suaveplan/audio-metadatamagic-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, returnAudioDocument. - Implement
CodecRegistry.encode(doc, format, opts)— dispatch to codec, returnUint8Array. - Implement
CodecRegistry.decodeStream()—ReadableStream<Uint8Array>→ReadableStream<AudioPage>viaStreamingDecoder. - Implement
CodecRegistry.encodeStream()—AudioDocument→ReadableStream<Uint8Array>viaStreamingEncoder. - 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— dynamicimport('@audio/decode-mp3')wrapper, decode + encode + streaming. - Write
src/codecs/mp3.test.tsusing deterministic fixtures (no network mocks). - Write
src/codecs/mp3.md. - Implement
FlacCodec— dynamicimport('@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 toCodecRegistry.decode, supportnotify/ondatacallbacks, 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()— fillAudioDocument.pagesas chunks arrive viaStreamingDecoderor fallback full-decode. - Implement
pageAccumulator()— push decoded PCM into pages, callnotifyon first page, callondataper block. - Return usable
AudioDocumentimmediately (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>usingStreamingEncoder. - Write
src/stream/stream-encoder.test.ts. - Write
src/stream/stream-encoder.md.
11. Memory budget
- Implement memory budget enforcement in
decodeSourceandprogressiveDecode— project bytes fromsampleRate × channels × duration × 4and throwAudioCodecError(AUDIO_CODECS.BUDGET_EXCEEDED)if overbudget. - 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;detectreturns correct format for known magic bytes; streaming decode total samples equals non-streaming decode total samples.
14. Docs + verify + publish
- All co-located
.mdfiles (≥200 words each). - Write
README.mdat 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.mdintoopenspec/specs/audio-codecs/spec.md. - Archive change folder to
openspec/archive/2026-05-14-enterprise-audio-codecs/.