Skip to navigation

Voice and language

View as MarkdownOpen in Claude

Voice configuration overview

Language configuration

ParameterDescriptionExample
nameHuman-readable name"English"
codeLanguage code for STT. See Language codes."en-US"
voiceTTS voice identifier"rime.spore" or "elevenlabs.josh:eleven_turbo_v2_5"

Fillers (natural speech)

ParameterDescriptionExample
speech_fillersUsed during natural conversation pauses["Um", "Well", "So"]
function_fillersUsed while executing a function["Let me check...", "One moment..."]

Adding a language

Basic configuration

The add_language method configures Text-to-Speech and Speech-to-Text for an agent:

LanguageSyntax
Pythonagent.add_language("English", "en-US", "rime.spore")
TypeScriptagent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' })
from signalwire import AgentBase
class MyAgent(AgentBase):
def __init__(self):
super().__init__(name="my-agent")
# Basic language setup
self.add_language(
name="English", # Display name
code="en-US", # Language code for STT
voice="rime.spore" # TTS voice
)

Voice format

The voice parameter uses the format engine.voice:model where model is optional:

# Engine and voice (engine.voice)
self.add_language("English", "en-US", "rime.spore")
# With model (engine.voice:model)
self.add_language("English", "en-US", "elevenlabs.josh:eleven_turbo_v2_5")

Always name the engine. A voice name on its own — "en-US-Neural2-F" — is resolved against a default engine, and that default can change. Pass the engine in the voice string, or set the engine parameter alongside a bare voice name:

self.add_language("English", "en-US", "josh", engine="elevenlabs")

Available TTS engines

ProviderEngine CodeExample VoiceReference
Amazon Pollyamazonamazon.Joanna-NeuralVoice IDs
Cartesiacartesiacartesia.a167e0f3-df7e-4d52-a9c3-f949145efdabVoice IDs
Deepgramdeepgramdeepgram.aura-asteria-enVoice IDs
ElevenLabselevenlabselevenlabs.thomasVoice IDs
Fish Audiofishfish.802e3bc2b27e49c2995d23ef70e6ac89:s2.1-proVoice IDs
Google Cloudgcloudgcloud.en-US-Casual-KVoice IDs
Grokgrokgrok.eveVoice IDs
Groqgroq-ttsgroq-tts.autumnVoice IDs
Inworldinworldinworld.Lauren:inworld-tts-1.5-miniVoice IDs
Microsoft Azureazureazure.en-US-AvaNeuralVoice IDs
Mistralmistralmistral.<voiceId>Voice IDs
OpenAIopenaiopenai.alloyVoice IDs
Rimerimerime.luna:codaVoice IDs
Smallest.aismallestsmallest.sophia:lightning_v3.1Voice IDs

Filler phrases

Add natural pauses and filler words:

self.add_language(
name="English",
code="en-US",
voice="rime.spore",
speech_fillers=[
"Um",
"Well",
"Let me think",
"So"
],
function_fillers=[
"Let me check that for you",
"One moment please",
"I'm looking that up now",
"Bear with me"
]
)

Speech fillers: Used during natural conversation pauses

Function fillers: Used while the AI is executing a function

Multi-language support

Set the language code to multi to have speech recognition transcribe whichever of its supported languages the caller speaks. The agent still answers in that entry’s single voice, so choose a voice that can speak the languages you expect. To answer each caller in their own language with a voice per language, use multilingual configuration instead.

class MultilingualAgent(AgentBase):
def __init__(self):
super().__init__(name="multilingual-agent")
# Transcribe whichever supported language the caller speaks.
# The single voice must speak every language the agent answers in,
# so use a multilingual voice, such as an ElevenLabs multilingual model.
self.add_language(
name="Multilingual",
code="multi",
voice="elevenlabs.Brian:eleven_multilingual_v2"
)
self.prompt_add_section(
"Language",
"Automatically detect and match the caller's language without "
"prompting or asking them to verify. Respond naturally in whatever "
"language they speak."
)

For more control over individual languages with custom fillers:

class CustomMultilingualAgent(AgentBase):
def __init__(self):
super().__init__(name="custom-multilingual")
# English (primary)
self.add_language(
name="English", code="en-US", voice="rime.spore",
speech_fillers=["Um", "Well", "So"],
function_fillers=["Let me check that"]
)
# Spanish
self.add_language(
name="Spanish", code="es-419", voice="rime.luna",
speech_fillers=["Eh", "Pues", "Bueno"],
function_fillers=["Dejame verificar", "Un momento"]
)
# French
self.add_language(
name="French", code="fr", voice="rime.claire",
speech_fillers=["Euh", "Alors", "Bon"],
function_fillers=["Laissez-moi verifier", "Un instant"]
)
self.prompt_add_section(
"Language",
"Automatically detect and match the caller's language without "
"prompting or asking them to verify."
)

Pronunciation rules

Fix pronunciation of specific words:

LanguageSyntax
Pythonagent.add_pronunciation(replace="ACME", with_text="Ack-me")
TypeScriptagent.addPronunciation({ replace: 'ACME', with: 'Ack-me' })
class AgentWithPronunciation(AgentBase):
def __init__(self):
super().__init__(name="pronunciation-agent")
self.add_language("English", "en-US", "rime.spore")
# Fix brand names
self.add_pronunciation(replace="ACME", with_text="Ack-me")
# Fix technical terms
self.add_pronunciation(replace="SQL", with_text="sequel")
# Case-insensitive matching
self.add_pronunciation(replace="api", with_text="A P I", ignore_case=True)
# Fix names
self.add_pronunciation(replace="Nguyen", with_text="win")

Set multiple pronunciations

# Set all pronunciations at once
self.set_pronunciations([
{"replace": "ACME", "with": "Ack-me"},
{"replace": "SQL", "with": "sequel"},
{"replace": "API", "with": "A P I", "ignore_case": True},
{"replace": "CEO", "with": "C E O"},
{"replace": "ASAP", "with": "A sap"}
])

Voice selection guide

Choosing the right TTS engine and voice significantly impacts caller experience.

Use case recommendations

Use CaseRecommended Voice Style
Customer ServiceWarm, friendly (rime.spore)
Technical SupportClear, professional (rime.marsh)
SalesEnergetic, persuasive (elevenlabs voices)
HealthcareCalm, reassuring
Legal/FinanceFormal, authoritative

Choosing an engine

Providers differ in latency, quality, cost, and language coverage. For a comparison of all supported providers and guidance on choosing between them, see Voices and languages — then audition candidate voices with the voice widget on each provider’s page.

Testing and evaluation process

Before selecting a voice for production:

  1. Create test content with domain-specific terms, company names, and typical phrases
  2. Test multiple candidates from your shortlisted engines
  3. Evaluate each voice: Pronunciation accuracy, natural pacing, emotional appropriateness, handling of numbers/dates/prices
  4. Test with real users if possible — internal team members or beta callers
  5. Measure latency in your deployment environment

Dynamic voice selection

Change voice based on context:

class DynamicVoiceAgent(AgentBase):
DEPARTMENT_VOICES = {
"support": {"voice": "rime.spore", "name": "Alex"},
"sales": {"voice": "rime.marsh", "name": "Jordan"},
"billing": {"voice": "rime.coral", "name": "Morgan"}
}
def __init__(self):
super().__init__(name="dynamic-voice")
def on_swml_request(self, request_data=None, callback_path=None, request=None):
call_data = (request_data or {}).get("call", {})
called_num = call_data.get("to", "")
if "555-1000" in called_num:
dept = "support"
elif "555-2000" in called_num:
dept = "sales"
else:
dept = "billing"
config = self.DEPARTMENT_VOICES[dept]
self.add_language("English", "en-US", config["voice"])
self.prompt_add_section("Role", f"You are {config['name']}, a {dept} representative.")

Language codes

The language code tells speech recognition which language to listen for. By default, SignalWire uses Deepgram’s Nova-3 model, so use a code from Deepgram’s Nova-3 language table, or multi for multi-language support. If you select a different speech recognition engine, use a code that engine supports. See ai.languages for how codes are applied.

The voice is chosen separately. Each provider’s supported languages are listed in Voices and languages.

Complete voice configuration example

from signalwire import AgentBase
class FullyConfiguredVoiceAgent(AgentBase):
def __init__(self):
super().__init__(name="voice-configured")
# Primary language with all options
self.add_language(
name="English", code="en-US", voice="rime.spore",
speech_fillers=["Um", "Well", "Let me see", "So"],
function_fillers=["Let me look that up for you", "One moment while I check", "I'm searching for that now", "Just a second"]
)
# Secondary language
self.add_language(
name="Spanish", code="es-419", voice="rime.luna",
speech_fillers=["Pues", "Bueno"],
function_fillers=["Un momento", "Dejame ver"]
)
# Pronunciation fixes
self.set_pronunciations([
{"replace": "ACME", "with": "Ack-me"},
{"replace": "www", "with": "dub dub dub"},
{"replace": ".com", "with": "dot com"},
{"replace": "@", "with": "at"}
])
self.prompt_add_section("Role", "You are a friendly customer service agent.")