Developers

Voice API

Overtone, Undertone, Duotone and Truetone over one key. Speech and transcription follow the OpenAI audio API shapes.

Authentication

Base URL: https://tts-api.yoob.com/v1. Send your API key as a bearer token on every request. Keys start with yoob_live_ or yoob_test_ and are shown once, when you create them in the console. Keep keys on your server: anyone who can read a key can spend your credits until you revoke it. A revoked key stops working within a minute.

from openai import OpenAI
client = OpenAI(base_url="https://tts-api.yoob.com/v1", api_key=os.environ["YOOB_API_KEY"])
print(client.models.list())

A missing, wrong or revoked key gets 401 with "code": "invalid_api_key".

Text to speech (Overtone)

POST /audio/speech with JSON. Returns 48 kHz WAV. Up to 500 characters a request; long input is split into chunks of about 40 words at sentence ends.

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", "quality": "fast",
       "input": "[tender] Hey. [sigh] Whatever happens tomorrow, you are not doing it alone."}' \
  --output line.wav
FieldValue
modelyoob-tts-1
voiceA voice id: w1243, m0770, w0110, m0035, w0073, m0886, w0043, m0290, w0059, m0112. Hear them on Overtone.
inputThe line, with tags (below)
qualitybest: several takes per sentence, keeps the cleanest. fast: one take, first audio sooner, for realtime.

For audio as it is made, use POST /audio/speech/stream with the same body and read the response as a stream.

Emotion, sound and delivery tags

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

  • Emotion, at the start: sets the feeling and pacing of the whole line. [angry] [calm] [desire] [disgust] [excited] [fear] [flirty] [grief] [hurt] [intimate] [joy] [longing] [nervous] [neutral] [playful] [relief] [sad] [shock] [surprise] [tender] [tired]. Common synonyms such as happy or scared are mapped onto these.
  • Sounds, anywhere: performed where they stand. [laughing] [giggle] [chuckle] [sigh] [gasp] [breathing] [inhale] [exhale] [crying] [sobbing] [sniff] [groan] [panting] [cough] [clear throat] [yawn] [scream]
  • Delivery spans, around words: [whisper]…[/whisper], [low voice], [shouting], [tearful], [trembling]. Close the span; closed spans render better.
[sad] [sigh] I walked past his old office today. [tearful] The nameplate was already gone. [/tearful]

Speech to text (Undertone)

POST /audio/transcriptions with the audio as the request body and its Content-Type; options go in the query string. Model yoob-asr-1.

curl "https://tts-api.yoob.com/v1/audio/transcriptions?response_format=verbose_json" \
  -H "Authorization: Bearer $YOOB_API_KEY" \
  -H "Content-Type: audio/wav" \
  --data-binary @clip.wav
response_formatReturns
jsonThe default: {"text": "..."}
textThe transcript as plain text
verbose_jsonSegments with caption, tags, emotion, word timings, voice fields and p_human, plus the speaker profile

A real verbose_json response, shortened:

{
  "task": "transcribe",
  "language": "english",
  "duration": 4.4,
  "text": "We still got some work to do and I look forward to getting that work done.",
  "caption": "[emo:joy] We still got some work to do and <shouting> I look forward to getting that work done. </shouting>",
  "segments": [{
    "start": 0.0, "end": 4.384,
    "caption": "[emo:joy] We still got some work to do and <shouting> I look forward to ... </shouting>",
    "tags": [["<shouting>", 1.84], ["</shouting>", 4.16]],
    "emotion": "joy",
    "emotion_probs": { "joy": 0.943, "sad": 0.031, "surprise": 0.007, ... },
    "words": [{ "word": "We", "start": 0.0, "end": 0.16 }, ...],
    "voice": { "f0_hz": 89.4, "wpm": 274.3, "snr_db": 15.9 },
    "p_human": 0.997
  }],
  "speaker": { "gender": {...}, "age": [...], "accent": {...}, "p_human": 0.997 },
  "model": "yoob-asr-1"
}

caption marks up how the words sounded: [emo:joy] for the feeling from that point on, [laughing], [sigh] or [breath] for sounds where they happened, and <whisper>…</whisper> for words said a particular way. Emotions come in eight families: joy, tender, surprise, neutral, sad, fear, angry and disgust, plus none.

Realtime transcription

Open wss://tts-api.yoob.com/v1/audio/transcriptions/stream with the same bearer header and send 16-bit PCM, mono, 16 kHz. You receive partial messages with the whole utterance so far (replace, don’t append) and a final message with the caption and emotion when the speaker finishes.

Voice detection (Truetone)

Every transcript carries p_human, the probability from 0 to 1 that the voice is a real person: on each segment for that sentence, and on speaker for the voice across the clip. The live socket reports it as the person talks.

p_humanRead it as
0.65 and aboveSounds human
0.35 to 0.65Can’t tell for sure
Below 0.35Sounds AI-generated

The detector is built to catch AI audio played through a speaker into a microphone. It catches about 98% of replayed AI from engines it was trained on, and 70 to 99% (89% on average) from engines it hasn’t heard. About 3 to 5% of real voices played through speakers are flagged, and 0.3% of clean files; whispery or quiet voices are flagged more often. Treat the score as one signal, not proof.

Duotone socket

One WebSocket per call: wss://tts-api.yoob.com/v1/duotone. Open it from your server with your key, send a config message first ({} starts a call with the default persona and voice w1243), then stream the caller’s microphone as 16-bit PCM, mono, 16 kHz, in frames of up to 1 s (40 ms works well). Keep sending while Duotone speaks: that is how it hears the caller cut in. Capture with echo cancellation on.

You receiveWhat it is
readyThe call is live: start the microphone
userWhat the caller is saying, updated as they speak; final: true ends their turn
replyThe reply as it is written, voice tags included
binary framesThe reply’s audio: 16-bit PCM, mono, 48 kHz
reply_doneThe reply is complete; interrupted: true means the caller cut in, so stop playing it
doneThe call has ended, with usage

Avatar SDK docs are at /docs/. Questions: team@yoob.com.