Best Practices
Optimize your API usage for better performance, reliability, and cost efficiency.
Text Optimization
Prepare your text for the best audio quality:
✅ Do
- Use proper punctuation for natural pauses
- Add commas where you want brief pauses
- Use periods for complete sentence breaks
- Spell out numbers contextually ("twenty dollars" vs "20")
- Expand abbreviations if pronunciation matters
❌ Avoid
- Very long sentences without punctuation
- Excessive special characters or symbols
- Multiple consecutive spaces or newlines
- HTML or markup in your text
python
# Clean text before sending
import re
def prepare_text(text):
# Remove HTML tags
text = re.sub(r'<[^>]+>', '', text)
# Normalize whitespace
text = ' '.join(text.split())
# Ensure ending punctuation
if not text.endswith(('.', '!', '?')):
text += '.'
return text
Chunking Long Text
For text longer than 5,000 characters, split it intelligently:
python
def chunk_text(text, max_chars=4500):
"""Split text at sentence boundaries."""
sentences = text.replace('! ', '!|').replace('. ', '.|').replace('? ', '?|').split('|')
chunks = []
current_chunk = ""
for sentence in sentences:
if len(current_chunk) + len(sentence) < max_chars:
current_chunk += sentence + " "
else:
if current_chunk:
chunks.append(current_chunk.strip())
current_chunk = sentence + " "
if current_chunk:
chunks.append(current_chunk.strip())
return chunks
# Generate audio for each chunk
chunks = chunk_text(long_article)
for i, chunk in enumerate(chunks):
audio = generate_tts(chunk)
save_audio(audio, f"part_{i+1}.mp3")
💡 Tip
Always split at sentence boundaries, not mid-sentence. This ensures natural audio flow and avoids cut-off words.
Voice Selection
Choose the right voice for your use case:
| Use Case | Recommended Voice Type | Example |
|---|---|---|
| Audiobooks | Narrative, warm tone | Peter, Sarah |
| E-learning | Clear, professional | Alice, James |
| IVR/Phone | Neutral, professional | Rachel, Thomas |
| Marketing | Energetic, engaging | Emma, Michael |
| Accessibility | Clear, moderate pace | Any voice at speed 0.9 |
python
# Preview voices before committing
voices = client.list_voices(language="en-US")
# Filter by use case
narrative_voices = [v for v in voices if "narrative" in v.get("tags", [])]
professional_voices = [v for v in voices if "professional" in v.get("tags", [])]
Caching Strategy
Cache generated audio to reduce API calls and costs:
python
import hashlib
import os
def get_cache_key(text, voice_id, speed=1.0):
"""Generate unique cache key for TTS request."""
content = f"{text}:{voice_id}:{speed}"
return hashlib.md5(content.encode()).hexdigest()
def get_or_generate_audio(text, voice_id, speed=1.0):
"""Check cache first, generate if not found."""
cache_key = get_cache_key(text, voice_id, speed)
cache_path = f"cache/{cache_key}.mp3"
# Return cached audio if exists
if os.path.exists(cache_path):
with open(cache_path, 'rb') as f:
return f.read()
# Generate new audio
audio = generate_tts(text, voice_id, speed)
# Save to cache
os.makedirs('cache', exist_ok=True)
with open(cache_path, 'wb') as f:
f.write(audio)
return audio
💡 When to Cache
- Static content (welcome messages, prompts)
- Frequently requested phrases
- Repeated UI elements
Error Handling
Build resilient applications with proper error handling:
python
import time
import random
def generate_with_retry(text, voice_id, max_retries=3):
"""Generate TTS with exponential backoff retry."""
for attempt in range(max_retries):
try:
response = requests.post(API_URL, json={
"text": text,
"voice_id": voice_id
}, headers={"X-API-Key": API_KEY}, timeout=30)
if response.status_code == 200:
return response.content
if response.status_code == 429:
# Rate limited - respect Retry-After header
retry_after = int(response.headers.get("Retry-After", 60))
time.sleep(retry_after)
continue
if response.status_code >= 500:
# Server error - exponential backoff
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
continue
# Client error - don't retry
response.raise_for_status()
except requests.exceptions.Timeout:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)
raise Exception("Max retries exceeded")
Rate Limit Management
Stay within limits to ensure uninterrupted service:
python
import time
from collections import deque
class RateLimiter:
"""Simple rate limiter for API calls."""
def __init__(self, max_per_minute=60):
self.max_per_minute = max_per_minute
self.requests = deque()
def wait_if_needed(self):
now = time.time()
minute_ago = now - 60
# Remove old requests
while self.requests and self.requests[0] < minute_ago:
self.requests.popleft()
# Wait if at limit
if len(self.requests) >= self.max_per_minute:
sleep_time = self.requests[0] - minute_ago + 0.1
time.sleep(sleep_time)
self.requests.append(now)
# Usage
rate_limiter = RateLimiter(max_per_minute=60)
for text in texts_to_convert:
rate_limiter.wait_if_needed()
audio = generate_tts(text)
Cost Optimization
Minimize character usage without sacrificing quality:
| Tip | Savings | Example |
|---|---|---|
| Remove redundant whitespace | 5-10% | "Hello world" → "Hello world" |
| Cache static content | 50-90% | Pre-generate welcome messages |
| Use appropriate model | Variable | Use aura-lite for IVR prompts |
| Batch similar requests | 10-20% | Generate all chapters at once |
python
# Track your usage
def check_usage():
response = requests.get(
"https://yourvoic.com/api/v1/usage",
headers={"X-API-Key": API_KEY}
)
usage = response.json()
chars_used = usage["characters_used"]
chars_limit = usage["characters_limit"]
percent_used = (chars_used / chars_limit) * 100
print(f"Usage: {chars_used:,} / {chars_limit:,} ({percent_used:.1f}%)")
if percent_used > 80:
print("⚠️ Warning: Approaching character limit!")
Security
Protect your API keys and user data:
- Never expose keys - Store in environment variables, not code
- Use server-side calls - Never call API from client-side JavaScript
- Rotate keys regularly - Update API keys every 90 days
- Monitor usage - Set up alerts for unusual activity
- Limit permissions - Use read-only keys where possible
python
import os
from dotenv import load_dotenv
# Load from .env file (never commit this file!)
load_dotenv()
API_KEY = os.getenv("YOURVOIC_API_KEY")
if not API_KEY:
raise ValueError("YOURVOIC_API_KEY environment variable not set")