Files
skills/docs/media/audio/audio-engine-server/src/source/file-source.md
2026-05-29 08:20:56 +01:00

3.1 KiB

FileSourceAdapter

(no submodules)

Purpose

FileSourceAdapter is the server-tier entry point for reading audio files into the universal AudioDocument model. It owns the path-sanitisation boundary, dispatches to @suaveplan/audio-codecs decodeSource for format detection and decode, and exposes both buffered (load, loadMany) and streaming (createReadStream) modes through a single injectable FsLike seam. The adapter implements no DSP itself — every byte ends up routed through the universal codec layer.

Features

  • Buffered load(path, opts?) returns an AudioDocument from a local path or an http/https URL.
  • loadMany(paths, opts?) resolves a Promise.all over load, preserving input order regardless of decode completion order.
  • createReadStream(path) returns a WHATWG ReadableStream<Uint8Array> backed by the injected FsLike (or node:fs.createReadStream).
  • Zod-validated options at every entry point; failures throw AUDIO_ENGINE_SERVER.INVALID_OPTIONS.
  • sanitizePath rejects empty / null-byte / ..-traversal paths against the optional rootDir boundary before any filesystem call is issued.
  • AbortSignal propagation — pre-aborted signals short-circuit with AUDIO_ENGINE_SERVER.ABORTED; mid-load aborts surface the same code via the codec layer.
  • OpenTelemetry instrumentation — span file.load, counter audio_engine_bytes_read_total, histogram audio_engine_load_duration_ms. Inert without an exporter.

Usage: Basic

import { FileSourceAdapter } from "@suaveplan/audio-engine-server";

const source = new FileSourceAdapter();
const doc = await source.load("/tmp/sample.wav");
console.log(doc.sampleRate, doc.channels, doc.sourceLength);

Usage: Advanced

import { FileSourceAdapter, defaultFs } from "@suaveplan/audio-engine-server";

const source = new FileSourceAdapter({
    fs: defaultFs,
    rootDir: "/var/audio",
    registry: customCodecRegistry,
});

const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 5000);
const docs = await source.loadMany(
    ["a.wav", "b.flac", "c.mp3"],
    { signal: ctrl.signal }
);

API Reference

  • new FileSourceAdapter(options?: FileSourceOptions) — fs, fetch, registry, rootDir all optional.
  • load(path, opts?): Promise<AudioDocument>
  • loadMany(paths, opts?): Promise<AudioDocument[]>
  • createReadStream(path): ReadableStream<Uint8Array>

Implementation Notes

load distinguishes URL inputs via isHttpUrl; URL inputs are fetched through the injected fetch and skip filesystem sanitisation. Local paths pass through sanitizePath(path, rootDir) before any FsLike call, so a path-traversal attempt throws INVALID_PATH before the filesystem is touched. ENOENT from the underlying readFile is mapped to FILE_NOT_FOUND; any other read error becomes IO_FAILED. Decode failures from the codec layer are re-thrown as DECODE_FAILED unless the inner error reports a stream abort, in which case the engine maps it to AUDIO_ENGINE_SERVER.ABORTED to preserve the signal-aborted contract.