# Streaming

Receive audio over HTTP as it is generated, including telephony formats.

> HTTP streaming is for text that already exists in full. If the text is still being produced — an LLM writing a reply, for example — use the [WebSocket input-streaming API](https://docs.kenpathlabs.com/input-streaming.md) instead: one connection per turn rather than one request per sentence, and synthesis starts before the sentence ends. It is also what the LiveKit and Pipecat integrations use.

## How it works

Set `stream: true` on `POST /v1/audio/speech` and the server returns audio in a chunked HTTP response as it is generated, rather than buffering the whole clip first. Time to first byte stays flat as the text gets longer, so this is the default worth using for anything beyond a short phrase.

## Formats & latency

`pcm` is the lowest-latency path: headerless 16-bit LE mono at your `sample_rate` (24 kHz default), playable the instant bytes arrive. Compressed formats (`mp3`, `opus`) stream too, but add a little container overhead.

> Negotiate capabilities from `GET /health`: the `engine` and `stream_formats` fields tell you exactly what the current deployment streams. Don’t assume; read it.

## Native & server playback

On native platforms, request `pcm` and write bytes to your audio sink as they arrive; first bytes land in a few hundred milliseconds on GPU serving. Re-align to 2-byte frames across chunk boundaries (a chunk can split a sample).

```python
import pyaudio

pa = pyaudio.PyAudio()
out = pa.open(format=pyaudio.paInt16, channels=1, rate=24000, output=True)

with client.audio.speech.with_streaming_response.create(
    model="svara-1", voice="sv_enhdbrj5", input=text,  # voice: Aanya
    response_format="pcm", extra_body={"stream": True},
) as response:
    tail = b""
    for chunk in response.iter_bytes():
        data = tail + chunk
        n = len(data) - (len(data) % 2)      # whole samples only
        out.write(data[:n]); tail = data[n:]
```

## Telephony

For phone systems, request companded 8 kHz audio directly; no transcoding step in your media server:

- `{ "response_format": "ulaw", "sample_rate": 8000 }`: North American / μ-law
- `{ "response_format": "alaw", "sample_rate": 8000 }`: European / A-law

Resampling runs in-process and scales: 8 kHz streams are cheap, so this fans out to many concurrent calls.
