Text-to-Speech API
Transform any text into professional-quality, natural-sounding speech with our diverse collection of AI voices. Perfect for bringing characters to life, creating audio content, or adding voice capabilities to your applications.
Quick Start
const response = await fetch('https://api.runanythingai.com/api/audio/full', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
"text": "Hello! This is your AI assistant speaking.",
"voice": "af_nicole",
"speed": 1.0
})
});
const audioBlob = await response.blob();
const audio = new Audio(URL.createObjectURL(audioBlob));
audio.play();
Why Use Our TTS?
- 🎭 Character Matching - Voices designed to complement our character endpoints
- 🎯 Instant Generation - Real-time audio synthesis with minimal latency
- 🌍 Global Accents - US and UK English voices for diverse applications
- ⚡ Production Ready - High-quality audio suitable for professional use
Endpoint
POST /api/audio/full
Request Parameters
| Parameter | Type | Required | Description | Default |
|---|---|---|---|---|
text | string | Yes | Text to convert (max 5,000 characters) | - |
voice | string | Yes | Voice ID from available voices | - |
speed | number | No | Speech rate: 0.5 (slow) to 2.0 (fast) | 1.0 |
Voice Library
Choose the perfect voice for your application:
🚺 Female Voices (US English)
| Voice | ID | Personality | Best For |
|---|---|---|---|
| Nicole | af_nicole | Professional, warm | Business, education, assistants |
| Sarah | af_sarah | Friendly, approachable | Customer service, tutorials |
| Heart | af_heart | Emotional, expressive | Storytelling, emotional content |
| Bella | af_bella | Confident, charismatic | Marketing, presentations |
| Nova | af_nova | Modern, tech-savvy | Tech content, AI assistants |
| Sky | af_sky | Clear, articulate | News, announcements |
| Aoede | af_aoede | Artistic, melodic | Creative content, poetry |
| Kore | af_kore | Youthful, energetic | Gaming, entertainment |
| Alloy | af_alloy | Neutral, versatile | General purpose |
| Jessica | af_jessica | Sophisticated, polished | Premium content |
| River | af_river | Calm, soothing | Meditation, relaxation |
🚹 Male Voices (US English)
| Voice | ID | Personality | Best For |
|---|---|---|---|
| Michael | am_michael | Authoritative, trustworthy | Business, leadership content |
| Adam | am_adam | Reliable, professional | Corporate, training |
| Liam | am_liam | Friendly, conversational | Casual content, chatbots |
| Eric | am_eric | Clear, instructional | Tutorials, education |
| Echo | am_echo | Dynamic, engaging | Podcasts, entertainment |
| Onyx | am_onyx | Deep, resonant | Dramatic content, narration |
| Fenrir | am_fenrir | Bold, powerful | Action content, gaming |
| Puck | am_puck | Playful, mischievous | Comedy, light content |
| Santa | am_santa | Jolly, warm | Holiday content, children's content |
🇬🇧 British Voices
| Voice | ID | Gender | Personality | Best For |
|---|---|---|---|---|
| Emma | bf_emma | Female | Elegant, refined | Luxury brands, literature |
| Isabella | bf_isabella | Female | Sophisticated, cultured | Historical content, documentaries |
| Alice | bf_alice | Female | Proper, articulate | Educational content, formal presentations |
| Lily | bf_lily | Female | Sweet, charming | Children's content, fairy tales |
| George | bm_george | Male | Distinguished, authoritative | News, formal announcements |
| Daniel | bm_daniel | Male | Professional, polished | Business, corporate content |
| Lewis | bm_lewis | Male | Intellectual, thoughtful | Academic content, analysis |
| Fable | bm_fable | Male | Storytelling, narrative | Fiction, audiobooks |
Voice Selection for Characters
- Witch characters: Try
af_heart,bf_emma, oraf_aoedefor mystical wisdom - Mage characters: Use
am_michael,bm_lewis, oraf_nicolefor scholarly authority - Succubus characters: Consider
af_bella,bf_isabella, oraf_heartfor charisma - Lightning characters: Pick
am_echo,af_nova, oraf_korefor energy
Response Format
The API returns audio data as a binary stream ready for immediate use.
Response Headers
| Header | Value |
|---|---|
Content-Type | audio/mpeg |
Content-Length | Size of audio file in bytes |
Audio Specifications
- Format: MP3 (MPEG Layer III)
- Quality: 128 kbps
- Sample Rate: 44.1 kHz
- Channels: Mono
Complete Examples
Browser Implementation
async function playTextToSpeech(text, voice = 'af_nicole', speed = 1.0) {
try {
const response = await fetch('https://api.runanythingai.com/api/audio/full', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({ text, voice, speed })
});
if (!response.ok) {
throw new Error(`TTS failed: ${response.status}`);
}
const audioBlob = await response.blob();
const audioUrl = URL.createObjectURL(audioBlob);
const audio = new Audio(audioUrl);
// Optional: Add event listeners
audio.addEventListener('loadstart', () => console.log('🎵 Loading audio...'));
audio.addEventListener('canplay', () => console.log('▶️ Ready to play'));
audio.addEventListener('ended', () => {
console.log('✅ Playback finished');
URL.revokeObjectURL(audioUrl); // Clean up memory
});
await audio.play();
return audio;
} catch (error) {
console.error('❌ TTS Error:', error.message);
throw error;
}
}
// Usage examples
playTextToSpeech("Welcome to our application!", "af_sarah");
playTextToSpeech("Processing your request...", "am_michael", 0.9);
Node.js Implementation
const fs = require('fs');
const path = require('path');
async function saveTextToSpeech(text, filename, voice = 'af_nicole', speed = 1.0) {
try {
const response = await fetch('https://api.runanythingai.com/api/audio/full', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.RUNANYTHING_API_KEY}`
},
body: JSON.stringify({ text, voice, speed })
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`TTS failed (${response.status}): ${errorText}`);
}
const buffer = await response.buffer();
const filepath = path.join(__dirname, filename);
fs.writeFileSync(filepath, buffer);
console.log(`🎵 Audio saved to: ${filepath}`);
console.log(`📊 File size: ${(buffer.length / 1024).toFixed(1)} KB`);
return filepath;
} catch (error) {
console.error('❌ TTS Error:', error.message);
throw error;
}
}
// Usage examples
await saveTextToSpeech("Hello world!", "greeting.mp3", "af_nicole");
await saveTextToSpeech("System alert!", "alert.mp3", "am_michael", 1.2);
Character + TTS Integration
async function createCharacterWithVoice(message, character, voice) {
try {
// Step 1: Generate character response
const textResponse = await fetch(`https://api.runanythingai.com/api/text/${character}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
messages: [{ role: "You", content: message, index: 0 }],
botName: "Character",
persona: getPersonaForCharacter(character)
})
});
const { id } = await textResponse.json();
// Step 2: Wait for text generation
const characterText = await pollForResult(id);
// Step 3: Generate speech
const audioResponse = await fetch('https://api.runanythingai.com/api/audio/full', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
text: characterText,
voice: voice,
speed: getSpeedForCharacter(character)
})
});
const audioBlob = await audioResponse.blob();
return {
text: characterText,
audio: URL.createObjectURL(audioBlob)
};
} catch (error) {
console.error('❌ Character + TTS Error:', error.message);
throw error;
}
}
function getPersonaForCharacter(character) {
const personas = {
'Witch': 'A wise forest witch who speaks in metaphors and ancient wisdom',
'Mage': 'A scholarly mage who explains complex concepts clearly',
'Succubus': 'A charismatic advisor who builds confidence',
'Lightning': 'An energetic coach who motivates with enthusiasm'
};
return personas[character] || 'A helpful assistant';
}
function getSpeedForCharacter(character) {
const speeds = {
'Witch': 0.9, // Slower, more mystical
'Mage': 0.95, // Measured, thoughtful
'Succubus': 1.0, // Normal, confident
'Lightning': 1.1 // Faster, energetic
};
return speeds[character] || 1.0;
}
// Usage
const result = await createCharacterWithVoice(
"I need motivation for my workout",
"Lightning",
"am_echo"
);
console.log("Character says:", result.text);
// Play the audio
const audio = new Audio(result.audio);
audio.play();
Use Cases & Applications
🎮 Gaming & Entertainment
// Dynamic NPC dialogue
await playTextToSpeech("Welcome, traveler! The village needs your help.", "bf_emma");
// Action announcements
await playTextToSpeech("Power up activated!", "am_echo", 1.2);
📚 Educational Content
// Lesson narration
await playTextToSpeech("Today we'll explore quantum mechanics...", "am_michael", 0.95);
// Interactive tutorials
await playTextToSpeech("Click the blue button to continue.", "af_sarah");
💼 Business Applications
// Customer service
await playTextToSpeech("Thank you for calling. How can I help you today?", "af_nicole");
// System notifications
await playTextToSpeech("Your report has been generated successfully.", "am_adam");
🎨 Creative Projects
// Audiobook narration
await playTextToSpeech("Chapter One: The mysterious letter arrived...", "bm_fable", 0.9);
// Podcast intros
await playTextToSpeech("Welcome to Tech Talk Tuesday!", "af_nova");
Advanced Features
Speed Control for Different Content
const speeds = {
meditation: 0.7, // Very slow, calming
storytelling: 0.9, // Slightly slow for narrative
conversation: 1.0, // Normal speaking pace
announcements: 1.1, // Slightly fast for energy
alerts: 1.3 // Fast for urgency
};
await playTextToSpeech("Take a deep breath and relax...", "af_river", speeds.meditation);
await playTextToSpeech("URGENT: System maintenance required!", "am_michael", speeds.alerts);
Batch Audio Generation
async function generateAudioBatch(textArray, voice = 'af_nicole') {
const audioFiles = [];
for (let i = 0; i < textArray.length; i++) {
const filename = `audio_${i + 1}.mp3`;
const filepath = await saveTextToSpeech(textArray[i], filename, voice);
audioFiles.push(filepath);
// Add delay to respect rate limits
await new Promise(resolve => setTimeout(resolve, 1000));
}
return audioFiles;
}
const scripts = [
"Welcome to our service.",
"Please wait while we process your request.",
"Thank you for your patience.",
"Your request has been completed."
];
const audioFiles = await generateAudioBatch(scripts, 'af_sarah');
Error Handling & Troubleshooting
Common Error Scenarios
| Status Code | Issue | Solution |
|---|---|---|
400 | Text too long (>5,000 chars) | Split text into smaller chunks |
400 | Invalid voice ID | Check voice ID against available list |
400 | Invalid speed value | Use speed between 0.5 and 2.0 |
401 | Invalid API key | Verify your API key is correct |
429 | Rate limit exceeded | Implement delays between requests |
500 | Server error | Retry request with exponential backoff |
Error Response Format
{
"error": {
"code": "TEXT_TOO_LONG",
"message": "Text exceeds maximum length of 5000 characters",
"details": {
"current_length": 6543,
"max_length": 5000
}
}
}
Robust Error Handling
async function robustTTS(text, voice = 'af_nicole', maxRetries = 3) {
// Validate input
if (text.length > 5000) {
throw new Error('Text too long. Split into chunks under 5000 characters.');
}
if (!isValidVoice(voice)) {
throw new Error(`Invalid voice: ${voice}. Check available voices.`);
}
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch('https://api.runanythingai.com/api/audio/full', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({ text, voice, speed: 1.0 })
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));
throw new Error(`HTTP ${response.status}: ${errorData.error?.message || 'Request failed'}`);
}
return await response.blob();
} catch (error) {
lastError = error;
if (error.message.includes('429')) {
// Rate limited - wait longer
const delay = Math.pow(2, attempt) * 2000; // Exponential backoff
console.log(`Rate limited. Waiting ${delay}ms before retry ${attempt + 1}/${maxRetries}`);
await new Promise(resolve => setTimeout(resolve, delay));
} else if (error.message.includes('500')) {
// Server error - retry
console.log(`Server error. Retry ${attempt + 1}/${maxRetries}`);
await new Promise(resolve => setTimeout(resolve, 1000));
} else {
// Client error - don't retry
throw error;
}
}
}
throw new Error(`TTS failed after ${maxRetries} attempts: ${lastError.message}`);
}
function isValidVoice(voice) {
const validVoices = [
'af_heart', 'af_bella', 'af_nicole', 'af_aoede', 'af_kore', 'af_sarah',
'af_nova', 'af_sky', 'af_alloy', 'af_jessica', 'af_river',
'am_michael', 'am_fenrir', 'am_puck', 'am_echo', 'am_eric', 'am_liam',
'am_onyx', 'am_santa', 'am_adam',
'bf_emma', 'bf_isabella', 'bf_alice', 'bf_lily',
'bm_george', 'bm_fable', 'bm_lewis', 'bm_daniel'
];
return validVoices.includes(voice);
}
Performance & Optimization
Best Practices
- ✅ Cache audio files when possible to reduce API calls
- ✅ Use appropriate speeds for different content types
- ✅ Batch requests with delays to respect rate limits
- ✅ Clean up blob URLs to prevent memory leaks
- ✅ Implement retry logic for network failures
Rate Limits
| Endpoint | Limit | Time Window |
|---|---|---|
/api/audio/full | 60 requests | per minute |
Text Optimization
function optimizeTextForTTS(text) {
return text
// Expand abbreviations
.replace(/Dr\./g, 'Doctor')
.replace(/Mr\./g, 'Mister')
.replace(/Mrs\./g, 'Missus')
.replace(/&/g, 'and')
// Handle numbers
.replace(/\b(\d+)\b/g, (match) => numberToWords(match))
// Remove or replace special characters
.replace(/[^\w\s\.,!?;:'"()-]/g, '')
// Normalize whitespace
.replace(/\s+/g, ' ')
.trim();
}
function numberToWords(num) {
// Simple implementation - use a library like 'number-to-words' for production
const ones = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
const teens = ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'];
const tens = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'];
num = parseInt(num);
if (num < 10) return ones[num];
if (num < 20) return teens[num - 10];
if (num < 100) return tens[Math.floor(num / 10)] + (num % 10 ? ' ' + ones[num % 10] : '');
return num.toString(); // Fallback for larger numbers
}
Limitations & Specifications
- Maximum text length: 5,000 characters per request
- Supported languages: English (US and UK accents)
- Audio format: MP3, 128 kbps, 44.1 kHz, mono
- Voice variety: 28 unique voices across different personalities
- Speed range: 0.5x to 2.0x normal speaking rate
Next Steps
- Character Endpoints - Create characters with matching voices
- API Workflows - Combine text generation with TTS
- Code Examples - See complete implementations
- Integration Guide - Framework-specific examples