Skip to main content
To lip-sync a character to generated speech, you need three things in sync:
  1. The audio file.
  2. The phoneme symbols actually spoken.
  3. The start time and duration of each phoneme.
Supertone returns all three when you pass include_phonemes: true on a TTS request.

Python — request audio + phonemes

TypeScript — request audio + phonemes

Map phonemes to visemes

A common rendering pipeline maps each IPA-style symbol to a small set of mouth shapes (visemes), then drives a 3D rig or 2D sprite by interpolating between them.
In your render loop, advance the current audio time and look up the active viseme for that timestamp. Tween viseme weights so the mouth doesn’t snap between shapes.

Stream phonemes in real time

When you call stream_speech with include_phonemes: true, the response becomes NDJSON. Parse each line as it arrives to drive lip-sync in real time:

Tips

  • Use the model that supports phonemes. sona_speech_2, sona_speech_2_flash, and sona_speech_1 all support phonemes. supertonic_api_3 and supertonic_api_1 do not.
  • Smooth transitions. Real mouths don’t snap between shapes — most engines interpolate viseme weights over 50–80 ms. The phoneme durations from the API are a good starting point for those tweens.
  • Stress and pauses. Empty symbol values mark silences/pauses — return the mouth to the rest pose during those.
  • Localize your mapping. Phoneme → viseme tables differ across languages. Tune your mapping for Korean and Japanese if you’re shipping multilingual content.

Pronunciation and phonemes

Reference for include_phonemes and the response shape.

Stream speech

NDJSON streaming for real-time lip sync.