Skip to main content
This guide uses tuner-stt-observer. It assumes you have a TunerSession set up. See the Quickstart for the session lifecycle and credentials.
tuner-stt-observer hooks into your STT provider’s native event system to capture the user side of the conversation. It never proxies or modifies your audio stream. It listens to the same events your application already receives.

Supported adapters

Need a provider that isn’t listed? Extend BaseSTTAdapter. See Custom providers below.

Install

Each provider adapter lives behind an optional extra so you only pull in the SDKs you actually use:

Deepgram

DeepgramAdapter registers on Deepgram’s Open, Transcript, and UtteranceEnd events. speech_final transcript fragments are buffered internally and flushed as a single joined utterance when UtteranceEnd fires. You get one complete user turn per utterance. Attach it to the Deepgram connection you already have:
Send audio to Deepgram as you normally would. The adapter only listens on the connection’s events and never touches audio:
Your LiveOptions must set utterance_end_ms (e.g. "1000") and vad_events=True. Without them, UtteranceEnd never fires and the fragment buffer never flushes, so calls have no user turns.
Barge-in isn’t handled by this adapter. Build it yourself with a local VAD or a provider event like Deepgram’s SpeechStarted.

Speechmatics

SpeechmaticsAdapter registers on ADD_TRANSCRIPT and END_OF_UTTERANCE. Speechmatics-rt stacks event handlers rather than replacing them, so the adapter coexists safely with any handlers you register yourself.
Speechmatics reports word times relative to the start of its session. session_start_ns anchors them to wall-clock time so the adapter can measure STT latency. Without it, the latency field is omitted. If the value is captured slightly too early, the adapter corrects it automatically.

Custom providers

For providers other than Deepgram and Speechmatics, extend BaseSTTAdapter from tuner_stt_observer. Its docstring documents the full contract (_record_user_turn(), _record_stt_usage(), timestamp conversion) with a worked example.

What gets captured

Troubleshooting

  • Your LiveOptions must set utterance_end_ms (e.g. "1000") and vad_events=True. Without them, Deepgram never emits UtteranceEnd and the utterance buffer never flushes.
  • Fragments are joined per utterance. If you’re seeing one turn per fragment, the utterance-end event is never firing. On Deepgram, check utterance_end_ms; on Speechmatics, confirm your session emits END_OF_UTTERANCE.

Next steps

Quickstart

The session lifecycle, credentials, and every observer wired together.

Text-to-Speech

Capture the agent side: synthesis latency and word-accurate interruption.

LangChain / LangGraph

Node transitions, tool calls, and LLM latency in your call timeline.

Create Call API

The underlying API every observer feeds into at flush time.