first commit
This commit is contained in:
76
docs/media/audio/audio-engine-server/src/sink/file-sink.md
Normal file
76
docs/media/audio/audio-engine-server/src/sink/file-sink.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# FileSinkAdapter
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`FileSinkAdapter` is the server-tier exit point for `AudioDocument`
|
||||
instances: it encodes a document through `@suaveplan/audio-codecs` for
|
||||
the requested format and writes the resulting bytes through the injected
|
||||
`FsLike` seam. Like `FileSourceAdapter`, the sink owns the
|
||||
path-sanitisation boundary and exposes both buffered (`save`,
|
||||
`saveMany`) and streaming (`createWriteStream`) modes.
|
||||
|
||||
## Features
|
||||
|
||||
- Buffered `save(doc, path, format, opts?)` runs the codec encoder via
|
||||
`encodeTo`, concatenates the resulting chunks, and writes the file —
|
||||
creating parent directories implicitly.
|
||||
- `saveMany(docs, pathFormat, format, opts?)` parallel-encodes a list of
|
||||
documents, expanding `%d` in the path template per index.
|
||||
- `createWriteStream(path)` returns a WHATWG `WritableStream<Uint8Array>`
|
||||
backed by `node:fs.createWriteStream` (or the injected `FsLike`).
|
||||
- Zod-validated options; failures throw `AUDIO_ENGINE_SERVER.INVALID_OPTIONS`.
|
||||
- `sanitizePath` runs before any filesystem call.
|
||||
- Unknown / unregistered format → `AUDIO_ENGINE_SERVER.ENCODE_FAILED`.
|
||||
- Underlying write errors → `AUDIO_ENGINE_SERVER.IO_FAILED`.
|
||||
- OpenTelemetry instrumentation — span `file.save`, counter
|
||||
`audio_engine_bytes_written_total`, histogram
|
||||
`audio_engine_save_duration_ms`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { FileSinkAdapter } from "@suaveplan/audio-engine-server";
|
||||
|
||||
const sink = new FileSinkAdapter();
|
||||
await sink.save(doc, "/tmp/out.flac", "flac");
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
const sink = new FileSinkAdapter({ rootDir: "/var/exports" });
|
||||
const writer = sink.createWriteStream("session.wav");
|
||||
await pcmStream.pipeTo(writer);
|
||||
|
||||
await sink.saveMany(
|
||||
[trackA, trackB, trackC],
|
||||
"stem-%d.wav",
|
||||
"wav",
|
||||
{ bitDepth: 24 }
|
||||
);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `new FileSinkAdapter(options?: FileSinkOptions)` — `fs`, `registry`,
|
||||
`rootDir` optional.
|
||||
- `save(doc, path, format, opts?): Promise<void>`
|
||||
- `saveMany(docs, pathFormat, format?, opts?): Promise<void>`
|
||||
- `createWriteStream(path): WritableStream<Uint8Array>`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The buffered `save` collects encoder chunks into an array, computes the
|
||||
total length, and writes a single concatenated buffer; the codec layer
|
||||
already streams internally so this is a small one-time copy. `saveMany`
|
||||
substitutes the literal `%d` token in `pathFormat` with the document's
|
||||
index. Unknown codec formats surface from the codec layer as
|
||||
`AUDIO_CODECS.NOT_SUPPORTED`; the sink re-throws them as
|
||||
`AUDIO_ENGINE_SERVER.ENCODE_FAILED` with the offending format in
|
||||
`context`. Underlying `node:fs` write failures (`EACCES`, `ENOSPC`, etc.)
|
||||
become `AUDIO_ENGINE_SERVER.IO_FAILED` with the resolved absolute path in
|
||||
`context`.
|
||||
Reference in New Issue
Block a user