Audio formats and optimization
On this page
Choose the right format for each context
Audio format is one of those settings you rush through at the start and regret later. Yet it determines perceived quality, the bandwidth every listen consumes, and compatibility with your target platform. A podcast delivered as raw PCM blows up your distribution costs, and a phone stream at 24,000 Hz gets transcoded along the way, with all the degradation that comes with it. This lesson reviews the available formats and how to decide between them.
Supported codecs
| Codec | MIME type | Compression | Main use |
|---|---|---|---|
mp3 | audio/mpeg | Lossy | Web, mobile, podcasts |
wav | audio/wav | Lossless | Post-production, archiving |
pcm | audio/pcm | None (raw) | Audio pipelines, Voice Agent |
mulaw | audio/basic | Logarithmic | Telephony (Americas, Japan) |
alaw | audio/alaw | Logarithmic | Telephony (Europe, international) |
MP3 covers most consumer distribution. WAV is for audio that still needs editing or must be kept lossless. PCM is the exchange format of real-time pipelines, including the Voice Agent, because it costs nothing to decode. Mu-law and A-law exist only for telephony and have no reason to show up anywhere else.
Sample rates
The sample rate sets how fine-grained the signal is: the higher it is, the better high frequencies come through, and the bigger the file.
| Sample rate | Quality | Use |
|---|---|---|
| 8,000 Hz | Telephony | VoIP, SIP, G.711 |
| 16,000 Hz | Wideband speech | Transcription, speech recognition |
| 22,050 Hz | FM radio | Podcasts, notifications |
| 24,000 Hz | TTS standard (default) | General use |
| 44,100 Hz | CD audio | Music production, audiobooks |
| 48,000 Hz | Video/broadcast | Post-production, broadcasting |
In practice, three cases settle it. Telephony requires 8,000 Hz, no discussion: that’s what G.711 demands. Web and mobile do fine with the default 24,000 Hz, the best balance between quality and bandwidth for voice. Production work, such as an audiobook or a video soundtrack, justifies 44,100 or 48,000 Hz, because the file will be mixed, normalized, possibly re-encoded, and every step eats away a little quality.
MP3 bit rates
With the MP3 codec, the bit rate sets the compression and therefore the final file size.
| Bit rate | Quality | Size for 1 min |
|---|---|---|
| 32,000 bps | Low | ~240 KB |
| 64,000 bps | Medium | ~480 KB |
| 96,000 bps | Good | ~720 KB |
| 128,000 bps (default) | Very good | ~960 KB |
| 192,000 bps | Excellent | ~1.4 MB |
Speech only occupies a small part of the spectrum: 128 kbps already reproduces it very well, and going up to 192 kbps makes your catalog half again as heavy without any listener hearing the difference on spoken content. Save that top tier for premium productions or musical passages.
Convert audio in Python
The Voice Agent delivers raw, base64-encoded PCM, and two conversions come up in almost every project. The first turns that stream into a numpy array normalized between -1 and 1, the format most signal-processing libraries expect, and goes the other way to send audio back to the API.
import base64
import numpy as np
def base64_to_audio(base64_audio: str) -> np.ndarray:
audio_bytes = base64.b64decode(base64_audio)
audio_int16 = np.frombuffer(audio_bytes, dtype=np.int16)
return audio_int16.astype(np.float32) / 32768.0
def audio_to_base64(audio_data: np.ndarray) -> str:
audio_int16 = (audio_data * 32767).astype(np.int16)
return base64.b64encode(audio_int16.tobytes()).decode("utf-8")
The second wraps PCM in a WAV container. Without that header, an audio player knows neither how many channels nor which sample rate to assume, and it will either refuse the file or play it at the wrong speed.
import wave
def pcm_to_wav(pcm_data: bytes, sample_rate: int = 24000) -> bytes:
import io
buffer = io.BytesIO()
with wave.open(buffer, "wb") as wf:
wf.setnchannels(1)
wf.setsampwidth(2) # 16-bit
wf.setframerate(sample_rate)
wf.writeframes(pcm_data)
return buffer.getvalue()
Optimize for the destination
For a web app, stick with 128 kbps MP3 at 24,000 Hz for TTS and 24,000 Hz PCM for the Voice Agent, which bidirectional streaming requires. Convert your static audio assets, such as jingles and prerecorded messages, to MP3 once and for all instead of serving WAV to every visitor.
For telephony, stay strictly with G.711 at 8,000 Hz and configure the Voice Agent directly in that format: any real-time transcoding adds latency where you have none to spare.
For storage, keep archiving and distribution separate: the master stays in 24,000 Hz WAV, ready to be reworked, and you distribute 128 kbps MP3, which is much lighter. Same content, two files, two purposes.
Manage memory in the browser
During streaming playback, every URL.createObjectURL call reserves memory that the browser doesn’t free on its own. Over a long session, these URLs pile up until the tab slows to a crawl. Revoke the previous one before creating a new one:
let currentBlobUrl = null;
function playAudioChunk(base64Data) {
// Free the previous URL
if (currentBlobUrl) {
URL.revokeObjectURL(currentBlobUrl);
}
const audioBuffer = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0));
const blob = new Blob([audioBuffer], { type: "audio/pcm" });
currentBlobUrl = URL.createObjectURL(blob);
// Play the audio...
}
Interpret TTS error codes
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Audio in the response body |
| 400 | Bad request | Check the text, codec, and sample rate |
| 401 | Unauthorized | Check the API key |
| 429 | Quota exceeded | Implement exponential backoff |
| 500/503 | Server error | Retry with backoff |
400 errors are fixed in your code and won’t go away on their own: they come from an incompatible parameter, typically a sample rate the chosen codec doesn’t accept. 429 and 5xx errors, on the other hand, call for the same response: exponential backoff, with delays that double on each attempt. An immediate retry loop only makes things worse by hammering the quota you just exceeded.
Key takeaways
- Five codecs are available: MP3, WAV, PCM, mu-law, and A-law, each suited to a specific context
- The default sample rate is 24,000 Hz; use 8,000 Hz for telephony and 44,100 Hz or higher for production
- 128 kbps MP3 offers the best quality-to-size trade-off for spoken voice
- Manage Blob URLs in the browser to avoid memory leaks
- Implement exponential backoff to handle 429 (rate limiting) and 5xx errors
Check your understanding
Voice Agent and TTS: voice from end to end, in five questions.
1. How does a Voice Agent session work?
Answer: Over a real-time WebSocket. You configure the session (voice, personality, instructions), then events flow both ways: the user’s audio in one direction, the agent’s spoken replies in the other.
2. What does function calling make possible in voice?
Answer: The voice agent calls your tools mid-conversation to look up an account, make a booking, or take action. Voice becomes a complete interface, not just a dictation machine.
3. What do TTS expressive tags add?
Answer: Control over speech: intonation, pauses, emphasis. Synthesis stops sounding monotone and follows the intent of the text, in every supported language.
4. Why do ephemeral tokens matter?
Answer: They let the client (browser or mobile app) connect to the voice service without exposing your main API key. The credentials are short-lived, scoped to a voice session, and expire on their own, which is what makes real-time voice secure.
5. What do audio formats let you control?
Answer: The trade-off between quality, latency, and bandwidth: choosing the format and sample rate that fit the channel (web, SIP telephony, LiveKit). It’s the optimization that gets you over the finish line.
Session, tools, expressiveness, security, formats: the complete voice assistant in this course brings all five together, and yours will follow the same plan.