Markup
https://api.suisse-speech.ch/v1 · X-API-KeyA text value whose first element is <speak> is parsed as markup. Every
construct is realised for real, not treated as a hint.
<speak>
Guete Tag.<break time="400ms"/>
Ihri Referenz isch <say-as interpret-as="digits">4711</say-as>.
<mark name="after_ref"/>
<prosody rate="slow">
Mir rüefed Sie zrugg uf <say-as interpret-as="telephone">+41 31 533 22 02</say-as>.
</prosody>
</speak>
| element | effect |
|---|---|
<break time="500ms"/> <break strength="strong"/> |
silence of exactly that length in the audio |
<say-as interpret-as="…"> |
rewrites the text into its spoken form (see below) |
<sub alias="Aktiengesellschaft">AG</sub> |
speaks the alias instead |
<prosody rate pitch volume> |
real rate, pitch and gain change on that passage |
<emphasis level="reduced|moderate|strong"> |
delivery directive on that passage |
<lang xml:lang="de-CH-bern"> |
switches language and dialect mid-text |
<mark name="x"/> |
returns the offset of that point in marks |
<p> <s> |
paragraph (500 ms) and sentence (250 ms) pauses |
prosody accepts keywords (x-slow…x-fast, x-soft…x-loud,
x-low…x-high), percentages, multipliers, -6dB, -2st.
Markup works in realtime too: a text.append whose content is a complete
<speak> document is expanded into passages immediately.
Unsupported elements are rejected by name, never ignored. The response is
400 tts.invalid_ssml with an explanation in error.detail:
{"error":{"code":"tts.invalid_ssml",
"message":"The markup could not be processed.",
"detail":"<phoneme> is not supported: phonetic alphabets are not supported by this engine; use <sub alias=\"...\"> to respell a word",
"request_id":"req_…"}}
<audio src> is refused deliberately: it would make our server fetch a URL of
your choosing. <phoneme> is refused because no phonetic alphabet reaches the
synthesis stage; use <sub alias> to respell a word.
Limits: a single pause ≤ 10 s, 60 s of pause in total, 2000 elements, 24 levels of nesting. Comments, processing instructions and DOCTYPE declarations are refused outright.
say-as: Swiss numbers in particular
interpret-as |
input | spoken as |
|---|---|---|
digits |
4711 |
vier sibe eis eis (Zürich) |
telephone |
+41 31 533 22 02 |
null drüü eis, füf drüü drüü, zwöi zwöi, null zwöi (Bern) |
characters / spell-out |
AB7 |
A, Be, sibe |
ordinal |
15 |
fünfzehnte |
date |
2026-09-15, 15.09.2026, 09/15/2026 + format="mdy" |
fünfzehnter September 2026 |
time |
14:30 |
14 Uhr 30 |
currency |
CHF 1250.50 |
1250 Franken 50 Rappen |
number / cardinal |
1'250 |
1250, handed to the voice as a numeral |
Three things worth knowing:
Digits are dialect-specific. digits and telephone use a digit table and
the familiar 3-3-2-2 grouping per dialect. Standard German digit words inside a
Bernese utterance are audible as a register break, which is why there is a table
per dialect and not one for German. German, French, Italian and English have
digit words; in every other language the digits stay numerals, grouped the same
way, and the voice says them in that language.
Dates, times, ordinals and amounts follow the language of the passage. The
table shows the German forms. French, Italian and English get their own
(15 septembre 2026, 14 h 30, 1250 franchi 50 centesimi, September 15, 2026
in American English); in every other language a date becomes 2026-09-15, a
time 14:30 and an amount 1250.50 CHF, which the voice reads in its own
language. A <lang> passage inside a document takes the forms of its language.
Cardinals are deliberately not expanded. number hands the numeral to the
voice, which reads it correctly in dialect. Rewriting it into Standard German
orthography would make it worse. Use say-as where a voice would otherwise
guess wrong (identifiers, phone numbers, dates, reference codes), not
everywhere.