Fix pronunciation with the TTS replace map
Fix pronunciation with the TTS replace map
Pass replace on POST https://api.x.ai/v1/tts (or session.update on the TTS WebSocket / Speech to Speech session) to swap how specific phrases are spoken without changing the text you send or the transcript the listener sees. You are still billed on the original characters.
Respellings and IPA
Values can be respellings or IPA phonetics. Keys stay the ordinary spelling you want to catch.
import os, requests
response = requests.post(
"https://api.x.ai/v1/tts",
headers={"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"},
json={
"text": "nginx is returning errors on the Acme Mobile edge nodes.",
"voice_id": "eve",
"language": "en",
"replace": {
"nginx": "/ˈɛndʒɪn ˈɛks/",
"Acme Mobile": "Acme Mobull",
},
},
)
response.raise_for_status()
open("spoken.mp3", "wb").write(response.content)
On the streaming TTS socket, send the map before the first text.delta:
{"type": "session.update", "replace": {"Acme Mobile": "Acme Mobull"}}
{"type": "text.delta", "delta": "Welcome to Acme Mobile."}
{"type": "text.done"}
The server replies session.updated with the map now in effect. An update mid-utterance applies to the next utterance.
Matching rules
- Case-insensitive match; spoken casing follows the value you set.
- Whole-word boundaries in space-separated scripts (
Acme Mobilesdoes not matchAcme Mobile). - Longest key wins when prefixes overlap.
- Map limits: 200 entries; keys ≤ 100 chars; values ≤ 128 chars; keys are letters, digits, apostrophes, spaces only.
- After substitution the spoken text must stay under 60,000 characters or the request fails (WebSocket sessions end).
Pitfalls
- Broken map entries return
400before any audio is generated. - With
with_timestamps: true,graph_charsdescribes the spoken (replaced) text. - IPA typos produce confident wrong audio. Listen once before shipping a new entry.
- Skip entries the model already says correctly (
IEEE→ "I triple E" unprompted). - Never expose the API key in the browser.