Skip to main content

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

ParameterTypeRequiredDescriptionDefault
textstringYesText to convert (max 5,000 characters)-
voicestringYesVoice ID from available voices-
speednumberNoSpeech rate: 0.5 (slow) to 2.0 (fast)1.0

Voice Library

Choose the perfect voice for your application:

🚺 Female Voices (US English)

VoiceIDPersonalityBest For
Nicoleaf_nicoleProfessional, warmBusiness, education, assistants
Sarahaf_sarahFriendly, approachableCustomer service, tutorials
Heartaf_heartEmotional, expressiveStorytelling, emotional content
Bellaaf_bellaConfident, charismaticMarketing, presentations
Novaaf_novaModern, tech-savvyTech content, AI assistants
Skyaf_skyClear, articulateNews, announcements
Aoedeaf_aoedeArtistic, melodicCreative content, poetry
Koreaf_koreYouthful, energeticGaming, entertainment
Alloyaf_alloyNeutral, versatileGeneral purpose
Jessicaaf_jessicaSophisticated, polishedPremium content
Riveraf_riverCalm, soothingMeditation, relaxation

🚹 Male Voices (US English)

VoiceIDPersonalityBest For
Michaelam_michaelAuthoritative, trustworthyBusiness, leadership content
Adamam_adamReliable, professionalCorporate, training
Liamam_liamFriendly, conversationalCasual content, chatbots
Ericam_ericClear, instructionalTutorials, education
Echoam_echoDynamic, engagingPodcasts, entertainment
Onyxam_onyxDeep, resonantDramatic content, narration
Fenriram_fenrirBold, powerfulAction content, gaming
Puckam_puckPlayful, mischievousComedy, light content
Santaam_santaJolly, warmHoliday content, children's content

🇬🇧 British Voices

VoiceIDGenderPersonalityBest For
Emmabf_emmaFemaleElegant, refinedLuxury brands, literature
Isabellabf_isabellaFemaleSophisticated, culturedHistorical content, documentaries
Alicebf_aliceFemaleProper, articulateEducational content, formal presentations
Lilybf_lilyFemaleSweet, charmingChildren's content, fairy tales
Georgebm_georgeMaleDistinguished, authoritativeNews, formal announcements
Danielbm_danielMaleProfessional, polishedBusiness, corporate content
Lewisbm_lewisMaleIntellectual, thoughtfulAcademic content, analysis
Fablebm_fableMaleStorytelling, narrativeFiction, audiobooks
Voice Selection for Characters
  • Witch characters: Try af_heart, bf_emma, or af_aoede for mystical wisdom
  • Mage characters: Use am_michael, bm_lewis, or af_nicole for scholarly authority
  • Succubus characters: Consider af_bella, bf_isabella, or af_heart for charisma
  • Lightning characters: Pick am_echo, af_nova, or af_kore for energy

Response Format

The API returns audio data as a binary stream ready for immediate use.

Response Headers

HeaderValue
Content-Typeaudio/mpeg
Content-LengthSize 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 CodeIssueSolution
400Text too long (>5,000 chars)Split text into smaller chunks
400Invalid voice IDCheck voice ID against available list
400Invalid speed valueUse speed between 0.5 and 2.0
401Invalid API keyVerify your API key is correct
429Rate limit exceededImplement delays between requests
500Server errorRetry 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

EndpointLimitTime Window
/api/audio/full60 requestsper 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