Skip to main content

FonadaLabs SDK

License: MIT Python 3.9+ Version 3.0.0

Unified Python SDK for FonadaLabs Text-to-Speech (TTS), Automatic Speech Recognition (ASR), and Audio Denoising APIs.

Table of Contents

Features

Text-to-Speech (TTS)

  • 🎙️ Voice-clone speech with klone_v2_flash (default) and klone_v2_pro
  • 🗂️ Catalog voices via share_id (enterprise: your own audio_url / audio)
  • 🔊 Flash streaming over HTTPS and WebSocket (pcm, wav, mp3, opus, mulaw, alaw)
  • 🌍 Multi-language support (Hindi, English, Telugu, Tamil, and more)
  • ⚡ Async support for concurrent requests
  • 🔒 Secure API key authentication
  • ⚠️ Built-in error handling for rate limits and credit exhaustion

Automatic Speech Recognition (ASR)

  • 🎤 Audio file transcription with ASR v3 (long audio, chunked server-side)
  • 🔄 Concurrent batch processing
  • 🌍 Multi-language support (validated by the API)
  • 🔒 Secure API key authentication
  • ⚠️ Comprehensive error handling

Audio Denoising

  • 🔇 High-quality audio denoising (DeepFilterNet + CMGAN)
  • 🎯 Full audio and streaming chunk processing
  • ⚡ Real-time WebSocket streaming with progress callbacks
  • 📦 Batch processing support
  • 🔒 Secure API key authentication
  • ⚠️ Built-in rate limit and credit management

Installation

# Install with all dependencies for TTS, ASR, and Denoise
pip install fonadalabs

Note for Windows users: Make sure you have Python 3.9-3.12 and upgraded pip:

python -m pip install --upgrade pip setuptools wheel
pip install fonadalabs

From Source (Development)

git clone https://github.com/fonadalabs/fonadalabs-sdk.git
cd fonadalabs-sdk
pip install -e .

For Development

# Install with development tools (pytest, black, etc.)
pip install fonadalabs[dev]

Quick Start

Text-to-Speech (TTS)

from fonadalabs import TTSClient, TTSError, CreditsExhaustedError, RateLimitError

# Initialize with API key (or set FONADALABS_API_KEY env variable)
client = TTSClient(api_key="your-api-key-here")

try:
    # Generate audio (model="klone_v2_flash" by default) with a catalog voice
    audio_data = client.generate_audio(
        text="नमस्ते! यह FonadaLabs TTS SDK का परीक्षण है।",
        language="Hindi",
        share_id="catalog-share-id",
        output_file="output.wav"
    )
    print(f"✓ Generated {len(audio_data)} bytes")
    
except CreditsExhaustedError as e:
    print(f"⚠️ API credits exhausted. Balance: {e.remaining_balance}")
except RateLimitError as e:
    print(f"⚠️ Rate limit exceeded. Retry after: {e.retry_after_seconds}s")
except TTSError as e:
    print(f"❌ TTS Error: {e}")

Automatic Speech Recognition (ASR)

from fonadalabs import (
    ASRClient, 
    ASRSDKError,
    AuthenticationError,
    ASRCreditsExhaustedError,
    ASRRateLimitError,
)

# Initialize with API key (or set FONADALABS_API_KEY env variable)
asr_client = ASRClient(api_key="your-api-key-here")

try:
    # Transcribe audio file (model="v3" by default, POST /v3/asr/transcribe)
    result = asr_client.transcribe_file(
        "audio.wav",
        language_id="hi",
    )
    print(f"✓ Transcription: {result.text}")
    print(f"✓ Language: {result.language_id}")
    print(f"✓ Credits: {result.credits_used}")
    print(f"✓ Duration: {result.audio_duration_s}s")
    
except ASRCreditsExhaustedError as e:
    print(f"⚠️ API credits exhausted. Usage: {e.current_usage}")
except ASRRateLimitError as e:
    print(f"⚠️ Rate limit exceeded. Retry after: {e.retry_after_seconds}s")
except AuthenticationError as e:
    print(f"❌ Authentication failed: {e}")
except ASRSDKError as e:
    print(f"❌ ASR Error: {e}")

Audio Denoising

from fonadalabs import (
    DenoiseHttpClient, 
    DenoiseStreamingClient,
    DenoiseCreditsExhaustedError,
    DenoiseRateLimitError
)

try:
    # Full audio denoising (HTTP)
    http_client = DenoiseHttpClient(api_key="your-api-key-here")
    denoised = http_client.denoise_file("noisy.wav", "clean.wav")
    print("✓ Denoised audio saved to clean.wav")
    
    # Streaming denoising with progress
    streaming_client = DenoiseStreamingClient(api_key="your-api-key-here")
    
    def progress_callback(current, total):
        percent = (current / total) * 100
        print(f"Progress: {current}/{total} chunks ({percent:.1f}%)")
    
    denoised = streaming_client.denoise_file(
        "noisy.wav", 
        "clean.wav",
        progress_callback=progress_callback
    )
    print("✓ Streaming denoising complete!")
    
except DenoiseCreditsExhaustedError:
    print("⚠️ API credits exhausted. Please add more credits.")
except DenoiseRateLimitError:
    print("⚠️ Rate limit exceeded. Please try again later.")
except Exception as e:
    print(f"❌ Denoise Error: {e}")

Authentication

All FonadaLabs APIs require API key authentication. You can obtain your API key from the FonadaLabs Dashboard.

# Set environment variable
export FONADALABS_API_KEY=your-api-key-here

# Or add to .env file
echo "FONADALABS_API_KEY=your-api-key-here" >> .env

Then use the SDK without passing the key:

from fonadalabs import TTSClient, ASRClient, DenoiseHttpClient

# API key is automatically loaded from environment
tts_client = TTSClient()
asr_client = ASRClient()
denoise_client = DenoiseHttpClient()

Method 2: Pass Directly in Code

from fonadalabs import TTSClient, ASRClient, DenoiseHttpClient

tts_client = TTSClient(api_key="your-api-key")
asr_client = ASRClient(api_key="your-api-key")
denoise_client = DenoiseHttpClient(api_key="your-api-key")

⚠️ Security Note: Never hardcode API keys in your source code. Always use environment variables or secure key management systems.

Advanced Features

Retired: TTS v1 and ASR v1 / v2

These models are no longer served. The SDK raises an error before sending any request:

Call Raises
TTSClient.generate_audio(..., model="v1") TTSError: TTS v1 model 'v1' has been retired. Use generate_audio(text, language=..., share_id='<catalog-share-id>') ...
TTSClient.generate_audio(text, "Vaanee") (voice name, no share_id) TTSError: Voice names like 'Vaanee' were TTS v1, which has been retired. Pass a catalog share_id instead ...
TTSClient.generate_audio_ws(...) TTSError: TTS v1 WebSocket streaming ... has been retired ... (use stream_session())
ASRClient.transcribe_file(..., model="v1") ValidationError: ASR model 'v1' has been retired. Use model='v3' (now the default) ...
ASRClient.transcribe_file(..., model="v2") ValidationError: ASR model 'v2' has been retired and renamed to 'v3'. Use model='v3' ...
ASRClient.stream_transcribe_file(...) / ASRWebSocketClient(...) ValidationError: ASR v1 real-time streaming (WebSocket) has been retired ...

At the gateway, POST /v2/asr/transcribe is still proxied to /v3/asr/transcribe for older SDK installs, but new code should use v3.

Languages

The SDK does not check languages; it sends language / language_id as given and the API normalizes it (ISO codes like hi, names like Hindi, en-IN → en) and validates it. An unsupported language comes back as a 400 whose body lists the supported languages; the SDK raises it as ValidationError (ASR) or TTSError (TTS).

Context Manager Support

Use TTSClient with Python's context manager for automatic resource cleanup:

from fonadalabs import TTSClient

# Resources are automatically cleaned up after the block
with TTSClient(api_key="your-api-key") as client:
    audio = client.generate_audio(
        text="Testing context manager",
        language="English",
        share_id="catalog-share-id",
        output_file="output.wav"
    )
    print(f"Generated: {len(audio)} bytes")

Async Operations (TTS)

Use async methods for concurrent requests:

import asyncio
from fonadalabs import TTSClient

client = TTSClient(api_key="your-api-key")

async def generate_multiple():
    tasks = [
        client.generate_audio_async("Text 1", language="Hindi", share_id="share-id-1"),
        client.generate_audio_async("Text 2", language="English", share_id="share-id-2"),
        client.generate_audio_async(
            "Text 3", language="Telugu", share_id="share-id-3", model="klone_v2_pro"
        ),
    ]
    return await asyncio.gather(*tasks)

audio_files = asyncio.run(generate_multiple())

Flash Streaming (TTS)

klone_v2_flash can stream audio while it is generated. The default output is raw pcm (16-bit little-endian, 24 kHz, mono, no header); wav, mp3, opus, mulaw and alaw (both 8 kHz) are also available. Text can be up to 5,000 characters.

from fonadalabs import TTSClient

client = TTSClient(api_key="your-api-key")

with open("out.pcm", "wb") as f:
    for chunk in client.stream_audio(
        "नमस्ते, आपका स्वागत है।",
        language="Hindi",
        share_id="catalog-share-id",
        output_audio_codec="pcm",
        speed=1.1,                 # 0.25–4.0
        instruct="calm, friendly", # up to 500 characters
    ):
        f.write(chunk)

print(client.last_stream_info)     # codec, sample_rate, channels, credits_charged

stream_audio_async(...) takes the same arguments (async for chunk in ...).

For voice agents, keep one WebSocket open and send many utterances; a rejected utterance raises VoiceCloneError and the connection stays open:

import asyncio
from fonadalabs import TTSClient

async def main():
    client = TTSClient(api_key="your-api-key")
    async with client.stream_session() as session:
        for line in ["Hello!", "How can I help you today?"]:
            async for chunk in session.speak(line, language="en", share_id="catalog-share-id"):
                play(chunk)
            print(session.last_end)  # audio_bytes, first_audio_ms, total_ms

asyncio.run(main())

Flash options (all optional): speed (0.25–4.0), duration (0.1–60 s, overrides speed), instruct (up to 500 characters), num_step (8–64, advanced). With audio_url / audio (enterprise), audio_text can be omitted and the API transcribes the reference clip (except Urdu). generate_audio(..., model="klone_v2_flash") also applies these options; it then collects the streamed audio and returns it in one piece. Only Flash streams; klone_v2_pro raises TTSError.

Batch Processing (ASR)

Process multiple audio files concurrently:

from fonadalabs import ASRClient

client = ASRClient(api_key="your-api-key")

# List of audio files to transcribe
file_paths = ["audio1.wav", "audio2.wav", "audio3.wav"]

# Batch transcribe with custom concurrency
results = client.batch_transcribe(
    file_paths=file_paths,
    language_id="en",
    concurrency=3
)

# Process successful transcriptions
for result in results.successful:
    print(f"✓ {result.file_path}: {result.text}")

# Handle failed transcriptions
for failed in results.failed:
    print(f"✗ {failed.file_path}: {failed.error}")

Error Handling

The SDK provides specific exception types for different error scenarios:

TTS Exceptions

from fonadalabs import (
    TTSError,                 # Base exception
    CreditsExhaustedError,    # Credits exhausted (402/429)
    RateLimitError            # Rate limit exceeded (429)
)

# Exception usage example
try:
    audio = client.generate_audio("Text", language="Hindi", share_id="catalog-share-id")
except CreditsExhaustedError as e:
    print(f"Credits exhausted. Balance: {e.remaining_balance}, Cost: {e.estimated_cost}")
except RateLimitError as e:
    print(f"Rate limited. Limit: {e.rate_limit}, Retry after: {e.retry_after_seconds}s")
except TTSError as e:
    print(f"TTS Error: {e}")

ASR Exceptions

from fonadalabs import (
    ASRSDKError,                 # Base exception
    AuthenticationError,         # Invalid API key (401/403)
    ValidationError,             # Invalid parameters
    HTTPRequestError,            # HTTP request failed
    ServerError,                 # Server error (500+)
    ASRRateLimitError,           # Rate limit exceeded (429)
    ASRTimeoutError,             # Request timeout
    ASRCreditsExhaustedError     # Credits exhausted (402/429)
)

# Exception usage example
try:
    result = asr_client.transcribe_file("audio.wav", language_id="hi")
except ASRCreditsExhaustedError as e:
    print(f"Credits exhausted. Usage: {e.current_usage}, Limit: {e.credit_limit}")
except ASRRateLimitError as e:
    print(f"Rate limited. Limit: {e.rate_limit}, Reset at: {e.reset_at}")
except AuthenticationError as e:
    print(f"Auth failed: {e}")
except ValidationError as e:
    print(f"Invalid parameters: {e}")
except ASRSDKError as e:
    print(f"ASR Error: {e}")

Denoise Exceptions

from fonadalabs import (
    DenoiseError,                    # Base exception
    DenoiseCreditsExhaustedError,    # Credits exhausted
    DenoiseRateLimitError            # Rate limit exceeded
)

Security Features

🔒 Base URL Lockdown

All SDK clients use hardcoded, secure base URLs that cannot be overridden. This prevents:

  • URL injection attacks
  • Data exfiltration attempts
  • Man-in-the-middle attacks
# ✅ SECURE: Base URLs are locked
client = TTSClient(api_key="your-key")

# ❌ PREVENTED: Cannot override base URL
# client = TTSClient(api_key="key", base_url="http://malicious.com")  # Not allowed

Base URLs can only be configured via environment variables by authorized administrators:

export FONADALABS_API_URL=https://your-secure-endpoint.com

🔐 API Key Validation

All API requests are validated:

  • API keys are required for all endpoints
  • Invalid keys return 401 Unauthorized
  • Keys are transmitted securely via HTTPS
  • Never logged or exposed in error messages

Documentation

Examples

TTS Examples

Located in tts_sdk/examples/:

  • basic_usage.py - Simple HTTP generation
  • websocket_usage.py - WebSocket with progress tracking
  • async_usage.py - Concurrent requests
  • streaming_usage.py - Audio chunk streaming
  • auth_usage.py - Authentication examples

ASR Examples

Located in test/:

  • asr_test.py - Comprehensive test suite with all features
  • Tests include: HTTP POST, WebSocket, multiple languages, error handling

Run ASR Tests:

# Set API key
export FONADALABS_API_KEY="your_api_key_here"

# Run all tests
cd test
python asr_test.py --audio test_audio.wav

# Run specific test
python asr_test.py --test post         # HTTP POST transcription
python asr_test.py --test ws           # WebSocket transcription
python asr_test.py --test languages    # Test multiple languages
python asr_test.py --test errors       # Error handling

Denoise Examples

Located in denoise_sdk/:

  • sdk_test.py - Quick start examples for HTTP and WebSocket denoising

Package Structure

fonadalabs/
├── __init__.py                    # Unified package exports
├── tts/                           # TTS submodule
│   ├── __init__.py
│   └── client.py                 # TTSClient
├── asr/                           # ASR submodule
│   ├── __init__.py
│   ├── client.py                 # ASRClient
│   ├── ws_client.py              # ASRWebSocketClient (retired stub)
│   ├── config.py                 # Configuration
│   ├── exceptions.py             # ASR exceptions
│   ├── utils.py                  # Utility functions
│   └── models/                   # Data models
│       └── types.py
└── denoise/                       # Denoise submodule
    ├── __init__.py
    ├── http_client.py            # DenoiseHttpClient
    ├── streaming_client.py       # DenoiseStreamingClient
    └── exceptions.py             # Denoise exceptions

Importing

All Three SDKs

from fonadalabs import (
    TTSClient,
    ASRClient,
    DenoiseHttpClient,
    DenoiseStreamingClient
)

tts = TTSClient(api_key="your-key")
asr = ASRClient(api_key="your-key")
denoise = DenoiseHttpClient(api_key="your-key")

TTS Only

from fonadalabs import TTSClient, TTSError, CreditsExhaustedError, RateLimitError
# or explicitly from submodule
from fonadalabs.tts import TTSClient, TTSError

ASR Only

from fonadalabs import ASRClient
# or explicitly from submodule
from fonadalabs.asr import ASRClient

Denoise Only

from fonadalabs import DenoiseHttpClient, DenoiseStreamingClient
# or explicitly from submodule
from fonadalabs.denoise import DenoiseHttpClient, DenoiseStreamingClient

Requirements

Dependencies (Installed Automatically)

Python: >= 3.9 (3.9, 3.10, 3.11, 3.12 supported)

Core Libraries:

  • httpx >= 0.24, < 1.0 (HTTP client)
  • websockets >= 11, < 13 (WebSocket support)
  • loguru >= 0.7, < 1.0 (Logging)
  • requests >= 2.28, < 3.0 (HTTP requests)

Audio Processing (for all services):

  • numpy >= 1.24.0, < 2.0 (Audio processing)
  • soundfile >= 0.12, < 0.14 (Audio I/O)
  • librosa >= 0.10, < 1.0 (Audio analysis - denoise)
  • websocket-client >= 1.5, < 2.0 (WebSocket streaming)

Development (optional - pip install fonadalabs[dev]):

  • pytest >= 7.0, < 8.0
  • black >= 23.0, < 24.0
  • isort >= 5.0, < 6.0
  • python-dotenv >= 1.0, < 2.0
  • nest-asyncio >= 1.5, < 2.0
  • build >= 0.10.0
  • twine >= 4.0.0

Contributing

We welcome contributions! Please see our contributing guidelines and feel free to submit pull requests.

License

MIT License - see LICENSE file for details.

Copyright (c) 2025 FonadaLabs

Support

Version

Current version: 3.0.0 (Unified SDK)

Version History

  • v3.0.0 (2026-10-22): Retire TTS v1 and ASR v1 (breaking); Flash streaming
    • TTS: default model is now klone_v2_flash; model="v1", voice names without share_id and generate_audio_ws raise TTSError
    • TTS: stream_audio / stream_audio_async (HTTPS) and stream_session (WebSocket) for klone_v2_flash; codecs pcm (default), wav, mp3, opus, mulaw, alaw
    • TTS: Flash now applies speed, duration, instruct and the new num_step; Flash audio_url / audio no longer require audio_text
    • ASR: v3 is the default and only model; model="v1" / "v2", stream_transcribe_file and ASRWebSocketClient raise ValidationError
    • Languages are validated by the API, not the SDK: removed is_supported_language, normalize_language, prepare_language_id, SUPPORTED_LANGUAGES and SUPPORTED_LANGUAGES_V3
    • Fixed ASRClient.close() raising after async calls run via asyncio.run()
  • v2.0.0 (2025-12-05): Multi-language TTS support
    • Added language parameter to all TTS methods
    • Supports 4 languages: Hindi, English, Tamil, Telugu
    • Updated SDK documentation
  • v1.0.0 (2025-10-16): Unified package with TTS, ASR, and Denoise
    • Base URL security lockdown
    • Required API key authentication for all endpoints
    • Comprehensive error handling with specific exception types
    • WebSocket streaming support for all services
    • Async/await support
    • Batch processing capabilities

Made with ❤️ by FonadaLabs

Metadata

Release files for fonadalabs 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fonadalabs 3.0.0
File Size Uploaded Provenance
fonadalabs-3.0.0.tar.gz 74.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fonadalabs 3.0.0
File Interpreter ABI Platform
fonadalabs-3.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 128.7 kB

Release files / fonadalabs-3.0.0.tar.gz

Download URL fonadalabs-3.0.0.tar.gz
Size 74.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f62ce4a1d242142f8a1b3db8febe9d87b379775f9fb97367f1628b285d16c579
BLAKE2b-256 checksum
How to use checksums
9d7ab36a9b9dda2baefe77194c1da6123c31a0b56a4815e9e91e8604ea80f996
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.11

Release files / fonadalabs-3.0.0-py3-none-any.whl

Download URL fonadalabs-3.0.0-py3-none-any.whl
Size 54.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
68776862bd705a375a134e2b9c6e18a8ba2e32be1106546f498208f6a6e427cf
BLAKE2b-256 checksum
How to use checksums
9bef14a9cea8144923ff5e77803c28341c889b45cd5ae04f850d6879df895725
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.11

Security for fonadalabs 3.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page