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

# Voices

> Name a voice with voice_id in the SDKs and on the wire, where to find voices, the ones to start with, and how voice and language fit together.

Every voice is named by its voice ID: the `voice_id` parameter on a WebSocket session and on an HTTP request, `voice_id` in the Python SDK's `TTSConfig`, and `voiceId` on a JavaScript SDK session (`voice_id` in its HTTP requests, which take the API's field names). It takes one of these:

* The library slug of an AssemblyAI voice, such as `aai-jane`.
* A voice's ID, a UUID such as `49c443a4-8a1d-5f7e-b70b-98bdbd9823c3`.
* The slug of one of your account's voices, such as a voice you [cloned](https://assemblyai.com/docs/tts/cloned-voices.md) in the AssemblyAI dashboard.

Leave `voice_id` out and you get `aai-jane`, the default voice, which speaks English. For text in another language, name a voice recorded in that language.

**Python SDK**

```python theme={null}
import assemblyai as aai

config = aai.TTSConfig(voice_id="aai-sara")

with aai.TTSSession(config) as session:  # the WebSocket API
    for chunk in session.speak("Hi, thanks for calling."):
        play(chunk)
    print(session.begin.configuration["voice_id"])

response = aai.TextToSpeech(config=config).synthesize("Hi, thanks for calling.")  # the HTTP API
print(response.voice_id)
```

The SDK reads your API key from `ASSEMBLYAI_API_KEY`, or from `aai.settings.api_key`.

**JavaScript SDK**

```javascript theme={null}
import { AssemblyAI } from "assemblyai";

const client = new AssemblyAI({ apiKey: process.env.ASSEMBLYAI_API_KEY });

const session = client.tts.session({ voiceId: "aai-sara" }); // the WebSocket API
const begin = await session.connect();
for await (const chunk of session.speak("Hi, thanks for calling.")) play(chunk);
await session.close();
console.log(begin.configuration.voice_id);

const response = await client.tts.synthesize({ text: "Hi, thanks for calling.", voice_id: "aai-sara" }); // the HTTP API
console.log(response.voiceId);
```

**Without an SDK**

On the WebSocket API, `voice_id` is a query parameter of the URL you open; on the HTTP API, a field of the request body:

```text theme={null}
wss://tts.us.assemblyai.com/v1/ws?voice_id=aai-sara&sample_rate=24000&encoding=pcm_s16le
```

```bash theme={null}
curl -sS --fail-with-body https://tts.us.assemblyai.com/v1/speech \
  -H "Authorization: $ASSEMBLYAI_API_KEY" \
  -d '{"text": "Hi, thanks for calling.", "voice_id": "aai-sara", "container": "wav"}' \
  -o sara.wav
```

The session or request echoes the voice it speaks with: `Begin.configuration.voice_id` on a session, which the SDKs expose on the `Begin` event, and the `X-TTS-Voice-Id` header on an HTTP response, which the SDKs expose on the result. It is the value you sent, or `aai-jane` when you sent none. On a session, `Begin.configuration.resolved_voice.voice_id` gives the voice's UUID, also when you named it by slug.

## AssemblyAI voices

The [voice catalog](https://www.assemblyai.com/dashboard/text-to-speech/voices) in the AssemblyAI dashboard holds thousands of voices across the six languages the model speaks. Browse it there, listen to each voice, and copy its `voice_id` with **Copy voice ID**; the text-to-speech playground has the same action, which copies the `voice_id` its session sends. AssemblyAI's voices carry slugs that begin with `aai-`. Each voice speaks one language, the language it was recorded in, so pick a voice in the language of your text.

These are good voices to start with. The examples on these pages use Audrey:

| Voice | `voice_id` | Language | Description |
| - | - | - | - |
| Aaliyah | `aai-aaliyah` | English, American | Young woman speaking American English with a fairly high-pitched voice |
| Abdiel | `aai-abdiel` | English | An older man speaking English with a breathy voice |
| Annabelle | `aai-annabelle` | English, American | A young woman with a high-pitched voice speaking American English |
| April | `aai-april` | English, American | A young woman speaking American English at a fast pace |
| Audrey | `aai-audrey` | English, American | A middle-aged woman with an even, steady intonation speaks American English |
| Buford | `aai-buford` | English, British | An older man speaking British English with an energetic delivery |
| Carrie | `aai-carrie` | English, British | A middle-aged woman with a soft-spoken delivery in British English |
| Cloyd | `aai-cloyd` | English, British | An older man with a high-pitched, fast-paced, energetic delivery in British English |
| Dorsey | `aai-dorsey` | English | An older man's voice with a raspy, textured, nasal, and breathy quality |
| Ernest | `aai-ernest` | English, American | A middle-aged man speaking fast-paced American English with a high-pitched voice |
| Ewald | `aai-ewald` | English, American | A middle-aged man speaking American English at a fairly fast pace |
| Gunnar | `aai-gunnar` | English | An older man speaking English at a fairly slow pace |
| Hailey | `aai-hailey` | English, American | A young woman speaking American English at a fairly fast pace |
| Kyla | `aai-kyla` | English, American | A young woman speaking American English at a fast pace |
| Lilla | `aai-lilla` | English, British | A middle-aged woman with energetic delivery and a nasal, expressive intonation in British English |
| Nancy | `aai-nancy` | English, British | A middle-aged woman speaking British English with a fairly even tone |
| Percival | `aai-percival` | English, British | An older man with energetic delivery and expressive intonation, speaking British English in a breathy manner |
| Peter | `aai-peter` | English, American | A middle-aged man with a soft-spoken delivery in American English |
| Sara | `aai-sara` | English, American | A young woman speaking American English with an even, steady intonation |
| Steven | `aai-steven` | English, Australian | A middle-aged man speaking Australian English with a fairly even tone |
| Titus | `aai-titus` | English, American | A young man with a deep, low-pitched voice speaking American English |
| Troy | `aai-troy` | English, Scottish | A young man with a soft-spoken, deep, low-pitched voice and expressive intonation in Scottish English |
| Yasmin | `aai-yasmin` | English, British | A middle-aged woman with expressive intonation speaks British English |
| Antonio Luis | `aai-antonioluis` | Spanish, Mexican | A deep, low-pitched voice of a middle-aged man speaking Mexican Spanish |
| Constanza | `aai-constanza` | Spanish, Mexican | A young woman speaking Mexican Spanish with an even, steady intonation |
| Malvina | `aai-malvina` | Spanish, Mexican | A soft-spoken middle-aged woman speaking Mexican Spanish |
| Oriol | `aai-oriol` | Spanish, Mexican | A middle-aged man speaking Mexican Spanish at a fairly fast pace |
| Günther | `aai-gunther` | German | A middle-aged man speaking German with expressive intonation and a soft-spoken delivery |
| Jörg | `aai-jorg` | German | A middle-aged man speaking German with a fairly even tone |
| Magdalena | `aai-magdalena` | German | A young woman with a deep, low-pitched voice speaking German |
| Donatien | `aai-donatien` | French | A middle-aged man with a high-pitched, soft-spoken voice and expressive intonation |
| Benício | `aai-benicio` | Portuguese | A young man speaking Portuguese with a balanced, natural, easy-to-listen-to voice |

A voice you [clone](https://assemblyai.com/docs/tts/cloned-voices.md#language-and-model) likewise speaks only the language of its recording.

## Voice and language

`language` defaults to `english`, and it decides which model the session runs on: the default model of that language in the region, `assemblyai-tts-1` for all six languages. Each voice speaks one language, the language it was recorded in, so set `language` to the language of the text you send and name a voice recorded in it, such as Constanza for Mexican Spanish.

**Python SDK**

```python theme={null}
# selected_voice_id comes from your voice picker; text_language is the
# language of the text you will send.
config = aai.TTSConfig(voice_id=selected_voice_id, language=text_language)
```

**JavaScript SDK**

```javascript theme={null}
// selectedVoiceId comes from your voice picker; textLanguage is the
// language of the text you will send.
const session = client.tts.session({ voiceId: selectedVoiceId, language: textLanguage });
const response = await client.tts.synthesize({ text, voice_id: selectedVoiceId, language: textLanguage });
```

**Without an SDK**

```javascript theme={null}
// Fragment: selectedVoiceId comes from your voice picker, and textLanguage is
// the language of the text you will send.
const params = new URLSearchParams({
  voice_id: selectedVoiceId,
  language: textLanguage,
  sample_rate: "24000",
  encoding: "pcm_s16le",
});
```

With a [cloned voice](https://assemblyai.com/docs/tts/cloned-voices.md), leave `language` out and the session speaks the voice's language; another `language` closes the session with `3006` before `Begin`. See [Language and model](https://assemblyai.com/docs/tts/cloned-voices.md#language-and-model).

`language` takes the full English name of the language, such as `spanish`, not a code such as `es`. This differs from the STT APIs, which take short language codes such as `es` or `en_us`. The [OpenAI-compatible route](https://assemblyai.com/docs/tts/openai-compatibility.md#extensions) and the [LiveKit plugin](https://assemblyai.com/docs/tts/livekit.md#set-the-language) accept an ISO 639-1 code such as `es` as well.

> [!WARNING]
>
> The API does not detect language. Set `language` to the language of your
> text: with an AssemblyAI voice it is `english` unless you set it, whatever
> language the text is in.

## Languages

`language` takes one of these values:

| Language | `language` value |
| - | - |
| English | `english` |
| Spanish | `spanish` |
| German | `german` |
| Italian | `italian` |
| Portuguese | `portuguese` |
| French | `french` |

A session speaks a language only where a model of the region speaks it. Both data zones serve all six languages on one model, `assemblyai-tts-1`, the default model of each of them, and `Begin.configuration.model` names the model a session runs on. A `language` outside this table closes the session with `3006` before `Begin`, with `error_type` `invalid_parameter` and `param` `language`, and the text lists the supported values. A supported language that no model of the region speaks closes with `3006`, `error_type` `invalid_request`, `param` `language` and the text `No voice model serves language <language> in this region`.

## What a wrong voice looks like

The server checks the voice when the session opens. A voice it cannot use never gets `Begin`: an `Error` frame arrives in its place, and the socket closes with the frame's `error_code`. The Python SDK raises it as `TTSError` from the `with` block, the JavaScript SDK rejects `connect()` with a `TextToSpeechError`; both carry the frame's `error_type` as `error_code` (`errorCode`) and its `param`. On the HTTP API the same refusals are `422` answers with the same codes, which the SDKs raise from `synthesize()` and `stream()`.

* **No voice with this `voice_id`.** A `voice_id` that names no voice your account can use on this host closes the session with `3012`, `error_type` `voice_not_found` and `param` `voice_id`. A bare name such as `voice_id=jane` is not a library slug: it is looked up among the slugs of your own voices, and unless one of your voices has that slug, it is not found either, with a message that ends `Did you mean voice_id=aai-jane?`. Send `aai-jane`.
* **A voice the session's model does not speak.** An AssemblyAI voice that the session's model does not speak in the session's language closes the session with `3006`, `error_type` `invalid_request` and `param` `voice_id`, and the message lists the voices available on that connection by their slugs.

With a `voice_id` that names no voice (`voice_id=aai-nonexistent`):

```json theme={null}
{
  "type": "Error",
  "error_code": 3012,
  "error": "The requested voice was not found. It may not exist, may have been deleted, or may be another account's private voice.",
  "error_type": "voice_not_found",
  "retryable": false,
  "param": "voice_id",
  "retry_after_seconds": null
}
```

Fix the voice before you reconnect; retrying unchanged fails identically. Keep handling a `3006` whose `param` is `voice_id` after `Begin` as well: in rare cases the refusal of a voice the model does not speak arrives right after `Begin`, with the same text, before any audio. Read `configuration.voice_id` and `configuration.language` from `Begin` to confirm what the session resolved, defaults included. See [Error handling](https://assemblyai.com/docs/tts/error-handling.md).

## Related

* [Voice cloning](https://assemblyai.com/docs/tts/cloned-voices.md): a voice you clone in the AssemblyAI dashboard, named by its `voice_id`.
* [WebSocket API basics](https://assemblyai.com/docs/tts/connect-parameters.md): the connect sequence and the rules for the rest of the query string.
* [Error handling](https://assemblyai.com/docs/tts/error-handling.md): what to do with `3006`, `3012` and the other close codes.
* [Quickstart](https://assemblyai.com/docs/tts/getting-started/quickstart.md): a full session using Audrey.
