Skip to content

VonageAudioSocket

Duplex audio provider for the Vonage Voice API WebSocket endpoint.

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:310

Duplex audio provider for the Vonage Voice API WebSocket endpoint.

Remarks

VonageAudioSocket covers BOTH the 'input' and 'output' pipeline roles for a phone call bridged to your server via an NCCO connect action with a websocket endpoint:

[
  {
    "action": "connect",
    "endpoint": [
      {
        "type": "websocket",
        "uri": "wss://example.com/vonage",
        "content-type": "audio/l16;rate=16000"
      }
    ]
  }
]

Your application accepts the WebSocket connection and passes the socket to attach(). The provider then:

  • parses the sample rate from the websocket:connected JSON event (8000 / 16000 / 24000 Hz, default 16000),
  • emits every inbound binary frame as a linear16 AudioChunk,
  • converts and re-chunks TTS audio into 20 ms linear16 frames at the negotiated rate, sent on a paced 20 ms timer (Vonage rejects large unpaced bursts),
  • surfaces DTMF key presses via onDtmf().

Data-flow diagram:

 socket binary frame ──> [input role] ──callback(chunk)──> InputQueue ──> STT
 TTS chunk ──enqueue()──> convert to linear16@rate ──> byte queue
                                                           │ 20 ms pump
                                                           v
                                               socket.send(640-byte frame)

Duplex semantics — one stop(), one pause(): because a single instance fills both the input and output pipeline slots, the shared lifecycle methods follow the semantics CompositeVoice relies on at runtime:

  • stop() implements the OUTPUT contract (barge-in): it clears the outbound queue and pump and settles any pending flush(). It deliberately does NOT deactivate inbound capture — CompositeVoice calls output.stop() when the caller interrupts the agent, and silencing the microphone there would leave the call permanently deaf. Inbound capture ends on detach(), socket close (remote hangup), or dispose().
  • pause() / resume() gate the INPUT side only. The turn-taking controller pauses input while the agent speaks and then awaits output.flush(); pausing the outbound pump too would deadlock that flush.

Output formats: linear16 at the negotiated rate passes straight through; linear16 at any other rate is resampled (linear interpolation); mulaw/alaw are G.711-decoded then resampled. Compressed formats (opus, mp3) are rejected by VonageAudioSocket.configure | configure() with instructions to reconfigure the TTS provider — e.g. new DeepgramTTS({ encoding: 'linear16', sampleRate: 16000 }).

STT auto-configuration caveat: VonageAudioSocket.getMetadata | getMetadata() is read at pipeline initialization, usually before Vonage has connected, so it reports the default 16000 Hz until the websocket:connected event arrives. Set content-type in your NCCO to audio/l16;rate=16000 (recommended) or configure your STT provider’s sample rate to match your NCCO rate.

Example

import { WebSocketServer } from 'ws';
import { VonageAudioSocket } from 'composite-voice';

const vonage = new VonageAudioSocket({ debug: true });
await vonage.initialize();

vonage.onDtmf((digit, duration) => {
  console.log(`Caller pressed ${digit} for ${duration} ms`);
});

const wss = new WebSocketServer({ port: 3000, path: '/vonage' });
wss.on('connection', (socket) => vonage.attach(socket));

See

Implements

Constructors

Constructor

new VonageAudioSocket(config?): VonageAudioSocket;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:425

Creates a new VonageAudioSocket instance.

Parameters

ParameterTypeDescription
configVonageAudioSocketConfigOptional configuration (see VonageAudioSocketConfig).

Returns

VonageAudioSocket

Remarks

Construction is cheap and performs no I/O. Call initialize before use and attach once Vonage has opened its WebSocket to your server.

Example

const vonage = new VonageAudioSocket({ debug: true });

Properties

PropertyModifierTypeDefault valueDescriptionDefined in
rolesreadonlyreadonly ProviderRole[]undefinedPipeline roles covered by this provider. Remarks VonageAudioSocket is a duplex provider covering the 'input' and 'output' slots. Separate STT, LLM, and TTS providers are still required.src/providers/io/vonage/VonageAudioSocket.ts:329
typereadonlyProviderType'websocket'Communication type for this provider. Remarks 'websocket' — the provider holds (a reference to) a persistent WebSocket for the duration of the call, even though the connection is accepted by the application rather than dialed by the provider.src/providers/io/vonage/VonageAudioSocket.ts:319

Methods

attach()

attach(socket): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:521

Attach the WebSocket that Vonage opened to your server.

Parameters

ParameterTypeDescription
socketVonageSocketThe accepted WebSocket (see VonageSocket).

Returns

void

Remarks

Wires message and close handlers using whichever event style the socket supports (on(...) for Node ws, addEventListener(...) for browser-style sockets) and resets the per-call negotiation state — the sample rate returns to the 16000 Hz default until the new call’s websocket:connected event arrives. If another socket is already attached it is detached first (its listeners are removed and any queued outbound audio is dropped).

When the socket exposes a binaryType property it is set to 'arraybuffer' so browser-style sockets deliver binary frames as ArrayBuffer rather than Blob.

The provider never closes the socket — your application owns its lifecycle.

Throws

ConfigurationError if the socket supports neither on() nor addEventListener().

Example

const wss = new WebSocketServer({ port: 3000 });
wss.on('connection', (socket) => vonage.attach(socket));

See

detach for the inverse operation


configure()

configure(metadata): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:811

Configure the output with the TTS provider’s audio format.

Parameters

ParameterTypeDescription
metadataAudioMetadataFormat description for incoming TTS chunks.

Returns

void

Remarks

Accepted encodings:

  • 'linear16' — passed through when the rate matches the negotiated rate, otherwise resampled with linear interpolation.
  • 'mulaw' / 'alaw' — G.711-decoded to linear16, then resampled if needed.

Compressed encodings ('opus', 'mp3') cannot be decoded server-side without heavy dependencies and are rejected. Configure your TTS provider for raw PCM instead — e.g. new DeepgramTTS({ encoding: 'linear16', sampleRate: 16000 }).

Throws

ConfigurationError if the encoding is unsupported or the audio is not mono.

Implementation of

AudioOutputProvider.configure


detach()

detach(): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:586

Detach the current socket, if any.

Returns

void

Remarks

Removes the provider’s message/close listeners, stops the outbound frame pump, drops any queued outbound audio, and settles pending flush promises (they resolve — the audio is cancelled, not failed). The socket itself is NOT closed; the application owns it. Inbound emission naturally ceases because no socket is delivering frames.

A no-op when no socket is attached — audio enqueued before the first attach stays queued and starts draining once a socket arrives.

See

attach


dispose()

dispose(): Promise<void>;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:456

Dispose of the provider and release all resources.

Returns

Promise<void>

Remarks

Detaches the socket (listeners removed, pump stopped, queue cleared, pending flush settled), clears every registered callback, and resets the sequence counter. The instance may be re-initialized afterwards.

Implementation of

AudioOutputProvider.dispose


enqueue()

enqueue(chunk): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:848

Enqueue a TTS audio chunk for playback into the call.

Parameters

ParameterTypeDescription
chunkAudioChunkAudio data from the TTS stage.

Returns

void

Remarks

The chunk is converted to linear16 at the negotiated sample rate (see configure) and appended to the outbound byte queue. A 20 ms interval pump chunks the queue into fixed-size frames (sampleRate / 50 samples) and sends one per tick — Vonage requires paced frames rather than a single burst.

Per-chunk metadata overrides the format set by configure. If neither is present the chunk is assumed to already be linear16 at the negotiated rate.

Implementation of

AudioOutputProvider.enqueue


flush()

flush(): Promise<void>;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:892

Wait for all enqueued audio to be delivered into the call.

Returns

Promise<void>

Remarks

Vonage has no mark/acknowledgement mechanism, so completion is timed: the paced pump sends one 20 ms frame per 20 ms tick, and flush() resolves one tick after the final frame is sent — i.e. after the total queued duration has elapsed. flush() also marks the end of the response, allowing the pump to send a final zero-padded partial frame if the queued bytes do not divide evenly into 20 ms frames.

Resolves immediately when nothing is queued or playing. Also resolves (as cancelled) on stop, detach, socket close, or dispose.

Implementation of

AudioOutputProvider.flush


getContentType()

getContentType(): string | null;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:634

Get the raw content-type announced by the websocket:connected event.

Returns

string | null

The content type (e.g. 'audio/l16;rate=16000'), or null if the connected event has not arrived yet.

Example

vonage.getContentType(); // 'audio/l16;rate=16000'

getMetadata()

getMetadata(): AudioMetadata;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:779

Get the format of the audio this provider emits.

Returns

AudioMetadata

AudioMetadata describing the inbound audio format.

Remarks

Always linear16 mono, 16-bit, at the negotiated sample rate. Until the websocket:connected event arrives this reports the 16000 Hz default — the pipeline reads it at initialization time to auto-configure STT, so either use audio/l16;rate=16000 in your NCCO (recommended) or configure the STT provider’s sample rate to match your NCCO explicitly.

Implementation of

AudioInputProvider.getMetadata


initialize()

initialize(): Promise<void>;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:441

Initialize the provider.

Returns

Promise<void>

Remarks

No external resources are acquired — the WebSocket is created by Vonage and supplied via attach. If already initialized, this is a no-op.

Implementation of

AudioOutputProvider.initialize


isActive()

isActive(): boolean;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:749

Check whether inbound audio is actively being emitted.

Returns

boolean

true when started and not paused.

Implementation of

AudioInputProvider.isActive


isPlaying()

isPlaying(): boolean;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:908

Check whether audio is currently being delivered into the call.

Returns

boolean

true between onPlaybackStart and onPlaybackEnd.

Implementation of

AudioOutputProvider.isPlaying


isReady()

isReady(): boolean;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:483

Check whether the provider has been initialized.

Returns

boolean

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

Implementation of

AudioOutputProvider.isReady


onAudio()

onAudio(callback): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:763

Register a callback to receive inbound audio chunks.

Parameters

ParameterTypeDescription
callback(chunk) => voidInvoked with each inbound AudioChunk (raw linear16 PCM at the negotiated sample rate).

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


onDtmf()

onDtmf(callback): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:619

Register a callback for DTMF key presses on the call.

Parameters

ParameterTypeDescription
callbackVonageDtmfCallbackInvoked with the digit and (when present) its duration in milliseconds.

Returns

void

Remarks

Vonage forwards keypad presses as JSON text frames {"event":"websocket:dtmf","digit":"5","duration":260}. Only one callback can be registered at a time; subsequent calls replace it.

Example

vonage.onDtmf((digit) => {
  if (digit === '0') transferToHuman();
});

onPlaybackEnd()

onPlaybackEnd(callback): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:931

Register a callback invoked when the outbound queue fully drains.

Parameters

ParameterTypeDescription
callback() => voidFunction called when playback ends.

Returns

void

Remarks

Also fired when playback is cancelled by stop, detach, or a socket close while audio was being delivered.

Implementation of

AudioOutputProvider.onPlaybackEnd


onPlaybackError()

onPlaybackError(callback): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:940

Register a callback invoked when sending audio to Vonage fails.

Parameters

ParameterTypeDescription
callback(error) => voidFunction called with the error.

Returns

void

Implementation of

AudioOutputProvider.onPlaybackError


onPlaybackStart()

onPlaybackStart(callback): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:918

Register a callback invoked when audio delivery begins after being idle.

Parameters

ParameterTypeDescription
callback() => voidFunction called when the first frame of a response is sent to Vonage.

Returns

void

Implementation of

AudioOutputProvider.onPlaybackStart


pause()

pause(): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:727

Pause inbound audio emission without dropping the call.

Returns

void

Remarks

Used by the turn-taking system to mute capture while the agent speaks. Frames received while paused are silently dropped. Outbound playback is intentionally unaffected — the turn-taking controller awaits flush() right after pausing input, and pausing the outbound pump here would deadlock that flush.

Implementation of

AudioOutputProvider.pause


resume()

resume(): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:738

Resume inbound audio emission after pause.

Returns

void

See

pause

Implementation of

AudioOutputProvider.resume


start()

start(): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:648

Start emitting inbound call audio as AudioChunk objects.

Returns

void

Remarks

Binary frames received before start() is called are silently dropped. Must be called after initialize; audio additionally requires an attached socket to flow.

Implementation of

AudioInputProvider.start


stop()

stop(): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:673

Stop outbound playback immediately and clear buffered audio (barge-in).

Returns

void

Remarks

This is the shared stop() of a duplex provider, and it implements the OUTPUT role’s contract: the outbound frame pump is cleared, queued audio is dropped, pending flush promises resolve (cancelled, not completed), and onPlaybackEnd fires if delivery was in progress.

As a duplex provider, the same stop() is invoked by CompositeVoice for two different reasons, so the provider dispatches on playback state:

  • Barge-in (output.stop()) — while outbound audio is queued or being delivered, only the output side is stopped. Inbound capture is deliberately kept alive: barge-in happens because the caller is speaking, and that speech must keep flowing to STT.
  • Stop listening (input.stop()) — with no outbound audio in flight, inbound emission is halted instead (restart with start()).

Implementation of

AudioOutputProvider.stop


stopCapture()

stopCapture(): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:711

Stop emitting caller audio, leaving outbound delivery alone.

Returns

void

Remarks

The pipeline calls this when it means “stop listening”. Restart with start().

Implementation of

AudioInputProvider.stopCapture


stopPlayback()

stopPlayback(): void;

Defined in: src/providers/io/vonage/VonageAudioSocket.ts:698

Stop outbound delivery, leaving caller audio flowing.

Returns

void

Remarks

The pipeline calls this for barge-in, so the provider never has to infer which side was meant. Clears the paced queue and settles any pending flush() as cancelled, so the pipeline cannot hang waiting on audio that will never be sent.

Capture is deliberately untouched: barge-in fires because the caller is speaking, and that speech has to reach STT. Safe when nothing is playing — barge-in is also raised while the agent is still thinking.

Implementation of

AudioOutputProvider.stopPlayback

© 2026 CompositeVoice. All rights reserved.

Font size
Contrast
Motion
Transparency