Get Started
Intro to Realtime STT
High-accuracy, low-latency multilingual speech-to-text for live voice agents.
Inworld's Realtime Speech-to-Text (STT) transcribes speech with high accuracy and low latency across 30 languages, built for voice agents that have to keep up with a live conversation. Alongside the transcript it returns Voice Profile signals — age, pitch, emotion, vocal style, accent — and gives you turn-taking you can tune or drive yourself.
Use synchronous transcription for complete audio files, and bidirectional WebSocket streaming for live audio.
Developer Quickstart
Make your first STT API call and get a transcript.
API Reference
View the complete API specification.
Code Examples
Browse ready-to-use GitHub samples for sync and real-time STT.
Using AI to code? Paste https://docs.inworld.ai/llms.txt into your assistant so it knows every page on this site. Want live search? Add the MCP server.
Prefer the terminal? npm install -g @inworld/cli — transcribe audio and create API keys with the Inworld CLI. AI agents can use it too.
Supported models
| Model ID | Endpoints | Best for |
|---|---|---|
inworld/inworld-stt-1 | Sync API + WebSocket | Voice agents and character-driven apps that benefit from transcription plus Voice Profile (age, pitch, emotion, vocal style, accent) and configurable turn-taking |
Supports 30 languages. See Language Support for the full list.
Streaming includes automatic end-of-turn detection with tunable sensitivity, plus a manual mode for client-controlled turn boundaries. See Turn Detection.
Speaker diarization is available as an Experimental feature. See the Speaker Diarization guide.
For pricing details, see Billing or inworld.ai/pricing.
Supported Audio Formats
| Format | Sync API | WebSocket Streaming |
|---|---|---|
LINEAR16 (PCM) | ||
MP3 | ||
OGG_OPUS | ||
FLAC | ||
AUTO_DETECT |
Recommended defaults: 16,000 Hz sample rate, 16-bit depth, mono. For container formats (MP3, FLAC, OGG_OPUS, WAV), sampleRateHertz is optional — the API auto-detects it from the file header.
Sync transcription accepts audio files up to ~16 MB. The actual duration depends on the encoding — for example, ~18 minutes of MP3 or ~8 minutes of 16 kHz 16-bit WAV. For larger files, split them into chunks or use the WebSocket streaming endpoint.
STT performs best with 16 kHz audio. Lower sample rates (such as 8 kHz telephony audio) contain fewer data points for the model to interpret, which reduces transcription accuracy. Upsampling low-sample-rate audio does not improve quality — it only interpolates between existing samples without adding new information.
Endpoints
| Endpoint | Method | Description |
|---|---|---|
/stt/v1/transcribe | POST | Send complete audio, receive full transcript |
/stt/v1/transcribe:streamBidirectional | WebSocket | Stream audio in real time, receive transcription chunks as they become available |
Supported Languages
See Language Support for the full list of languages supported by inworld/inworld-stt-1.
Error Handling
Errors follow the standard gRPC status format.
Authentication error
{
"code": 16,
"message": "Unauthenticated: invalid or missing API key.",
"details": []
}Invalid request
{
"code": 3,
"message": "Unsupported audio encoding.",
"details": []
}Common gRPC status codes
| Code | Name | Description |
|---|---|---|
3 | INVALID_ARGUMENT | Invalid or missing request field (encoding, model ID, audio data) |
8 | RESOURCE_EXHAUSTED | Too many concurrent requests (rate limit) |
16 | UNAUTHENTICATED | Invalid or missing API key |
Streaming (WebSocket) errors
On the streaming endpoint, errors arrive as a frame with a top-level error key using the same status format:
{
"error": {
"code": 3,
"message": "invalid transcribe config: unsupported audio encoding"
}
}A malformed first message (for example, a config not wrapped in transcribeConfig) currently closes the socket with WebSocket close code 1005 and no error frame. If your connection closes silently with no transcripts, check the shape of your first message.
Best Practices
- Audio — Use MP3/OGG_OPUS for file uploads to reduce size; use LINEAR16 for streaming (required) and when you need highest quality.
- Streaming — With manual turn-taking, send
endTurnat each turn boundary andcloseStreamwhen done. - Speech events — Listen for
speechStartedandspeechStoppedevents in the streaming response to detect when a speaker begins and stops talking. Use these to build custom turn-taking logic or visualize voice activity. - Voice Profile — Set
voiceProfileConfig.enableVoiceProfiletotrueand optionally adjusttopN(default: 10) to control how many labels per category are returned. - Language hint — If you know the audio's language, set
language(e.g.en,ja) for cleaner output; the hint also constrains the output script (see Language Support). Leave it empty to auto-detect or when speakers switch languages. - Custom vocabulary — Pass domain-specific terms (names, jargon, acronyms) in
promptsto bias recognition toward them. It is a soft bias rather than a hard keyword lock, so test it on the cases where the baseline actually misses the term. - Test with sample audio and your target language before production.
Troubleshooting
| Issue | What to check |
|---|---|
| No transcript | API key, audio encoding matches request, valid audio file |
UNAUTHENTICATED | INWORLD_API_KEY set correctly and not expired in Portal |
INVALID_ARGUMENT | audioEncoding matches the actual format (LINEAR16 for raw PCM, MP3 for MP3, etc.) |
| Poor quality | Use 16 kHz sample rate (8 kHz telephony audio has fewer data points and will produce lower-quality results); ensure clear speech |
| Large file failures | Split or compress (e.g. MP3/OGG_OPUS); respect upload size limits |
| No Voice Profile | Ensure voiceProfileConfig.enableVoiceProfile is set to true in your request |
For more help, see the Inworld Discord community.