Yoob

Text to speech

Overtone turns a line of text into expressive 48 kHz speech: the feeling, the laughs and sighs, whispered or shouted words, all written into the text. Try every option on the TTS page before you write code.

bash
curl https://tts-api.yoob.com/v1/audio/speech \
  -H "Authorization: Bearer $YOOB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "yoob-tts-1", "voice": "m0770", "input": "[tender] Hey. [sigh] Whatever happens tomorrow, you are not doing it alone."}' \
  --output line.wav

Voices

Each voice is a designed character. Pass its id as voice. These are the voices the console offers, each with a sample on the TTS page; GET /voices lists every voice the API knows, including 414 more Pro voices with regional accents that are not in this table.

VoiceNameSoundsSpeaker
w1243Amber, late-night confidanteBreathy, intimate, hushedWoman, mid 20s, American
m0770David, gravel-voiced storytellerDeep, warm, gravellyMan, early 30s, American
w1371Luna, friendly language tutorBright, clear, friendlyWoman, early 30s, American
m0868James, calm documentary narratorDeep, warm, measuredMan, early 40s, American
w0744Astrid, sharp-witted designerCrisp, bright, articulateWoman, late 20s, British
m1419Walter, wise old radio hostDeep, smooth, resonantMan, early 60s, American
w0769Valentina, big-hearted home cookSmoky, bright, breathyWoman, mid 20s, American
m1381Ryan, energetic sports fanYouthful, bright, dynamicMan, late 20s, American
w0754Leonie, elegant architectVelvety, smooth, refinedWoman, early 40s, British
m0042Marcus, seasoned detectiveDeep, gravelly, resonantMan, mid 40s, American · pro voice
w0445Zoe, sweet best friendSweet, warm, youthfulWoman, mid 20s, American
m1573Tyler, upbeat podcast hostBright, punchy, clearMan, late 20s, American
m0290Adam, soft-spoken romanticDeep, warm, intimateMan, mid 20s, American
w0250Linda, warm British teacherWarm, refined, melodiousWoman, late 50s, British
m0886Leo, laid-back musicianHusky, soft, warmMan, mid 20s, American
w0964Eleanor, velvet-voiced stage actressVelvety, husky, breathyWoman, late 50s, British
m0112Jake, easygoing surferWarm, youthful, raspyMan, mid 20s, American
w1438Chloe, bubbly California creatorBright, youthful, airyWoman, early 20s, Californian
m0602Ben, dry-humored baristaWarm, mellow, dryMan, mid 20s, American
w0110Rachel, no-nonsense news anchorCrisp, assertive, dryWoman, early 30s, American
m0035Sam, curious studentBright, youthful, clearMan, young adult, American
w0073Scarlett, smoky jazz singerSultry, velvety, breathyWoman, late 20s, American
w1058Emma, cheerful morning hostBright, crisp, youthfulWoman, early 30s, American
w0059Mia, soothing meditation guideSoft, breathy, sensualWoman, late 20s, American
w0043Lily, dreamy poetAiry, breathy, youthfulWoman, early 20s, American
h_aus_wMatilda, sunny Aussie adventurerBright, playful, energeticWoman, late 20s, Australian · pro voice
h_irish_mLiam, charming pub storytellerWarm, lively, charmingMan, early 30s, Irish · pro voice
h_scot_mCallum, rugged Highland guideRich, rugged, warmMan, mid 40s, Scottish · pro voice
h_ind_wPriya, warm Mumbai teacherWarm, melodic, articulateWoman, early 30s, Indian · pro voice
h_south_mWyatt, southern ranch ownerSlow, smooth, drawlingMan, late 40s, Southern US · pro voice
h_brit_mOliver, witty London barristerCrisp, dry, wittyMan, mid 30s, British · pro voice
h_ny_wNina, sassy New York cabbieRaspy, sassy, confidentWoman, early 40s, New York · pro voice
h_fr_wCamille, parisian art curatorSoft, elegant, breathyWoman, late 20s, French · pro voice
h_trailer_mVictor, movie trailer voiceBooming, cinematic, deepMan, mid 50s, American · pro voice

Emotion, sound and delivery tags

Write how the line should sound into the line itself, in lower-case square brackets.

Emotion, at the start of the line

One tag first sets the feeling of the whole line, and the voice's pacing with it: sad, tender and intimate lines are slower. Use the exact names below; common synonyms such as happy or scared are mapped onto them.

[angry][calm][desire][disgust][excited][fear][flirty][grief][hurt][intimate][joy][longing][nervous][neutral][playful][relief][sad][shock][surprise][tender][tired]

Sounds, anywhere

A sound is performed where it stands. One in the middle of a line starts a new chunk there.

[laughing][giggle][chuckle][sigh][gasp][breathing][inhale][exhale][crying][sobbing][sniff][moaning][groan][kissing][panting][cough][clear throat][yawn][scream]

Delivery spans, around words

Wrap words to say them a particular way, and close the span: an unclosed span is closed for you, but closed spans render better. [pause] is dropped.

[whisper] … [/whisper][low voice] … [/low voice][shouting] … [/shouting][tearful] … [/tearful][trembling] … [/trembling]

All three together:

[sad] [sigh] I walked past his old office today. [tearful] The nameplate was already gone. [/tearful]
The TTS page has a chip for every tag and highlights the ones it doesn't know, which is the quickest way to get a line right.

Quality

quality trades the first sound for polish. Long inputs are split into chunks of up to about 40 words, at sentence ends and before mid-line sounds, and every chunk keeps the line's leading emotion.

qualityWhat happensUse it for
best8 takes of each chunk; a word check drops takes that slur or skip words, and the cleanest, most in-voice take is kept. With 2 or more chunks the first is a single quick take, so audio starts at once. The default.Anything listened to
best_allBest of 8 on every chunk, the first included.Short lines where every word matters
fastOne take per chunk, no scoring.Drafts, previews, the first reply in a conversation

"pick": "expressive" ranks best takes of an emotion-tagged chunk by how clearly they carry the feeling instead of by overall polish: more emotional, a little less clean.

Output formats

All audio is 48 kHz mono. Choose the container with response_format:

response_formatWhat you get
wavWAV, 16-bit. The default.
pcmRaw signed 16-bit little-endian samples, no header. Best for streaming into a player.
mp3MP3
opusOpus in Ogg
aacAAC (ADTS)
flacFLAC

Streaming audio

With "stream": true the response arrives chunk by chunk as each chunk is picked, so playback can start while the rest renders. With pcm, pipe it straight into a player:

bash
curl -N https://tts-api.yoob.com/v1/audio/speech \
  -H "Authorization: Bearer $YOOB_API_KEY" -H "Content-Type: application/json" \
  -d '{"model": "yoob-tts-1", "voice": "w1243", "input": "[excited] Okay, okay, do not freak out. [gasp] They want me to start on Monday!", "response_format": "pcm", "stream": true}' \
  | ffplay -f s16le -ar 48000 -ac 1 -nodisp -autoexit -

Response headers describe the render: x-yoob-seed (pass it back as seed to reproduce the audio), x-yoob-quality, x-yoob-sample-rate and x-request-id.

Streaming text in

When the text itself is still being written, by a language model for example, open the speech WebSocket and send the text as it arrives. Each sentence is voiced as soon as it is complete, all in one render that keeps one voice and one seed. It is one connection per reply, and the rate limit counts connections, not sentences.

javascript
const ws = new WebSocket("wss://tts-api.yoob.com/v1/audio/speech/stream", {
  headers: { authorization: `Bearer ${process.env.YOOB_API_KEY}` },   // Node; see Authentication for browsers
});
ws.binaryType = "arraybuffer";
ws.onopen = async () => {
  ws.send(JSON.stringify({ voice: "w1243", quality: "best", response_format: "pcm" }));
  for await (const delta of llmReply) ws.send(JSON.stringify({ text: delta }));
  ws.send(JSON.stringify({ end: true }));
};
ws.onmessage = (e) => {
  if (typeof e.data !== "string") return play(e.data);      // 48 kHz s16le audio
  const m = JSON.parse(e.data);                              // ready, chunk, done or error
};
  • Text is cut after . ! ? … once the next character arrives, never inside a tag, an open span or an abbreviation such as “Dr.”.
  • A later sentence shorter than min_words (3) waits for the next one; the first sentence always goes at once.
  • Text that runs past 40 words without a sentence end is cut at its last comma, semicolon or colon.
  • {"flush": true} voices whatever is buffered now. 30 s with no message counts as the end; at most 20,000 characters per connection.

Cancelling

Closing the connection cancels a render. When something sits between you and the API that may not pass the close on quickly, give the request your own id and cancel it explicitly, which stops it at once:

bash
# when speaking
-d '{"model": "yoob-tts-1", "voice": "w1243", "input": "...", "request_id": "reply-42"}'

# to stop it
curl https://tts-api.yoob.com/v1/audio/speech/cancel \
  -H "Authorization: Bearer $YOOB_API_KEY" -H "Content-Type: application/json" \
  -d '{"request_id": "reply-42"}'

Ids are 1–64 characters of [A-Za-z0-9._-], unique per key while running. An id cancelled before its request arrives is remembered for 30 s, and that request is refused.

Speed, seed and delivery

FieldWhat it does
speed0.5 to 2.0. The voice speaks the same words in 1/speed of the time; it is not a time-stretch.
seedAn integer, or a string of 1–64 characters. The same input, voice, quality, speed, instructions and seed always give the same audio.
instructionsFree-text delivery, up to 300 characters. Short comma lists work best: "gentle voice, warm voice, comforting, softly spoken".
inputUp to 4,096 characters per request.

Next steps