Skip to content

BufferInput

Server-side audio input provider that accepts pushed audio buffers.

Defined in: src/providers/input/BufferInput.ts:206

Server-side audio input provider that accepts pushed audio buffers.

Remarks

BufferInput allows server-side applications to feed audio data into the CompositeVoice pipeline without any browser dependencies. The application pushes raw audio via push(), and BufferInput wraps each buffer into an AudioChunk with a timestamp and sequence number before delivering it to the registered callback.

The audio format can be declared up-front in the constructor via AudioMetadata, letting the pipeline auto-configure STT encoding/sample-rate settings. Anything left undeclared is filled in by magic-byte detection on the pushed bytes, so a pipeline can accept an arbitrary WAV, OGG, or MP3 buffer with no format configuration at all.

Format resolution order (first defined value wins):

  1. Fields declared in the constructor
  2. Fields detected from the container header of the pushed audio
  3. Raw-PCM defaults — 16 kHz, mono, linear16

Detection timing matters. The pipeline reads getMetadata() while startListening() runs, which is before the first push(). To have detected values reach the STT provider, sniff the head of the stream with detectFormat() before starting the pipeline. Detection during push() still updates getMetadata() and fires onFormatDetected(), but arrives too late to configure an STT provider that has already connected.

Data-flow diagram:

app.push(data) ──> BufferInput ──callback(chunk)──> InputQueue ──> STT
                       |
                 active=true?
                   yes: emit + sniff format
                   no:  drop

Examples

import { BufferInput } from 'composite-voice';
import { createReadStream } from 'node:fs';

const input = new BufferInput({
  sampleRate: 16000,
  encoding: 'linear16',
  channels: 1,
  bitDepth: 16,
});

await input.initialize();
input.onAudio((chunk) => {
  console.log(`Received ${chunk.data.byteLength} bytes, seq=${chunk.sequence}`);
});
input.start();

// Stream audio from a file
const stream = createReadStream('audio.raw', { highWaterMark: 4096 });
stream.on('data', (buf: Buffer) => input.push(buf.buffer));
// No format declared — sniff the file header, then let the pipeline configure
// the STT provider from what was found.
import { readFileSync } from 'node:fs';

const audio = readFileSync('speech.wav');
const input = new BufferInput();

input.detectFormat(audio.buffer);
// => { sampleRate: 16000, encoding: 'linear16', channels: 1, bitDepth: 16,
//      mimeType: 'audio/wav' }

await voice.startListening();
input.push(audio.buffer);

See

Implements

Constructors

Constructor

new BufferInput(metadata?, options?): BufferInput;

Defined in: src/providers/input/BufferInput.ts:299

Creates a new BufferInput instance.

Parameters

ParameterTypeDescription
metadataPartial<AudioMetadata>Format description for the audio that will be pushed. Omit it entirely to rely on detection.
optionsBufferInputOptionsProvider options — see BufferInputOptions.

Returns

BufferInput

Remarks

The metadata parameter declares the audio format that will be pushed via push(). This metadata is returned by getMetadata() and used by the pipeline to auto-configure the downstream STT provider.

Every field is optional. Undeclared fields are filled in from the container header of the pushed audio, falling back to 16 kHz mono linear16 when the stream carries no recognizable header. Declared fields are never overwritten by detection, so partial declarations work: declare the sample rate you know and let the container supply the rest.

Example

// Fully declared — no detection needed
const input = new BufferInput({
  sampleRate: 16000,
  encoding: 'linear16',
  channels: 1,
  bitDepth: 16,
});

// Undeclared — format comes from the pushed buffer's header
const sniffing = new BufferInput();

// Declared format, detection off — pushed headers are ignored
const fixed = new BufferInput(
  { sampleRate: 8000, encoding: 'mulaw', channels: 1 },
  { autoDetect: false }
);

Properties

PropertyModifierTypeDefault valueDescriptionDefined in
rolesreadonlyreadonly ProviderRole[]undefinedPipeline roles covered by this provider. Remarks BufferInput is a single-role provider covering only the 'input' slot. It requires a separate STT provider for the 'stt' role.src/providers/input/BufferInput.ts:223
typereadonlyProviderType'rest'Communication type for this provider. Remarks BufferInput uses 'rest' because it does not maintain a persistent connection — audio is pushed imperatively by the application.src/providers/input/BufferInput.ts:214

Methods

detectFormat()

detectFormat(data): AudioMetadata;

Defined in: src/providers/input/BufferInput.ts:604

Detect the audio format from a buffer without pushing it into the pipeline.

Parameters

ParameterTypeDescription
dataArrayBufferThe start of the audio stream to inspect.

Returns

AudioMetadata

The resolved AudioMetadata, identical to what getMetadata() now returns.

Remarks

Runs the same sniffing push() performs, but emits nothing. Call it before startListening() so the detected format reaches the STT provider: the pipeline reads getMetadata() while starting, before any audio has been pushed.

Pass the head of the stream — the first few kilobytes are enough, and the whole file is fine. Detection accumulates across calls, so feeding chunks of a stream one at a time works the same as feeding a single buffer. Once the format resolves, further calls are no-ops until resetDetection().

Works even when autoDetect is disabled — an explicit call is an explicit request. Declared format fields still take precedence in the result.

Example

const audio = readFileSync('speech.ogg');
const input = new BufferInput();

const metadata = input.detectFormat(audio.buffer);
console.log(metadata.encoding, metadata.sampleRate); // 'opus' 48000

await voice.startListening(); // STT is configured from the detected format
input.push(audio.buffer);

See

onFormatDetected for the callback form


dispose()

dispose(): Promise<void>;

Defined in: src/providers/input/BufferInput.ts:326

Dispose of the provider and release all resources.

Returns

Promise<void>

Remarks

Stops accepting audio, clears the callback references, discards any detected format, and resets the sequence counter. After disposal the instance should not be reused.

Implementation of

AudioInputProvider.dispose


getDetectedFormat()

getDetectedFormat(): DetectedAudioFormat | null;

Defined in: src/providers/input/BufferInput.ts:477

Get the container format detected from the pushed audio.

Returns

DetectedAudioFormat | null

The detected DetectedAudioFormat, or null when detection has not resolved yet or the stream carries no recognizable container (raw PCM, or an unknown format).

See

isFormatResolved to tell the two null cases apart


getMetadata()

getMetadata(): AudioMetadata;

Defined in: src/providers/input/BufferInput.ts:440

Get the audio format metadata for the audio being pushed.

Returns

AudioMetadata

The resolved AudioMetadata for the current stream.

Remarks

Merges three sources, in descending priority: the fields declared in the constructor, the fields detected from the pushed stream’s container header, and the raw-PCM defaults (16 kHz mono linear16). The result therefore changes once detection resolves, unless every field was declared.

Used by the pipeline to auto-configure STT encoding, sample rate, and channel settings via configureSTTFromMetadata(). That call happens during startListening() — see the class remarks on detection timing.

See

detectFormat to resolve detection early

Implementation of

AudioInputProvider.getMetadata


initialize()

initialize(): Promise<void>;

Defined in: src/providers/input/BufferInput.ts:313

Initialize the provider, making it ready to accept audio.

Returns

Promise<void>

Remarks

A no-op beyond setting the initialized flag, since BufferInput has no external resources to acquire. If already initialized, this is a no-op.

Implementation of

AudioInputProvider.initialize


isActive()

isActive(): boolean;

Defined in: src/providers/input/BufferInput.ts:404

Check whether the provider is actively emitting audio.

Returns

boolean

true when started and not paused.

Implementation of

AudioInputProvider.isActive


isFormatResolved()

isFormatResolved(): boolean;

Defined in: src/providers/input/BufferInput.ts:488

Check whether format detection has finished for the current stream.

Returns

boolean

true once enough bytes have been seen to settle on a format — including the raw-PCM fallback, where BufferInput.getDetectedFormat | getDetectedFormat() stays null.


isReady()

isReady(): boolean;

Defined in: src/providers/input/BufferInput.ts:343

Check whether the provider has been initialized.

Returns

boolean

true when initialize has completed and dispose has not yet been called.

Implementation of

AudioInputProvider.isReady


onAudio()

onAudio(callback): void;

Defined in: src/providers/input/BufferInput.ts:419

Register a callback to receive audio chunks.

Parameters

ParameterTypeDescription
callback(chunk) => voidFunction invoked with each AudioChunk when audio is pushed and the provider is active.

Returns

void

Remarks

Only one callback can be registered at a time; subsequent calls replace the previous callback. Must be called before start().

Implementation of

AudioInputProvider.onAudio


onFormatDetected()

onFormatDetected(callback): void;

Defined in: src/providers/input/BufferInput.ts:514

Register a callback fired when the audio format is detected.

Parameters

ParameterTypeDescription
callback(metadata, format) => voidInvoked with the resolved AudioMetadata and the detected container format, which is null for raw PCM and unknown formats.

Returns

void

Remarks

Invoked once per stream, as soon as detection resolves — from either push() or BufferInput.detectFormat | detectFormat(). Only one callback can be registered at a time; subsequent calls replace the previous one.

The callback does not fire when autoDetect is disabled and detectFormat() is never called.

Example

input.onFormatDetected((metadata, format) => {
  console.log(`Detected ${format ?? 'raw pcm'} at ${metadata.sampleRate} Hz`);
});

pause()

pause(): void;

Defined in: src/providers/input/BufferInput.ts:382

Temporarily pause audio emission without stopping the provider.

Returns

void

Remarks

Audio pushed while paused is silently dropped. Resume with resume().

Implementation of

AudioInputProvider.pause


push()

push(data): void;

Defined in: src/providers/input/BufferInput.ts:552

Push raw audio data into the pipeline.

Parameters

ParameterTypeDescription
dataArrayBufferRaw audio bytes matching the format declared in the constructor’s AudioMetadata, or any container format listed in DetectedAudioFormat when relying on detection.

Returns

void

Remarks

Wraps the raw ArrayBuffer into an AudioChunk with a timestamp and monotonically increasing sequence number, then delivers it to the registered callback. If the provider is not active (not started, stopped, or paused), the data is silently dropped.

Unless detection is disabled, the head of the stream is also sniffed for a container signature, updating getMetadata() and firing onFormatDetected(). Sniffing copies at most MAX_SNIFF_BYTES bytes and never delays or alters the emitted chunk — headers are passed through to the STT provider intact, since that is what AudioHeaderCache re-injects on reconnect.

Example

// Push PCM audio from a Node.js Buffer
const pcmBuffer = Buffer.alloc(3200); // 100ms of 16kHz 16-bit mono
input.push(pcmBuffer.buffer);

// Push from a WebSocket message
ws.on('message', (data: ArrayBuffer) => input.push(data));

resetDetection()

resetDetection(): void;

Defined in: src/providers/input/BufferInput.ts:618

Discard the detected format so the next stream is sniffed afresh.

Returns

void

Remarks

Detection resolves once and then stops inspecting bytes, which is what you want for a single stream. Call this between streams — a new file pushed into the same provider, say — so the next one is detected on its own merits. Declared format fields are unaffected.


resume()

resume(): void;

Defined in: src/providers/input/BufferInput.ts:393

Resume audio emission after a pause.

Returns

void

See

pause

Implementation of

AudioInputProvider.resume


start()

start(): void;

Defined in: src/providers/input/BufferInput.ts:358

Start accepting and emitting audio chunks.

Returns

void

Remarks

After calling start(), audio pushed via push() will be delivered to the callback registered with onAudio(). Must be called after initialize().

Implementation of

AudioInputProvider.start


stop()

stop(): void;

Defined in: src/providers/input/BufferInput.ts:370

Stop accepting audio and cease emitting chunks.

Returns

void

Remarks

Audio pushed after stop() is silently dropped. The provider can be restarted with start().

Implementation of

AudioInputProvider.stop

© 2026 CompositeVoice. All rights reserved.

Font size
Contrast
Motion
Transparency