---
title: "Text to Speech"
description: "Generate Indian-language speech, a block at a time or streamed as the words are written."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.dev.navana.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Text to Speech

Synthesis comes in two modes. They share voices, credentials, and pricing, and
differ in when you get audio back.

- **Non-streaming** — Send a block of text, get the complete audio back in the response, plus its
sample rate and duration in headers.

Best for prompts, notifications, IVR menus, and anything where you already
have the whole text.
- **Streaming** — Open a WebSocket and push text in as it becomes available. Audio chunks
come back as they are generated, so you can start playing the first
sentence before the last one exists.

Best for LLM output, live agents, and anything latency-sensitive.

## Choosing between them

| | Non-streaming | Streaming |
| --- | --- | --- |
| Endpoint | `POST tts.navana.ai/tts/bytes` | `wss://tts.navana.ai/v1` |
| Auth | `X-API-Key` header | `auth_token` in the `hello` frame |
| Input | One block of text | Many text frames over one connection |
| Output | Complete audio buffer | Audio chunks as generated |
| Time to first audio | After the whole text is synthesized | After the first sentence |
| Billed on | Characters of input text | Characters of input text |

**Both modes bill the same way.** Streaming costs nothing extra. It changes
when you receive audio, not what you pay for it. If latency matters, stream.
Characters are counted by Unicode code point, so an Indic script is not
penalised for its encoding.

## The one thing to know about the output

Both modes return **raw audio with no container**. Not a WAV, not an MP3, just
samples. Handing those bytes to an audio player will not work, because nothing
in them says what sample rate they are.

Non-streaming tells you the rate in the `X-Sample-Rate` response header.
Streaming tells you in its `ready` frame. To get a playable file, prepend a
44-byte WAV header, which Python's `wave` module will do for you.

Headerless output is what makes streaming work: chunks concatenate with no
seams and can be fed straight into a live audio sink.

## What you can build

**Speak an LLM's answer as it is generated.** Stream tokens into the synthesis
socket sentence by sentence and play audio while the model is still writing.
That is the difference between a voice product that feels responsive and one
that pauses for several seconds before every reply.

**Localise a product's voice across ten languages.** The same request shape and
the same key work for all of them. Change `lang`, and keep `voice` constant if
you want the same speaker throughout.

**Generate telephony prompts at the right rate.** Synthesize directly at 8 kHz
and skip a resampling step in your call pipeline.

## Languages and voices

Ten languages, with voices that carry across all of them under a single id. See
[Voices and languages](/text-to-speech/voices) for the list and how to find a
voice.

## Start here

- [Non-streaming synthesis](/text-to-speech/non-streaming) — One call, complete audio. The fastest path to a first result.
- [Streaming synthesis](/text-to-speech/streaming) — The WebSocket protocol, frame by frame, with a working client.
- [Voices and languages](/text-to-speech/voices) — All ten languages, and how to find a voice.
- [API reference](/api-reference/synthesize) — Exact parameters, headers, and errors.

Source: https://docs.dev.navana.ai/text-to-speech/index.mdx
