Python SDK for ConvoZen TTS and STT services
Project description
ConvoZen Voice SDK
Text-to-Speech (TTS) and Speech-to-Text (STT) for Python.
One API key for both TTS and STT.
Install
pip install convozen
Requires Python 3.9+
TTS — Convert Text to Speech
Copy and run:
import convozen
client = convozen.Client(api_key="your-api-key")
audio = client.tts.synthesize("नमस्ते… मुझे आपके सर्विस के बारे में थोड़ी जानकारी चाहिए।", language="hi")
with open("output.wav", "wb") as f:
f.write(audio)
With options:
import convozen
client = convozen.Client(api_key="your-api-key")
audio = client.tts.synthesize(
text="Welcome to Playground.",
language="en", # default: "en"
voice="roohi", # default: "roohi"
model="ragini-v1", # default: "ragini-v1"
speed=1.2, # default: 1.0
)
with open("output.wav", "wb") as f:
f.write(audio)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
text |
str |
required | Text to convert to speech |
language |
str |
"en" |
Language code (see supported languages below) |
voice |
str |
"roohi" |
Voice ID for synthesis (see available voices below) |
model |
str |
"ragini-v1" |
TTS model: "ragini-v1" (Indian languages), "ragini-lite" / "ragini_lite" (lightweight Hindi), or "rawi-v1" (Arabic) |
speed |
float |
1.0 |
Speech speed. 0.5 = half speed, 2.0 = double speed. Not applied for ragini_lite. |
sample_rate |
int |
model-dependent | Output sample rate in Hz. Defaults to 22050 for ragini_lite and 24000 for other models |
stream |
bool |
False |
If True, returns audio chunks as they are generated |
format |
str |
"wav" |
Audio output format. Currently only wav is supported |
Streaming
import convozen
client = convozen.Client(api_key="your-api-key")
for chunk in client.tts.synthesize("Long text here...", language="en", stream=True):
audio_player.write(chunk)
Available Voices
| Voice | ID | Default |
|---|---|---|
| Roohi | roohi |
Yes |
| Amaya | amaya |
|
| Kiyansh | kiyansh |
|
| Neeraj | neeraj |
|
| Manya | manya |
|
| Nidhi | nidhi |
|
| Ira | ira |
|
| Trisha | trisha |
|
| Charvi | charvi |
audio = client.tts.synthesize("Hello", language="en", voice="roohi")
Ragini Lite
ragini_lite is the lightweight Ragini backend — a Piper/VITS Hindi voice served
at 22.05 kHz. Use it when you want a smaller, faster Hindi voice.
audio = client.tts.synthesize(
"नमस्ते, आप कैसे हैं?",
language="hi",
model="ragini-lite", # "ragini-lite" and "ragini_lite" both work
)
Both "ragini-lite" (hyphen, matching ragini-v1) and "ragini_lite" (underscore)
are accepted — the SDK normalizes them to the same model.
Supported parameters
| Parameter | Value for ragini_lite |
Notes |
|---|---|---|
text |
any non-empty string | Required |
model |
"ragini-lite" or "ragini_lite" |
Both forms accepted |
language |
"hi", "en" |
Hindi voice |
sample_rate |
int, defaults to 22050 |
When omitted, the SDK sends 22050 (vs 24000 for other models) |
stream |
True / False |
Chunked streaming supported |
format |
"wav" |
Only wav is supported |
Not supported / no effect
| Parameter | Behavior on ragini_lite |
|---|---|
voice |
Single voice only. Defaults to roohi; any other voice ID falls back to roohi. |
speed |
Not applied. Accepted for API compatibility but has no effect on the output. |
Rawi — Arabic TTS
Use model="rawi-v1" for Arabic dialect synthesis:
import convozen
client = convozen.Client(api_key="your-api-key")
audio = client.tts.synthesize(
text="Welcome to Playground.",
language="jo", # Jordanian dialect
voice="hadi",
model="rawi-v1",
speed=1.2,
)
with open("output.wav", "wb") as f:
f.write(audio)
Rawi languages: en, ar, ae, eg, jo, ms, hz, nj
Rawi voices: ahmad, hadi, karim, mohammad, rafoush, ghaida, hana, heba, layan, salma
STT — Convert Speech to Text
Copy and run:
import convozen
client = convozen.Client(api_key="your-api-key")
result = client.stt.transcribe("recording.wav")
print(result.text) # "hello how can I help you"
print(result.score) # -2.45 (confidence — closer to 0 is better)
By default this transcribes mono, single-speaker audio and returns an STTResponse.
Alif — Arabic STT
Use model="alif-v1" for Arabic speech recognition:
import convozen
client = convozen.Client(api_key="your-api-key")
result = client.stt.transcribe(
"arabic_recording.wav",
model="alif-v1",
)
print(result.text) # Arabic transcript
print(result.score) # confidence — closer to 0 is better
Notes for alif-v1:
- Optimized for Arabic audio (all dialects supported by the model)
- Plain transcription only — use
akshara-profor diarization, stereo, or Indian-language STT lang_tagsare not required (the model does not use language-penalty hints)
Word-level timestamps
Timestamps are opt-in — pass word_time_stamps=True:
result = client.stt.transcribe("recording.wav", word_time_stamps=True)
for w in result.word_timestamps:
print(f"{w.word} {w.start_s:.2f}s – {w.end_s:.2f}s")
Works on both the transcript and diarization paths (per-turn timestamps on DiarizeTurn.word_timestamps).
Speaker Diarization (mono)
For a mono recording with multiple speakers, set diarize=True to get a per-speaker breakdown (DiarizeResponse):
result = client.stt.transcribe("call.wav", diarize=True)
for turn in result.turns:
print(f"[{turn.speaker_id}] {turn.start_sec:.1f}s – {turn.end_sec:.1f}s")
print(f" {turn.transcript}")
# [s0] 0.0s – 3.2s
# Hello, this is support. How can I help you?
# [s1] 4.0s – 7.8s
# Hi, I'd like to reschedule my appointment.
If you know how many speakers to expect, pass n_speakers (an integer 2–4) as a hint. Leave it as None (default) to auto-detect:
result = client.stt.transcribe("interview.wav", diarize=True, n_speakers=2)
Response fields (DiarizeResponse):
| Field | Type | Description |
|---|---|---|
turns |
list[DiarizeTurn] |
Speaker turns in order |
num_speakers |
int |
Number of distinct speakers detected |
total_duration_sec |
float |
Total audio duration in seconds |
Each DiarizeTurn has speaker_id, start_sec, end_sec, transcript, and word_timestamps (populated when word_time_stamps=True).
Stereo audio
If each speaker is on a separate channel (e.g. a 2-channel call recording), set audio_channels="stereo". Each channel is treated as one speaker, and you get a DiarizeResponse:
result = client.stt.transcribe("stereo_call.wav", audio_channels="stereo")
For stereo, keep
diarize=False(the channels already are the speakers) and leaven_speakers=None. The declaredaudio_channelsmust match the file — a mono file declared"stereo"(or vice-versa) is rejected with a400.
Denoising
For noisy multi-speaker audio, enable denoise=True. It applies on the diarization path (diarize=True or audio_channels="stereo"):
result = client.stt.transcribe("noisy_call.wav", diarize=True, denoise=True)
Specify Languages
If you know which languages are spoken in the audio, pass them in lang_tags. This improves accuracy — especially for multilingual audio like Hindi + English call recordings:
result = client.stt.transcribe(
"recording.wav",
lang_tags=["hi", "en"],
)
print(result.text) # "हां मुझे appointment reschedule करना है"
Keyword Boosting
Have domain-specific words the model keeps getting wrong? Pass them in keywords and the model will bias towards recognizing them:
# Without keyword boosting: "can you tell me about conversion"
# With keyword boosting: "can you tell me about convozen"
result = client.stt.transcribe(
"recording.wav",
keywords=["convozen", "akshara"],
)
Choose a Model
Use model to select which ASR model processes the audio:
result = client.stt.transcribe("recording.wav", model="akshara-pro") # default
result = client.stt.transcribe("recording.wav", model="akshara-base")
result = client.stt.transcribe("arabic.wav", model="alif-v1") # Arabic STT
| Model | Best for |
|---|---|
akshara-pro |
Maximum accuracy for Indian languages (default) |
akshara-base |
Lighter / faster Indian-language STT |
alif-v1 |
Arabic speech-to-text |
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
audio |
str | os.PathLike |
required | Path to the audio file |
model |
str |
"akshara-pro" |
ASR model: "akshara-pro", "akshara-base", or "alif-v1" (Arabic) |
audio_channels |
str |
"mono" |
"mono" or "stereo". Must match the actual file |
diarize |
bool |
False |
True to return per-speaker turns (mono only) |
n_speakers |
int |
None |
Expected speaker count (2–4) for mono diarization. None → auto-detect |
denoise |
bool |
False |
Apply denoising on the diarization path — helps on noisy audio |
lang_tags |
list[str] |
None |
Languages spoken in the audio — improves accuracy when known |
word_time_stamps |
bool |
False |
True to return per-word timestamps |
blank_penalty |
float |
None |
Penalizes silence/blank tokens; increase to reduce empty gaps. None → derived from lang_tags |
keywords |
list[str] |
None |
Domain words the model should bias towards recognizing |
When to use what
audio_channels |
diarize |
n_speakers |
Result |
|---|---|---|---|
"mono" |
False |
None |
Plain transcript → STTResponse |
"mono" |
True |
None |
Auto speaker count → DiarizeResponse |
"mono" |
True |
2–4 |
Hinted speaker count → DiarizeResponse |
"stereo" |
False |
None |
Channel-split diarization → DiarizeResponse |
Anything outside these rows raises a ValueError (e.g. n_speakers without diarize, n_speakers outside 2–4, diarize=True with "stereo").
Supported Languages
| Code | Language | TTS | STT |
|---|---|---|---|
en |
English | Yes | Yes |
hi |
Hindi | Yes | Yes |
ta |
Tamil | Yes | Yes |
te |
Telugu | Yes | Yes |
kn |
Kannada | Yes | Yes |
ar |
Arabic | Yes (rawi-v1) |
Yes (alif-v1) |
ae |
Emirati Arabic | Yes (rawi-v1) |
Yes (alif-v1) |
eg |
Egyptian Arabic | Yes (rawi-v1) |
Yes (alif-v1) |
jo |
Jordanian Arabic | Yes (rawi-v1) |
Yes (alif-v1) |
ms |
Modern Standard Arabic | Yes (rawi-v1) |
Yes (alif-v1) |
hz |
Hijazi Arabic | Yes (rawi-v1) |
Yes (alif-v1) |
nj |
Najdi Arabic | Yes (rawi-v1) |
Yes (alif-v1) |
mr |
Marathi | — | Yes |
bn |
Bengali | — | Yes |
gu |
Gujarati | — | Yes |
ml |
Malayalam | — | Yes |
Check Credits
import convozen
client = convozen.Client(api_key="your-api-key")
info = client.account.info()
print(info.global_balance) # credits remaining (shared across TTS and STT)
print(info.plan) # e.g. "pro"
print(info.allowed_services) # e.g. ["tts", "stt"]
print(info.tts_lifetime_used) # credits ever spent on TTS
print(info.stt_lifetime_used) # credits ever spent on STT
print(info.rate_limit.limit) # requests allowed per window
print(info.rate_limit.remaining) # requests left in the current window
print(info.rate_limit.reset_in_seconds) # seconds until the window resets
print(info.rate_limit.window_seconds) # length of the window
AccountInfo
| Field | Type | Description |
|---|---|---|
account_id |
str |
Account identifier |
org_id |
str |
Organization identifier |
plan |
str |
Plan tier (e.g. "pro", "free") |
global_balance |
int |
Credits remaining, shared across TTS and STT |
allowed_services |
List[str] |
Services enabled for the key, e.g. ["tts", "stt"] |
tts_lifetime_used |
int |
Credits ever spent on TTS |
stt_lifetime_used |
int |
Credits ever spent on STT |
rate_limit |
RateLimitInfo |
limit, remaining, reset_in_seconds, window_seconds |
Changed: credits are a single
global_balanceshared by TTS and STT. The oldinfo.credits.tts.balance/info.credits.stt.balanceaccessors (and theCredits/CreditBalancetypes) have been removed — they described a schema the server no longer returns and silently reported0.
Error Handling
import convozen
from convozen import AuthenticationError, RateLimitError, APIError
client = convozen.Client(api_key="your-api-key")
try:
audio = client.tts.synthesize("Hello")
except AuthenticationError:
print("Invalid API key")
except RateLimitError:
print("Too many requests")
except APIError as e:
print(f"Server error: {e}")
Standalone Clients
from convozen import TTS, STT
tts = TTS(api_key="your-api-key")
audio = tts.synthesize("Hello", language="hi")
stt = STT(api_key="your-api-key")
# Flat transcript
result = stt.transcribe("recording.wav")
print(result.text)
# Per-speaker diarization (mono, multiple speakers)
result = stt.transcribe("call.wav", diarize=True)
for turn in result.turns:
print(f"[{turn.speaker_id}] {turn.start_sec:.2f}s – {turn.end_sec:.2f}s : {turn.transcript}")
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file convozen-0.4.1.tar.gz.
File metadata
- Download URL: convozen-0.4.1.tar.gz
- Upload date:
- Size: 18.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d925c5e5e60fdf3db45ba139b3518039a68a4266643f1bb07c7b692a17045f05
|
|
| MD5 |
0dc61799b1dc124611f7ff6f8beb4c3d
|
|
| BLAKE2b-256 |
ea0959ab4e4179234eb15725b4f06828dc089bd6612d8e5fff2f2f7545d7955b
|
File details
Details for the file convozen-0.4.1-py3-none-any.whl.
File metadata
- Download URL: convozen-0.4.1-py3-none-any.whl
- Upload date:
- Size: 22.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78f654e5c48053ba021b28d6681e6ccf2b86e07cb824447d5d0541155a19d7c6
|
|
| MD5 |
bbe242a41b43d95518257f8333c5749b
|
|
| BLAKE2b-256 |
8e97ce2295778b6ffd4158008862c37959a3b58454e613677c54ab0017da1a98
|