Metadata-Version: 2.4
Name: vakyamai
Version: 0.1.0
Summary: Python SDK for the Vakyam Text-to-Speech API
Author: Vakyam AI
License: MIT
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.27
Requires-Dist: websockets<16,>=12
Provides-Extra: dev
Requires-Dist: bandit[toml]<2,>=1.9.4; extra == 'dev'
Requires-Dist: pip-audit<3,>=2.10; extra == 'dev'
Requires-Dist: pytest<10,>=9.0.3; extra == 'dev'
Requires-Dist: ruff<1,>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# VakyamAI Python SDK

Python SDK for the Vakyam Text-to-Speech API.

This package intentionally exposes only the public TTS API surface:

- `GET /v1/voices`
- `POST /v1/tts/generate`
- `POST /v1/tts/stream`
- `WS /v1/tts/websocket`

API-key management and health endpoints are server/dashboard concerns and are not included.

## Install

```bash
pip install vakyamai
```

For local development from this repository:

```bash
pip install -e ".[dev]"
```

## Examples

All examples use the production API URL by default. Set your API key first:

```bash
export VAKYAM_API_KEY="vak_live_..."
```

Then run:

```bash
python examples/env_key_usage.py
python examples/synthesize.py
python examples/error_handling.py
python examples/async_streaming.py
python examples/async_websocket.py
```

Available examples:

- [env_key_usage.py](examples/env_key_usage.py): create a client from `VAKYAM_API_KEY`
- [synthesize.py](examples/synthesize.py): generate an MP3 file from text
- [error_handling.py](examples/error_handling.py): handle typed SDK/API errors
- [async_streaming.py](examples/async_streaming.py): stream PCM bytes asynchronously
- [async_websocket.py](examples/async_websocket.py): synthesize one sentence over async WebSocket

## Initialize

```python
from vakyamai import VakyamAI

Vakyam = VakyamAI(
    api_key="vak_live_...",
    base_url="http://127.0.0.1:8000",  # omit for production
)
```

For safety, `http://` base URLs are accepted only for localhost by default. Use
`allow_insecure_base_url=True` only on trusted development networks.

By default, the SDK reads configuration from the environment:

```bash
export VAKYAM_API_KEY="vak_live_..."
```

Then create the client without arguments:

```python
from vakyamai import VakyamAI

Vakyam = VakyamAI()
```

Precedence:

- `api_key=` passed in code overrides `VAKYAM_API_KEY`
- the SDK uses `https://api.vakyam.ai` by default
- `base_url=` is available only as an explicit development/test override

## List Voices

```python
voices = Vakyam.voices.list(group_by="language")
print(voices)
```

Use the returned `voice_name` and language code in synthesis requests.

## Generate Speech

```python
response = Vakyam.tts.generate(
    text="வணக்கம், நான் வாக்யம் AI பேசுகிறேன்.",
    model_id="raaga-v1",
    voice_name="Meera",
    language="ta-IN",
    output_format="mp3",
    sample_rate=24000,
    speed=1.0,
    voice_strength=2.0,
)

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

`response.audio` contains decoded audio bytes. `response.audio_base64` preserves the raw API field.
`sample_rate` accepts `8000`, `16000`, `24000`, or `48000`; the default is `24000`.
`voice_strength` controls voice conditioning strength from `1.0` to `3.0`; the default is `2.0`.
Supported languages are `ta-IN`, `hi-IN`, `mr-IN`, `te-IN`, `en-IN`, `gu-IN`, `bn-IN`, and `kn-IN`.
Supported output formats are `mp3`, `wav`, `pcm`, and `mulaw`.

## HTTP Streaming

```python
with open("speech.pcm", "wb") as file:
    for chunk in Vakyam.tts.stream(
        text="வணக்கம்.",
        model_id="raaga-v1",
        voice_name="Meera",
        language="ta-IN",
        output_format="pcm",
        sample_rate=24000,
        voice_strength=2.0,
    ):
        file.write(chunk)
```

To collect the full stream and response metadata:

```python
streamed = Vakyam.tts.stream_to_bytes(
    text="வணக்கம்.",
    model_id="raaga-v1",
    voice_name="Meera",
    language="ta-IN",
    sample_rate=24000,
    voice_strength=2.0,
)

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

Async streaming is available through `AsyncVakyamAI`:

```python
from vakyamai import AsyncVakyamAI

async with AsyncVakyamAI() as Vakyam:
    async for chunk in Vakyam.tts.stream(
        text="வணக்கம்.",
        model_id="raaga-v1",
        voice_name="Meera",
        language="ta-IN",
        output_format="pcm",
        sample_rate=24000,
        voice_strength=2.0,
    ):
        ...
```

`AsyncVakyamAI` is intentionally focused on streaming APIs. Use `VakyamAI` for
`voices.list()` and non-streaming `tts.generate()`.

## WebSocket

```python
with Vakyam.tts.websocket(
    model_id="raaga-v1",
    voice_name="Meera",
    language="ta-IN",
    output_format="pcm",
    sample_rate=24000,
    voice_strength=2.0,
) as ws:
    result = ws.synthesize("நான் சரியாக இருக்கிறேன்.")
    result.save("sentence.pcm")
```

The WebSocket API expects one complete sentence or utterance at a time.
Idle WebSocket sessions close after 60 seconds without an incoming message by
default. Calling `ws.ping()` sends a client ping and resets the server idle timer.

Async WebSocket usage:

```python
from vakyamai import AsyncVakyamAI

async with AsyncVakyamAI() as Vakyam:
    async with Vakyam.tts.websocket(
        model_id="raaga-v1",
        voice_name="Meera",
        language="ta-IN",
        output_format="pcm",
        sample_rate=24000,
        voice_strength=2.0,
    ) as ws:
        result = await ws.synthesize("நான் சரியாக இருக்கிறேன்.")
        result.save("sentence.pcm")
```

## Errors

The SDK maps the API error envelope into typed exceptions:

```python
from vakyamai import RateLimitError, ValidationError

try:
    Vakyam.tts.generate(
        text="...",
        model_id="raaga-v1",
        voice_name="Meera",
        language="ta-IN",
        sample_rate=24000,
        voice_strength=2.0,
    )
except RateLimitError as exc:
    print(exc.retry_after_seconds)
except ValidationError as exc:
    print(exc.code, exc.message)
```

Common exception classes:

- `AuthenticationError`
- `InsufficientCreditsError`
- `ConcurrencyLimitError`
- `RateLimitError`
- `ServiceUnavailableError`
- `ValidationError`
- `APIError`
- `APIConnectionError`
