Skip to main content
Streaming voice shares the realtime voice gate: contact your AI Reserve representative to have realtimeVoiceEnabled turned on for your organization — until then, session mints return 403.
Streaming voice gives your application a long-lived WebSocket for one of two jobs:
  • Streaming text-to-speech (inworld-tts-2, inworld-tts-2-flash): send sentences, or individual LLM tokens, as your model produces them and receive audio chunks back as they are synthesized, with several independent contexts on one socket.
  • Streaming speech-to-text (inworld-stt-1): send microphone audio as it is captured and receive interim and final transcripts with turn boundaries.
Both are Inworld’s own streaming sockets, carried by the same voice relay that serves realtime voice sessions and minted by the same endpoint. The relay speaks Inworld’s native frames; nothing is translated, so Inworld’s own client samples work once the URL and credential are swapped. Billing, budgets and usage reporting are handled by AI Reserve like every other surface.

Models

The per-character rate is the same rate the Inworld HTTP passthrough books, so a character costs the same whichever transport carried it.

How it works

  1. Mint a session credential: POST /v1/realtime/sessions with the model (and, for TTS, the voice). The gateway authenticates you, checks the org gate, reserves worst-case funds from your wallet, and returns a short-lived ephemeral_key and a wss_url on the relay’s /v1/audio/tts or /v1/audio/stt path.
  2. Connect your WebSocket to wss_url with ephemeral_key and speak Inworld’s frames. The relay opens Inworld’s socket on your behalf with the platform credential; neither your AI Reserve key nor the Inworld key ever reaches your code.

Step 1: Mint a session

voice on a TTS session is an Inworld voice id: any stock voice, or one of your organization’s cloned or professionally cloned voices. It is pinned for the whole session — every create and updateConfig you send has its voiceId replaced with it — so a ticket cannot be used to speak with a voice the mint never authorized. Another organization’s voice answers 404 at mint, or closes the socket with code 1008 if the relay’s own check refuses it. Defaults to Ashley. An STT session takes no voice (sending one is a 400). The response is the realtime mint’s: wss_url points at /v1/audio/tts or /v1/audio/stt, ephemeral_key is a one-use HMAC ticket valid for five minutes, max_session_seconds is 3540. A mint answers 503 with Retry-After when the deployment has no Inworld credential; nothing is charged.

Step 2: Connect and stream

From a server, pass the key as a bearer header; from a browser, offer the browser_subprotocols the mint returned. Then speak Inworld’s protocol.

Text-to-speech

Client frames: create, send_text, flush_context, close_context, cancel_context and updateConfig, each with an optional contextId, exactly as Inworld documents them. voiceId and modelId are set by the relay. enableCustomPronunciation is removed (it selects the shared workspace dictionary, which is not available through AI Reserve); a frame selecting named dictionaries (pronunciationDictionarySettings) closes the socket with 1008 — select dictionaries on the HTTP synthesis endpoints instead. Any other frame, a non-JSON frame, or a send_text over Inworld’s 2000-unit limit closes the socket.

Speech-to-text

The first frame must be transcribeConfig (the relay sets modelId); audioProtocol: "BINARY" turns on raw binary audio frames, otherwise send base64 audioChunk frames. Then endTurn and closeStream as Inworld documents. A binary frame before the config, or without BINARY selected, closes the socket with 1008.

Billing

  • TTS is billed on the characters of every send_text the relay forwards, UTF-16 code units as Inworld counts, at the model’s rate. Inworld does not count text a cancel_context discards before synthesis; AI Reserve does, so an interruption-heavy client is charged for the last unsynthesized sentence — the conservative side. The mint reserves 3,000 characters a minute for the maximum session; the settle clamps at that reserve.
  • STT is billed on connected seconds, like grok-voice. Inworld counts audio for as long as it keeps arriving, which for a live microphone is the connected session; a socket held open and silent is charged for the silence. Mute by not sending, or close the stream.
  • The reserve is released and the actual charge booked by the settle sweep a few minutes after the socket closes; the row appears in your Event Log under inworld-tts-2, inworld-tts-2-flash or inworld-stt-1 with provider inworld.

Limits

  • Sessions last at most 3540 seconds; Inworld closes a TTS socket after 10 minutes of inactivity.
  • Frames are capped at 1 MiB; a client that outruns the relay’s buffers is closed with 1013.
  • Concurrency is Inworld’s account tier, shared across every organization on the platform.
  • Inworld’s speech-to-speech Realtime API is not served; use grok-voice or eleven-realtime-* on realtime voice sessions.