Skip to main content
AssemblyAI TTS natively handles pacing, tone and normalization from the input text. For most sentences, the input text should match what you expect to hear, without special customization. Use this guide to understand and adapt the model’s built-in handling of pace, tone and entity pronunciation.

Pacing and tone

Use full sentences with proper punctuation. When the input text has no punctuation, the model may not render the speech into the sentences you expect to hear. To control pace and tone:
  • Emphasis: use exclamation marks to emphasize a statement.
  • Questions: use question marks to apply the correct tone for a question.
  • Surprise: follow a question mark with an exclamation mark to add a tone of surprise to the question. Compare You haven't seen this before? with You haven't seen this before?!.
  • Short pauses: use commas or ellipses to produce a brief pause. Both produce a similar pause, and writing several together doesn’t make the pause longer.
  • Sudden cutoffs: end the text with a dash, written as two hyphens, to cut the speech off. Compare Yes, it's right here in front of -- with Yes, it's right here in front of..
  • Stressed words: capitalize an entire word to emphasize it. Compare You call THAT a spoon? with You call that a spoon?.
  • Filler words: write them directly into the text, separated by commas and without repeated consonants: It's, uh, right here in front of the, uh, um, thing.
  • Stutters: use dashes: I c-c-can't believe what I'm seeing!
  • False starts: repeat the first word of a sentence, followed by a dash and a space: That- that is the one.

Normalization

Write currencies, phone numbers, addresses and abbreviations the way they’re normally written. The model reads them the way they’re normally pronounced: A currency symbol at the start of a number makes the model read the number as an amount, rather than digit by digit. Well-known abbreviations are read the expected way. For an uncommon acronym or abbreviation, put dashes between the letters: E-T-O is Reference Evapotranspiration.

Reading numbers a specific way

When a number has to be spoken a particular way, such as when confirming a card number:
  • Digit by digit: separate the digits with dashes. 4-3-2-1 is read as four three two one.
  • As a whole number: write it with commas. 4,321 is read as four thousand three hundred and twenty one.
  • Short pauses between groups, as in a card number: put a dash between the groups of digits.

How text is read

The server sends your text to the model as written, in every language: numbers, currency, dates, symbols, URLs, Markdown, emoji and bracketed text such as [pause] reach the model unchanged, and the model reads them on its own. Where the reading matters, write it out in words: a slash in a URL path, for example, comes out as a pause rather than the word, and a written form the model has not seen often can be read another way than you meant. Remove markup, and anything else that should not be read out, before you send the text.
  • Long text is split into pieces before it is spoken, and each piece is spoken on its own, so a split can be heard as a short pause. The server splits:
    • at sentence ends: after ., ! or ?, with any closing quote or bracket, followed by whitespace, but not after a title such as Dr., initials such as e.g. or p.m., a German ordinal such as 3., or a list number that starts its line (5.);
    • at every line break, so each line of a bullet list, a heading or a paragraph without a final period ends a piece;
    • inside a long sentence, after ,, ; or : followed by whitespace, so 12,500 or 3:45 is never split;
    • inside a long clause, between words, at whitespace or U+200B ZERO WIDTH SPACE;
    • inside a long word, such as a URL, a hash or a long number, at the punctuation inside it (/ . ? = & - _ : # @ + ~ , ;), where its runs of digits start and end, and, if it is still too long, between characters. A letter is not separated from its accents, nor an emoji from its modifiers, unless one character with its marks is too long for a piece.
  • Long text is never refused for its length or for a lack of spaces: a 400-letter run, a hexadecimal hash or a 300-digit number is spoken in pieces. The limits on input size are the character limits: 2000 characters per Generate and 8000 sent but not yet synthesized on the WebSocket API (see Limits), and 5,000 per request on the HTTP API.
  • In rare cases a piece does not fit the model with the session’s voice. The session then closes with 3006 after Begin, with a text that begins Text contains a <n>-character segment too long to synthesize and ends Send shorter sentences. The server splits every text into pieces that fit, so this points to a fault on our side: report it with the session’s id. Sending the text again in shorter sentences avoids it.
  • Text with no letter or digit is not spoken. The server checks each sentence, or group of sentences, that it synthesizes at once:
    • only whitespace and symbols, such as emoji, $, €, + or ©: no audio;
    • punctuation without a letter or digit, such as ?!, ..., %, #, &, @, - or •: a short silence, about 0.64 seconds;
    • anything else is spoken as written, emoji and marks included, except emoji or marks joined to a word without a space that do not fit in the word’s piece: the server leaves those out rather than speak a piece with no word in it.
  • [pause] is text like any other: it is not a pause instruction.
WordBoundaries still lists your text exactly as you sent it, markup included; see Word boundaries.