Public Beta ・ Our New Gradium Text-to-Speech Model Is Live

How to Make TTS Pronounce Numbers, Dates, and Phone Numbers Correctly

9 min readUpdated

Most TTS models are trained on narration, audiobooks, and read-aloud text. That training data is rich in complete sentences and standard vocabulary. It is poor in the specific patterns voice agents produce constantly: phone numbers with international prefixes, dates in regional formats, email addresses, currency amounts, alphanumeric order IDs. The model that handles "The meeting is on Thursday afternoon" perfectly will handle "+33 1 70 36 21 00" or "07/18/2026" inconsistently, because these patterns were rare or absent in its training distribution.

Some providers require developers to manually format inputs for correct pronunciation: inserting spaces in phone numbers, spelling out abbreviations, reformatting dates. With Gradium, the same raw text the LLM generates can be sent directly to the TTS without an intermediate normalization step.

There are three distinct mechanisms for controlling pronunciation in Gradium TTS: native model handling, text normalization rules (rewrite_rules), and pronunciation dictionaries. This guide covers all three and when to use each.

Why does structured content break generic TTS?

The problem is an input distribution mismatch. As Neil Zeghidour explains in discussing Gradium's training approach: generating good training data for phone numbers requires "an actual random number generator so that we actually cover the whole scope of phone number," because asking a language model to generate diverse phone numbers produces only a few repeated patterns. This is precisely why most TTS models trained on general internet text or audiobook data fail on structured content: the variability of real-world phone numbers, dates, and IDs is not represented in their training distribution.

Specific failure modes that show up in production:

Phone numbers: a number like "+33 1 70 36 21 00" may be read as a flat string of digits rather than grouped naturally the way a French speaker would say it (by pairs, in the French convention). An American number may be read digit-by-digit rather than as three plus four digits.

Dates: "07/18/2026" is ambiguous. It should be read as "July eighteenth, twenty twenty-six" in American English, but a generic model may read it as "zero seven slash eighteen slash two thousand and twenty-six" or apply the wrong regional convention.

Currency amounts: "$347.89" should be read as "three hundred forty-seven dollars and eighty-nine cents" in a customer service context, but may be read as "dollar three hundred forty-seven point eight nine" by a model that has not learned the spoken convention for monetary amounts.

Email addresses: "user@company.com" must expand to "user at company dot com." A model without explicit email handling may read the "@" as "at" but then stumble on the domain, producing "company dot c o m" or simply "company com."

Alphanumeric codes: confirmation codes, order IDs, and reference numbers like "B4X-2291" require spelling each character individually. A model that tries to pronounce this as a word will produce an unintelligible output.

Mechanism 1: what does the model handle natively?

The first and most reliable mechanism is choosing a TTS model that handles structured inputs correctly by default, without any preprocessing. Gradium's TTS is specifically tuned for these cases. Phone numbers are grouped and intoned naturally instead of read as a flat digit string. URLs and email addresses are spelled out with correct handling of domains, dots, dashes, slashes, and special characters. Dates and times are pronounced in the regional convention of the target language.

This matters architecturally because it removes a preprocessing layer between your LLM and your TTS. If your TTS can handle raw LLM output correctly, you do not need to transform the text before sending it. That transformation step is a failure surface: it is code that must be maintained, updated when output formats change, and debugged when it misses a case.

The June 2026 evaluation of Gradium TTS against Cartesia Sonic 3.5, Inworld TTS 1.5 Max, ElevenLabs Flash v2.5, and ElevenLabs Multilingual v2 measured pronunciation accuracy by category on pass/fail listening tests. In English, Gradium reads email addresses correctly 97% of the time, the top result in the comparison. Time expressions (14:30, 3:45 PM, and similar formats) are handled correctly 86% of the time, compared to 51 to 61% for ElevenLabs models. In French, phone numbers are handled correctly 93% of the time, compared to 51 to 58% for ElevenLabs and Inworld.

A new beta model extends this native handling further: IBAN numbers read digit by digit with correct grouping, native time expressions ("halb drei", "14:30 Uhr"), account handles, measurements, reference codes, license plates, and URLs. It is available through the API by setting model_name to gradium-tts-beta; see the public beta announcement.

For domain-specific terms that are not part of general training, the mechanisms below provide additional control.

Mechanism 2: how do rewrite_rules work?

The rewrite_rules parameter enables explicit text normalization rules that expand structured patterns into speech-friendly forms before synthesis. It is set in the json_config field of the TTS WebSocket setup message.

The Text-to-Speech API supports text rewriting rules that normalize and expand certain patterns in the input text before synthesis. These rules help the model properly pronounce dates, times, numbers, email addresses, URLs, phone numbers, and alphanumeric codes. The full rule reference is in the Gradium documentation.

How to enable rewrite_rules

In the WebSocket setup message:

{
  "type": "setup",
  "voice_id": "your-voice-id",
  "output_format": "pcm",
  "json_config": {
    "rewrite_rules": "en"
  }
}

The rewrite_rules field accepts two types of values: individual rule names (comma-delimited), or a language alias that enables all recommended rules for that language. The language alias is the simplest approach for most deployments.

Language aliases

Language aliases enable all recommended normalization rules for a specific language in a single setting:

Alias Language What it enables
"en" English Date formatting, time expressions with AM/PM, phone number grouping, email expansion, URL expansion, number-to-words for certain contexts
"fr" French Date formatting per French convention, time with "h" separator (14h30), phone number grouping in pairs (French convention), email expansion
"de" German Date formatting, time formatting, phone number conventions for Germany/Austria/Switzerland
"es" Spanish Date and time per regional convention, phone number formatting
"pt" Portuguese Date and time, phone number conventions for European and Brazilian Portuguese

What each rule category covers

Date rules: convert numeric date formats to spoken form. The rule applied depends on the language alias. For English, "07/18/2026" becomes "July eighteenth, two thousand and twenty-six." The rule preserves punctuation at the end of the date.

Time rules: convert time formats to spoken form with the appropriate regional convention. For French, "14h30" uses the "h" separator convention. For English, "14:30" becomes "two thirty PM."

Phone number rules: group digits and apply regional intonation patterns instead of reading digits flat. French phone numbers are grouped as pairs. German numbers follow their own regional grouping.

Email rules: expand email addresses to their spoken components. "@" becomes "at," "." becomes "dot," and domain components are read individually.

URL rules: expand URLs to their spoken components, handling slashes, dots, hyphens, and protocol prefixes.

Alphanumeric code rules: spell out individual characters in mixed alphanumeric strings, treating hyphens as separators.

Combining rules with a pronunciation dictionary

Rules and pronunciation dictionaries can be used together in the same request. Set rewrite_rules in json_config and pass pronunciation_id in the setup message:

{
  "type": "setup",
  "voice_id": "your-voice-id",
  "output_format": "pcm",
  "json_config": {
    "rewrite_rules": "fr"
  },
  "pronunciation_id": "your-pronunciation-dict-id"
}

The json_config also controls other TTS parameters alongside rewrite_rules: temp (generation temperature, default 0.6), cfg_coef (guidance strength), padding_bonus (speech speed control, negative values faster, positive values slower), and voice similarity controls.

For the full parameter reference, see How to Use json_config in Gradium.

Mechanism 3: when do you need a pronunciation dictionary?

Pronunciation dictionaries handle the cases that general normalization rules do not cover: domain-specific terms, brand names, technical abbreviations, and proper nouns with non-standard pronunciation. A dictionary defines exactly how specific words or phrases should be spoken, regardless of how they appear in the input text.

What pronunciation dictionaries are for

Rule-based normalization handles structural patterns: things that follow a predictable format and can be expanded algorithmically. Pronunciation dictionaries handle lexical exceptions: things whose pronunciation cannot be derived from their spelling.

Examples:

  • A healthcare application where drug names (fluoxetine, metformin, dexamethasone) must be pronounced consistently and correctly
  • A financial application where fund names and ticker symbols have specific spoken forms (MSCI as "M S C I," not "mis-ki")
  • An enterprise application where the company name, product line, or internal code system has a non-standard pronunciation
  • Any application where specific acronyms should be spelled out (API as "A P I") versus others that should be pronounced as words (NASA as "NASA")

How to create and use a pronunciation dictionary

Pronunciation dictionaries are created through Gradium Studio or the API. Once created, each dictionary receives an ID. The dictionary is applied to a TTS session by passing the ID as a pronunciation_id parameter in the WebSocket setup message:

{
  "type": "setup",
  "voice_id": "your-voice-id",
  "output_format": "pcm",
  "pronunciation_id": "your-pronunciation-dict-id"
}

The dictionary applies to every synthesis request on that session. For the step-by-step creation guide, including both Gradium Studio and the Python SDK, see How to Use Pronunciation Dictionaries in Gradium TTS.

How do the three mechanisms combine in practice?

The three mechanisms are complementary and can be applied in layers:

Tier 1: native model handling. Send raw LLM output directly to Gradium TTS. Most structured content (phone numbers, common date formats, email addresses, currency amounts) is handled natively without additional configuration.

Tier 2: rewrite_rules. For any remaining mispronunciations on structured patterns (international phone number formats, regional date conventions, specific time formats), enable the appropriate language alias in json_config. This is a one-line configuration change in the setup message.

Tier 3: pronunciation_id. For domain-specific terms, brand names, technical abbreviations, and any lexical items with non-standard pronunciation, create a pronunciation dictionary and attach it to the session.

Most production voice agents use Tier 1 alone for simple use cases, and add Tier 2 when deploying to specific regional markets with different numeric and date conventions. Tier 3 is most common in healthcare, finance, legal, and enterprise deployments where domain vocabulary is a hard requirement.

Glossary

rewrite_rules

A field in the json_config parameter of the Gradium TTS WebSocket setup message that enables text normalization rules. Accepts a comma-delimited string of individual rule names or a language alias (e.g., "en", "fr") that enables all recommended rules for that language. Applied to the input text before synthesis.

Text normalization

The conversion of structured text patterns into speech-friendly spoken forms before synthesis. Examples: numeric dates to spoken date conventions, phone numbers to grouped digit sequences, email addresses to their expanded spoken form. Can be handled natively by the TTS model or explicitly via normalization rules.

Language alias (rewrite_rules)

A shorthand value for the rewrite_rules field that enables all recommended normalization rules for a specific language in a single setting. Supported aliases: "en" (English), "fr" (French), "de" (German), "es" (Spanish), "pt" (Portuguese).

Pronunciation dictionary

A developer-defined mapping from specific words or phrases to their intended spoken form. Applied via the pronunciation_id parameter in the Gradium TTS WebSocket setup message. Used for domain-specific terms, brand names, acronyms, and proper nouns with non-standard pronunciation that normalization rules cannot cover.

json_config

The advanced voice settings parameter in the Gradium TTS WebSocket setup message. Controls rewrite_rules (text normalization), temp (generation temperature), cfg_coef (guidance strength), padding_bonus (speed), and voice similarity settings. Documented in full at How to Use json_config in Gradium.

Pass/fail listening test

An evaluation method where native-speaker evaluators judge whether each synthesized output is correct for a specific content category (phone numbers, email addresses, dates). Captures binary accuracy on structured content. Used in Gradium's June 2026 evaluation against Cartesia Sonic 3.5, Inworld TTS 1.5 Max, and ElevenLabs models.

Frequently Asked Questions