Documentation Index
Fetch the complete documentation index at: https://docs.kova.ai/llms.txt
Use this file to discover all available pages before exploring further.
kova-tts is the official Python client for the Kova TTS API. Source: github.com/evalabs-ai/kova-tts-clients.
Install
Requires Python 3.10+.
Initialize
import os
from kova_tts import KovaTTSClient
client = KovaTTSClient(api_key=os.environ["KOVA_API_KEY"])
By default the client targets https://api.kova.ai/v1/tts. Override base_url for staging or self-hosting:
client = KovaTTSClient(
api_key=os.environ["KOVA_API_KEY"],
base_url="https://staging.api.kova.ai/v1/tts",
)
Sync TTS
from kova_tts import AudioResponseFormat
result = client.tts(
text="Hello world.",
voice="cal",
response_format=AudioResponseFormat(encoding="mp3"),
timestamps=True,
)
client.write_audio_file(result.audio, "out.mp3")
if result.timestamps:
print(result.timestamps.words)
result.audio is the decoded audio bytes (bytes), not base64.
Streaming TTS
stream_tts returns an async iterator of events:
import asyncio
from kova_tts import AudioResponseFormat
async def main():
async for event in client.stream_tts(
text="Hello world.",
voice="cal",
response_format=AudioResponseFormat(encoding="mp3"),
timestamps=True,
):
if event.type == "audio":
# event.audio is decoded bytes for this chunk
print(f"audio: {len(event.audio)} bytes")
elif event.type == "timestamps":
print(event.words)
asyncio.run(main())
WebSocket
import asyncio
from kova_tts import AudioResponseFormat
async def main():
async with client.websocket() as ws:
await ws.start_context(
context_id="ctx-1",
voice_id="cal",
model_id="default",
response_format=AudioResponseFormat(encoding="pcm", sample_rate=32000),
)
await ws.send_text("Hello ", context_id="ctx-1")
await ws.send_text("world.", context_id="ctx-1")
await ws.flush(context_id="ctx-1", flush_id="end")
async for frame in ws:
if frame.type == "audio":
print(f"pcm: {len(frame.audio)} bytes")
elif frame.type == "timestamps":
print(frame.timestamps.words)
elif frame.type == "flush_completed" and frame.flush_id == "end":
break
await ws.close_context(context_id="ctx-1")
asyncio.run(main())
Helpers
| Symbol | What it does |
|---|
client.write_audio_file(audio, path) | Write decoded audio bytes to disk (mp3, wav, opus, etc. — the encoded file format). |
client.decode_base64_bytes(value) | Decode a base64 string to raw bytes. Useful if you’re handling stream events manually. |
client.decode_pcm16le_base64(value) | Decode a base64-encoded PCM16-LE chunk to a list[int] of samples. |
kova_tts.write_audio_file(audio, path) | Top-level convenience function — same as the method. |
For raw PCM → WAV file conversion (used in the WebSocket example), use stdlib wave:
import wave
with wave.open("out.wav", "wb") as wf:
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(32000)
wf.writeframes(pcm_bytes)
For listing voices, use raw HTTP — the SDK does not currently expose a list_voices method:
import httpx, os
resp = httpx.get("https://api.kova.ai/v1/tts/speakers",
headers={"x-api-key": os.environ["KOVA_API_KEY"]})
print(resp.json()["speaker_ids"])
Errors
The SDK raises a subclass of KovaTTSError on non-2xx responses. The exception carries the HTTP status and the parsed JSON body:
from kova_tts import KovaTTSClient, KovaTTSError
try:
result = client.tts(text="hi", voice="bad-voice")
except KovaTTSError as e:
print(e.status_code, e.body) # e.g. 422 {'detail': [...]}
See Errors for the full status-code reference.
See also