> Agent-readable docs index: /llms.txt. Download /docs.zip to grep all markdown files locally.

---
title: Python SDK
description: Install and use the Vakyam Python SDK.
---

# Python SDK

The official Python SDK (`vakyamai`) wraps the public TTS API: listing voices,
synthesizing speech, HTTP streaming, and realtime WebSocket synthesis.

## Install

```bash
pip install vakyamai
```

Requires Python 3.10+. The `websockets` package is installed automatically and
is used for realtime synthesis.

## Create a client

The client reads `VAKYAM_API_KEY` from the environment by default:

```python
from vakyamai import VakyamAI

client = VakyamAI()
```

You can also pass the key explicitly:

```python
client = VakyamAI(api_key="vak_live_...")
```

Precedence: an `api_key=` argument overrides `VAKYAM_API_KEY`.

The client supports use as a context manager:

```python
with VakyamAI() as client:
    ...
```

For streaming and realtime WebSocket synthesis, an async client
`AsyncVakyamAI` is also available — use it with `async with` and `await`:

```python
from vakyamai import AsyncVakyamAI

async with AsyncVakyamAI() as client:
    ...
```

## List voices

```python
voices = client.voices.list(group_by="language")  # or group_by="voice"
```

## Generate speech

```python
response = client.tts.generate(
    text="வணக்கம், நான் வாக்யம் AI பேசுகிறேன்.",
    model_id="raaga-v1",
    voice="Archana",
    language="ta-IN",
    output_format="mp3",   # mp3 | wav | pcm | mulaw, default mp3
    sample_rate=24000,     # 8000 | 16000 | 24000 | 48000, default 24000
    speed=1.0,             # 0.5 - 2.0, default 1.0
)

response.save("speech.mp3")
print(response.duration_seconds, response.characters_used)
```

All arguments are keyword-only. `output_format`, `sample_rate`, and `speed`
are optional and are also accepted by `stream`,
`stream_to_bytes`, and `websocket`.

> **Note:**
> `voice` accepts a **preset name** (e.g. `"Archana"`) or a **custom voice ID**
> beginning with `vc_` (e.g. `voice="vc_01EXAMPLE"`).

The returned `SpeechResponse` exposes:

| Attribute          | Type    | Description                        |
| ------------------ | ------- | ---------------------------------- |
| `audio`            | `bytes` | Decoded audio bytes.               |
| `audio_base64`     | `str`   | The raw base64 field from the API. |
| `format`           | `str`   | Output format of the audio.        |
| `duration_seconds` | `float` | Duration of the audio.             |
| `characters_used`  | `int`   | Credits consumed.                  |
| `save(path)`       | method  | Write `audio` to a file.           |

## HTTP streaming

Iterate over raw byte chunks:

```python
with open("speech.pcm", "wb") as file:
    for chunk in client.tts.stream(
        text="வணக்கம்.",
        model_id="raaga-v1",
        voice="Archana",
        language="ta-IN",
        output_format="pcm",
    ):
        file.write(chunk)
```

Or collect the full stream plus metadata in one call:

```python
streamed = client.tts.stream_to_bytes(
    text="வணக்கம்.",
    model_id="raaga-v1",
    voice="Archana",
    language="ta-IN",
)

streamed.save("speech.pcm")
print(streamed.metadata.characters_used)
```

## WebSocket

The session config (model, voice, language, format, speed) is sent **before** any
text — `websocket(...)` opens the connection and sends the `config` message on
entry, so every `synthesize` call after it uses that config.

```python
# Opens the connection and sends the config message first
with client.tts.websocket(
    model_id="raaga-v1",
    voice="Archana",
    language="ta-IN",
    output_format="pcm",
) as ws:
    # Then send text — one complete sentence per call
    result = ws.synthesize("நான் சரியாக இருக்கிறேன்.")
    result.save("sentence.pcm")
```

Send one complete sentence per `synthesize` call. See the
[realtime guide](/guides/realtime-websocket).

`synthesize` returns a `WebSocketSpeechResult` with `audio` (bytes),
`characters_used`, `duration_seconds`, `truncated`, `truncation_reason`,
`cancelled`, and a `save(path)` method.

### Interrupting an utterance (barge-in)

Call `ws.cancel()` to interrupt the current utterance. It sends a `cancel`,
drains any remaining audio, and returns the terminal `WebSocketSpeechResult`
(with `cancelled=True`). It is safe to call `cancel()` from another thread while
`synthesize()` is running; you are billed only for audio produced before the
cancel.

```python
result = ws.cancel()
print(result.cancelled, result.characters_used)
```

The server closes idle connections after 60 seconds without an incoming message.
The SDK sends a keepalive ping while the session is open; you can also ping
explicitly between utterances, which resets the server's idle timer:

```python
ws.ping()
```

## Error handling

The SDK maps the API error envelope into typed exceptions:

```python
from vakyamai import RateLimitError, ValidationError

try:
    client.tts.generate(
        text="...",
        model_id="raaga-v1",
        voice="Archana",
        language="ta-IN",
    )
except RateLimitError as exc:
    print("retry after", exc.retry_after_seconds)
except ValidationError as exc:
    print(exc.code, exc.message)
```

Available exception classes:

* `AuthenticationError`
* `InsufficientCreditsError`
* `ConcurrencyLimitError` — too many concurrent synthesis requests for the account
* `RateLimitError` — exposes `retry_after_seconds`
* `ValidationError`
* `ServiceUnavailableError` — no worker was available to synthesize (HTTP 503)
* `APIError` — base for API responses, exposes `status_code`, `code`, `message`
* `APIConnectionError` — raised when the API cannot be reached

---

*Powered by [holocron.so](https://holocron.so)*
