Technical guide

How WAV audio becomes Twilio Media Streams audio

See how IVRReady converts WAV source audio into headerless 8 kHz mono audio/x-mulaw, base64 media.payload, and a runtime Stream SID template.

By IVRReady · Published August 28, 2026 · Last updated August 28, 2026

Direct answer

Outbound bidirectional Twilio Media Streams media.payload is not a WAV file. It is base64-encoded raw audio/x-mulaw at 8,000 Hz and one channel. When the source is already a μ-law WAV, its RIFF/WAVE container bytes must still be removed; only the audio bytes inside the inspected data chunk become the payload.

Source WAV versus delivered payload

Source RIFF/WAVE
├─ RIFF size + WAVE form
├─ fmt  chunk
├─ optional chunks and padding
└─ data header
   └─ [ μ-law audio bytes ]

Twilio media.payload
= base64([ μ-law audio bytes ])

The headerless .ulaw artifact and the JSON template are developer assets. IVRReady does not open a WebSocket or send them to Twilio.

Why slice(44) is unsafe

Forty-four bytes is only one common minimal WAV layout. Real RIFF files can place extra chunks before audio, use odd-sized chunks with padding, or carry larger format structures. IVRReady first validates the RIFF chunk graph, then uses the parser’s proven dataOffset and dataSize bounds. It copies exactly that region and never scans arbitrary bytes for a convenient data string.

Two source paths, one proven payload

Canonical source: zero FFmpeg

8 kHz mono μ-law WAV → structural verification → exact data-chunk extraction → raw .ulaw → base64 → media template. No audio transcoding occurs.

Noncanonical verified source

For example, 48 kHz stereo PCM WAV → browser-local FFmpeg correction → generated WAV reinspection → 0x0007 / 8 kHz / mono proof → exact extraction → payload.

Base64 overhead and the browser envelope

Base64 length is exactly 4 × ceil(raw bytes / 3), so it expands raw media by roughly one third before the JSON envelope is counted. Twilio’s documentation says a payload can be any size; that is a protocol statement, not unlimited browser memory. IVRReady keeps encoding chunks bounded, yields cooperatively during large payloads so cancellation remains responsive, and has exercised raw payloads through 30 MiB on its documented release test host. That measurement is not a Twilio maximum.

One prepared payload versus runtime chunking

IVRReady creates one payload per source. The cited outbound contract does not impose an invented 20 ms or 160-byte message requirement. A runtime application may still choose smaller messages for its own buffering, interruption, or scheduling design; that is an application optimization, not an IVRReady compatibility rule.

The runtime Stream SID

{
  "event": "media",
  "streamSid": "MZ_REPLACE_AT_RUNTIME",
  "media": {
    "payload": "<base64 μ-law payload>"
  }
}

The developer’s application replaces the placeholder with the active Stream SID it received at runtime. Twilio also documents mark messages for completion feedback and clear for buffered media control; those are runtime WebSocket responsibilities and IVRReady does not implement them.

Prepare WAV source locally

Use the Twilio Media Streams audio preparer, review G.711 μ-law WAV fundamentals, or compare the six target contracts.

Sources and evidence

Vendor-specific statements follow IVRReady’s executable target profiles and their recorded official evidence. Technical context uses the primary sources below.

  • Media Streams — WebSocket Messages

    Outbound bidirectional media-message shape, μ-law/8000 base64 payload, any-size wording, buffering, header prohibition, and mark guidance. Last verified 2026-08-28.

  • Media Streams Overview

    Bidirectional stream directionality and application-to-Twilio playback scope. Last verified 2026-08-28.

  • TwiML Voice: <Stream>

    <Connect><Stream> bidirectional behavior and WebSocket runtime boundary. Last verified 2026-08-28.