Three ways to make your avatar speak. Pick the one that matches your use case — the rest of the API stays the same.
Set mode once in your config:
The default. Bidirectional voice over WebSocket. Your user speaks, the avatar listens, thinks, and responds — all in real time.
How it works: the SDK captures the user's microphone and streams it to the server. The server understands what was said, generates a reply, and sends back the spoken audio along with the timing data that drives lip-sync.
call mode requests microphone permission when start() is called. Handle the MIC_PERMISSION_DENIED error for users who decline.
Best for: Support agents, AI companions, interactive tutors.
Inside call mode, a second choice: who decides a turn is over. This is
session wiring, not part of the avatar — the same avatar can run hands-free in
one app and push-to-talk in another.
| Mode | Best when |
|---|---|
auto | Quiet environments and hands-free use. Nothing to teach the user — they just talk. |
push-to-talk | Noisy rooms, shared spaces, and open mics where an endpointer would keep triggering on background speech. |
Push-to-talk is deliberately forgiving at both ends: 200 ms of already-captured audio is released on press, because people start talking a hair before their thumb lands, and 250 ms of real audio is still sent after release, so a syllable the user let go on is not cut off. A hold longer than two minutes is treated as a stuck key rather than a person, and the turn is closed.
The built-in controls render the hold-to-talk button for you. To build your own, see useAvatar → Push to talk.
call mode can also let the avatar see, if you opt in with
perception: { camera: true }. The camera stays closed until the avatar
actually needs to look at something. See
Camera perception.
Send text programmatically — the avatar speaks it. No microphone, no voice input.
The server processes the text, generates audio, and returns it with alignment data for lip-sync.
Best for: Announcements, notifications, narration, scripted onboarding flows.
You already have audio (from another TTS provider, a pre-recorded file, or a custom pipeline). Send it to the avatar to lip-sync and play.
Accepted input types: ArrayBuffer, Float32Array, Blob.
Best for: Custom TTS pipelines (ElevenLabs, Play.ai, etc.), pre-recorded content with dynamic delivery.
| Prop | Type | Default | Description |
|---|---|---|---|
WebSocket connectionOptional | call / tts / audio | No default | All three open a live session. |
AuthenticationOptional | all three | No default | Every mode needs one of getSessionToken, deployId, or apiKey. |
Microphone requiredOptional | call only | No default | Only call mode captures user audio. |
Server-side AIOptional | call only | No default | Only call mode uses the language model for responses. |
Camera (opt-in)Optional | call only | No default | perception.camera applies to call mode. |
Transcript & captionsOptional | call mode | No default | Assembled from both sides of a live conversation. |
turnTakingOptional | call only | No default | auto or push-to-talk. Ignored in the other modes. |
Built-in controlsOptional | call only | No default | controls.enabled renders the start/stop/mute bar in call mode. |
speakText()Optional | tts only | No default | Send a string for the avatar to speak. |
speakAudio()Optional | audio only | No default | Send raw audio data for lip-sync playback. |
addLiveContext()Optional | call only | No default | Inject real-time context into the conversation. |
Calling a method outside its mode is a no-op that emits a non-fatal
INVALID_MODE error — it never breaks the session. The methods are typed
optional for exactly this reason, so use optional chaining.