# `encode/encode-to` Universal encode entry point — encode an `AudioDocument` to bytes and write them to any `Destination` (file path, WritableStream, or callback). _(no submodules)_ ## Purpose `encodeTo` is the top-level public-facing encode API. Callers do not need to wire codec dispatch + destination plumbing manually — they pass in a document, a format name, and a destination handle, and the function takes care of routing through `CodecRegistry.encode` and then writing the resulting bytes to the destination via the appropriate platform call. ## Features - Accepts three `Destination` variants: - `string` file path → resolved via dynamic `import('node:fs/promises')` for `writeFile`. Runtime-gated so the import never appears statically. - `WritableStream` → write via the stream's writer, closes the stream after writing. - `(chunk: Uint8Array) => void` callback → single invocation with the full payload. - Optional `opts.format: "pcm" | "float"` and `opts.bitDepth: 8 | 16 | 24 | 32` for codecs that support multiple sample formats (WAV). - Optional `opts.sampleRate` override — used when the encode pipeline needs to retarget a different rate than the document's natural rate. - Optional `opts.signal` (AbortSignal) — checked before encode dispatch. Pre-aborted signals throw `AUDIO_CODECS.STREAM_ERROR`. - Optional `opts.registry` to inject a pre-configured registry. Defaults to a fresh `CodecRegistry()` — callers that need WAV/AIFF/ CAF or WASM codecs available should pass in the registry from `decode-source.ts` or construct one with the codecs they need. - Zod-validated options — invalid `sampleRate`/`bitDepth`/`format` throws `AUDIO_CODECS.INVALID_SOURCE`. - Encoder errors are wrapped — codec-specific failures surface as `AUDIO_CODECS.ENCODE_FAILED` with the original error on `cause`. - Invalid destination (not a path/stream/callback) throws `AUDIO_CODECS.INVALID_SOURCE`. ## Usage: Basic Example ```ts import { CodecRegistry, encodeTo, WavCodec } from "@suaveplan/audio-codecs"; const registry = new CodecRegistry({ codecs: [WavCodec] }); await encodeTo(doc, "/tmp/out.wav", "wav", { registry, bitDepth: 16, format: "pcm", }); ``` ## Usage: Advanced Example Encode to a streaming destination (e.g. an HTTP response body) with abort cancellation: ```ts import { CodecRegistry, encodeTo, WavCodec } from "@suaveplan/audio-codecs"; const registry = new CodecRegistry({ codecs: [WavCodec] }); const ctrl = new AbortController(); const responseStream = new WritableStream({ write(chunk) { sendOverWebSocket(chunk); }, }); await encodeTo(doc, responseStream, "wav", { registry, bitDepth: 24, format: "pcm", signal: ctrl.signal, }); // Or write via callback for fine-grained control: let captured: Uint8Array | undefined; await encodeTo(doc, (chunk) => { captured = chunk; }, "wav", { registry }); ``` ## API Reference - `type Destination = string | WritableStream | ((chunk: Uint8Array) => void)` - `interface EncodeToOpts { sampleRate?, bitDepth?, format?, signal?, registry? }` - `const EncodeToOptsSchema` — Zod schema validating `sampleRate`, `bitDepth`, and `format`. - `async function encodeTo(doc: AudioDocument, destination: Destination, format: string, opts?: EncodeToOpts): Promise` — throws `INVALID_SOURCE` for invalid options or unrecognised destination, `STREAM_ERROR` for pre-aborted signals, `NOT_SUPPORTED` for unknown formats, `ENCODE_FAILED` for codec errors. ## Implementation Notes - The file-path destination uses dynamic `import('node:fs/promises')` to keep the package universal. Browser callers must use the `WritableStream` or callback destination — passing a string path in a browser would fail with `INVALID_SOURCE` via the dynamic import failure, which then surfaces as `INVALID_SOURCE` at the outer boundary. - The `WritableStream` path acquires a writer, writes one chunk, then closes via `writer.close()`. Callers that need to keep the stream open for additional writes should use a callback destination instead — the closed-after-one-write semantics matches the single-payload encode model. - The callback destination receives the full encoded buffer in one invocation. For per-chunk encode (where bytes arrive as encoding progresses), use `CodecRegistry.encodeStream` directly instead of `encodeTo`. - Codec error wrapping preserves the original via `cause`; callers can recover the underlying error via `(err as AudioCodecsError).cause`. - `opts.signal` is checked only before dispatch — codec internal abort during encode requires the codec to honour the signal, which most current codecs (WAV native, WASM wrappers) do not. Mid-encode cancellation will not interrupt the codec call but will surface as a thrown `STREAM_ERROR` from any subsequent `encodeTo` call against the same controller.