Skip to main content
What HappensWhen Vobiz encounters a Stream element in your XML response:
  1. Vobiz initiates a WebSocket connection to your specified URL
  2. Once connected, raw audio packets are streamed in real-time
  3. Your application can process, analyze, or forward the audio
  4. For bidirectional streams, your app can also send audio back to the call

XML Setup

To initiate an audio stream, include the Stream element in your XML response with the WebSocket URL:
Basic Stream XML
Understanding keepCallAliveWithout keepCallAlive="true": The <Stream> element starts the background stream process and finishes immediately. Since there are no more elements in your XML response, the call hits “End Of XML Instructions” and hangs up instantly.With keepCallAlive="true": The system explicitly waits for the stream to finish (disconnect/error/timeout) before moving on or hanging up. This keeps the call open without needing a <Pause> element.Note: keepCallAlive requires bidirectional="true". Use this attribute instead of <Pause> for a cleaner implementation.

Key Configuration Parameters

  • WebSocket URL: The text content of the element (e.g., wss://stream.vobiz.ai/stream). Must be publicly reachable; use wss:// (TLS) in production - ws:// is for local testing only.
  • bidirectional: Set to true to enable sending audio back to the call. Requires audioTrack="inbound" (or omit it).
  • audioTrack: inbound (caller), outbound (callee), or both. Default inbound. Do not combine both/outbound with bidirectional="true".
  • contentType: Inbound codec and rate that Vobiz sends to your application. Use audio/x-l16;rate=8000 (default), audio/x-l16;rate=16000, or audio/x-mulaw;rate=8000. Vobiz reports the selected format in start.mediaFormat.
  • streamTimeout: Maximum streaming duration in seconds (default: 86400 / 24 hours). When reached, Vobiz stops the stream and (for server-side termination) fires Event=StopStream.
  • keepCallAlive: Set to true to prevent the call from hanging up when the stream ends or encounters an error. Requires bidirectional="true".
  • maxRetries: Reconnect attempts if the WebSocket fails to open or drops mid-stream. Default 0 (disabled), max 10.
  • statusCallbackUrl / extraHeaders: See the full attribute reference on the <Stream> element page.
For the complete attribute table, allowed values, and the HTTP status-callback payloads, see Stream XML element.
<Stream contentType> configures inbound Vobiz-to-application audio. It does not configure the audio your application sends back. For outbound playback, set playAudio.media.contentType and playAudio.media.sampleRate on each playAudio event.

WebSocket Connection

Your WebSocket server must be ready to accept connections from Vobiz. Here’s what the initial connection looks like:

Connection Start Message

Vobiz sends this when the stream starts
This frame fires once, immediately after the WebSocket opens. The call and stream identifiers live inside the nested start object. start.mediaFormat reports the inbound format Vobiz will use for subsequent media events.

Audio Data Messages

Continuous 20 ms audio frames sent during the stream
Vobiz emits approximately 50 media frames per second (one every 20 ms) while the call is active. media.payload contains base64-encoded raw audio in the inbound format declared by start.mediaFormat. Individual media events do not repeat contentType or sampleRate, so initialize your decoder from the start event.

End of stream

When the call ends, the sequence Vobiz sends over the WebSocket is:
  1. The final media frame (no special marker - its shape is identical to every other media frame).
  2. The WebSocket close event - this is the end-of-stream signal.
  3. Out-of-band: the hangup_url HTTP webhook fires with the full Event=Hangup payload (HangupCause, Duration, EndTime, etc).
Handle end of stream from your close handler
End-of-stream triggers include: the caller hanging up, the carrier ending the call, streamTimeout being reached, or your own server sending a stop command.
Vobiz does not send an inbound { "event": "stop" }. The WebSocket simply closes after the final media frame - that is the only in-band signal. If you’re waiting for a stop JSON message on the socket, you’ll wait forever.Event=StopStream on statusCallbackUrl is only delivered when the server initiates the termination via an outbound stop packet (it fires reliably in that case). It does not fire for caller-hangup or mid-stream-kill paths.The authoritative “call is over” signal across all termination paths is the hangup_url HTTP webhook, which fires once with Event=Hangup plus the full hangup payload. Configure it on the REST call-create request.stop does exist as an outbound (Server → Vobiz) command for agent-initiated hangup - see Server-initiated stop on the Stream events page.

Connection Flow

  1. Vobiz receives your XML response containing the Stream element
  2. WebSocket connection established to your specified URL
  3. “start” event sent with call metadata and stream configuration
  4. Continuous “media” events stream audio packets in real-time
  5. Bidirectional streams (optional): Your app can send playAudio events back to Vobiz
  6. WebSocket close - the final media frame is followed by a socket close (no inbound stop event)
  7. hangup_url webhook fires with the authoritative Event=Hangup payload

Reconnects and idempotency

If the WebSocket fails to open or drops mid-stream and you set maxRetries (1-10) on the <Stream> element, Vobiz retries the connection. Each retry is a fresh connection: it opens a new socket and replays a new start event with a new streamId (the callId stays the same). Design your handler to be idempotent across reconnects:
  • Key per-call state on start.callId, not start.streamId, so a reconnect resumes the same logical session.
  • Expect to receive a second start after a drop. Re-send your greeting only if the conversation hadn’t progressed, or resume from saved state.
  • A close you see may be a transient drop that Vobiz will retry, not the end of the call. The authoritative end-of-call signal is the hangup_url Event=Hangup webhook (see below).
With maxRetries="0" (the default), a dropped socket is terminal.

Implementation Examples

Prefer a runnable reference? See the Bun Media Stream Server - a minimal sink-only example that answers a call with <Stream>, records audio to WAV, and logs status callbacks. Drop in your own STT/LLM/TTS pipeline to extend it.

Node.js WebSocket Server

Simple WebSocket server to receive audio

Python WebSocket Handler

Python asyncio WebSocket server

Vobiz XML Response with Stream

Complete example with status callbacks
This example streams both inbound and outbound audio with 8kHz sample rate (Mu-law), includes custom session headers, and sends status updates to your callback URL.

Troubleshooting

Invalid Stream ConfigurationProblem: If your call hangs up with End Of XML Instructions, you likely have an invalid configuration.Solution: The media server does not support audioTrack="both" when bidirectional="true". You must set audioTrack="inbound" (or remove the attribute) for bidirectional streams.