Class TelephonyStreamTransport

Adapts a telephony provider WebSocket media stream to the IStreamTransport interface consumed by the AgentOS voice pipeline.

Inbound path (phone -> pipeline)

  1. Provider WebSocket frames arrive as raw Buffer or JSON string.
  2. MediaStreamParser.parseIncoming normalises them to MediaStreamIncoming events.
  3. 'audio' events: mu-law 8 kHz -> Int16 PCM -> resample -> Float32 -> 'audio' emit.
  4. 'dtmf' / 'mark' events are re-emitted as-is for higher-layer handling.
  5. 'start' transitions the transport to 'open' and sends the optional connection acknowledgment from the parser.
  6. 'stop' or WebSocket close transitions to 'closed' and emits 'close'.

Outbound path (pipeline -> phone)

  1. sendAudio() receives an EncodedAudioChunk (PCM Int16 format assumed).
  2. Chunk is resampled from chunk.sampleRate -> 8 kHz via linear interpolation.
  3. Resampled PCM is mu-law encoded via convertPcmToMulaw8k.
  4. MediaStreamParser.formatOutgoing wraps the bytes for the provider.
  5. The formatted payload is sent over the WebSocket.

Events emitted

  • 'audio' (AudioFrame) -- inbound decoded audio for STT / VAD.
  • 'dtmf' ({ digit: string; durationMs?: number }) -- caller key-press.
  • 'mark' ({ name: string }) -- named stream marker.
  • 'close' () -- transport has been fully closed.
  • 'error' (Error) -- unrecoverable WebSocket or parsing error.

Example

const parser = new TwilioMediaStreamParser();
const transport = new TelephonyStreamTransport(ws, parser, { outputSampleRate: 16000 });

transport.on('audio', (frame: AudioFrame) => {
// Feed to STT engine
sttEngine.pushAudio(frame.samples, frame.sampleRate);
});

transport.on('dtmf', ({ digit }) => {
console.log(`Caller pressed: ${digit}`);
});

Hierarchy

  • EventEmitter
    • TelephonyStreamTransport

Implements

  • IStreamTransport

Accessors

Constructors

Methods

Properties

Accessors

  • get state(): "connecting" | "open" | "closing" | "closed"
  • Current connection lifecycle state.

    • connecting -- WebSocket is open but the provider's start event has not arrived yet.
    • open -- Stream is active; audio can be sent and received.
    • closing -- close was called; waiting for WS to finish closing.
    • closed -- Stream is fully terminated; no further I/O.

    Returns "connecting" | "open" | "closing" | "closed"

Constructors

Methods

  • Send synthesised audio to the caller.

    Assumes chunk.format === 'pcm' and that chunk.audio contains raw signed 16-bit little-endian PCM samples at chunk.sampleRate. The audio is resampled to 8 kHz, mu-law encoded, and forwarded via the parser.

    No-op if the transport is not in the 'open' state (e.g., before the provider's start event or after the stream has closed).

    Parameters

    • chunk: EncodedAudioChunk

      Encoded audio chunk from the TTS pipeline.

    Returns Promise<void>

  • Send a JSON control message over the WebSocket.

    No-op if the transport is not in the 'open' state.

    Parameters

    • message: ServerTextMessage

      Server-to-client pipeline protocol message.

    Returns Promise<void>

  • Initiate graceful closure of the transport.

    Sets state to 'closing' and delegates to the underlying WebSocket's close() method. The actual transition to 'closed' happens when the WebSocket's 'close' event fires.

    Parameters

    • Optional code: number

      Optional WebSocket close code (default 1000).

    • Optional reason: string

      Optional human-readable close reason.

    Returns void

Properties

id: string = ...

Stable UUID for this transport connection.