> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Transcription operations

> Operate live call transcription day to day: turn it on, read partial and final transcripts during and after a call, set language routing, supply your own speech key, and alert on provider failures.

# Transcription operations

This page is the operator's companion to [Live call transcription](/voice/live-call-transcription). That page explains what the feature is and how failover behaves; this one shows you how to turn it on, watch it work, and get paged when it does not.

## 1. Turning it on

Live transcription is a workspace-level voice setting, not a per-call flag you set on each dial.

1. Open **Settings → Voice**.
2. Enable live transcription for Classic and outbound calls. Once enabled, every eligible call streams speech to the platform-managed STT chain and begins emitting transcript events.
3. If you supply your own speech key, register it under **Settings → Voice → Speech-to-text (BYO)** instead. Section 5 covers what changes when you do.

**Classic vs outbound calls.** The setting covers both surfaces, but they behave the same way once on:

* **Classic calls** (inbound through queues, ring groups, IVR, forwarding) start transcribing when the call connects.
* **Outbound calls** (dialer and direct outbound) start transcribing the same way, when the call connects.

AI voice agents do not use this toggle. Each agent picks its speech vendor in the agents console and runs its own realtime pipeline — see [Voice gateway: the realtime AI-voice media edge](/concepts/voice-gateway-realtime-edge). The failover in section 6 does not apply to agent calls either.

There is nothing to restart and no provider to pick. The platform chain is assembled at service boot from whichever vendors have credentials provisioned; the call inherits that chain.

## 2. Reading the transcript

### During the call

While a call is live, the partial and final transcript is available two ways:

* **The voice console.** Open the in-progress call; the live transcript panel renders interim (partial) frames as the caller speaks and replaces them with final frames as each utterance completes. Interim text is provisional — it can change as the recognizer refines a phrase; only a `final` frame is stable.
* **The live transcript stream.** Subscribe a client to the per-call server-sent-events endpoint:

  ```
  GET /api/v1/voice/calls/{callId}/transcript/stream
  ```

  Each event is a transcript frame:

  ```json theme={null}
  {
    "type": "final",
    "speaker": "customer",
    "text": "I'd like to check the status of my order.",
    "ts": 1728748801234,
    "confidence": 0.97
  }
  ```

  * `type` — `partial` (interim, replaceable) or `final` (the utterance is complete; this text will not change).
  * `speaker` — `agent` or `customer` on a diarized two-party call.
  * `text` — the transcribed text for this frame.
  * `ts` — epoch-milliseconds timestamp of the frame.
  * `confidence` — recognizer confidence from 0 to 1, present when the vendor reports one.

  EventSource clients cannot set custom headers, so pass your API key as a `?token=` query parameter when calling this endpoint from a browser.

### After the call

When the call ends, the finalized transcript is attached to the call record and appears in two places:

* **Call detail** — the transcript with its speaker turns, plus (when generated) the AI call summary and sentiment.
* **The recording library** — the call's row carries a `transcription_status` of `pending`, `processing`, `complete`, `failed`, or `skipped`, and the finalized diarized segments are searchable once transcription completes. See [Searchable recording and transcript library](/voice/recording-library).

A `call.transcript_ready` webhook fires when the post-call transcript is persisted, so your own systems can pull it without polling — see section 7.

## 3. Latency and quality

**How far behind the speaker does the transcript run?** That depends on which provider family is serving the stream.

| Provider family | Mode | What you observe |
| - | - | - |
| Deepgram (streaming) | Live stream | Sub-second interim frames; the live panel tracks speech closely. This is the platform primary. |
| Azure / Google (streaming) | Live stream | Comparable live behavior when serving as a failover; a brief pause during the mid-call switch, then streaming resumes. |
| Whisper (OpenAI) | Batch only | Not a live provider. Whisper transcribes completed audio segments after the fact; it never serves a live stream. |

**Whisper as a backup.** Whisper is the validated fallback for the **on-demand, post-call** path (transcribe a finished recording) — it is proven in that role. It is deliberately skipped for the **live** path: a live call cannot hand a mid-utterance stream to a batch recognizer, so the live failover chain walks past Whisper to the next streaming-capable vendor. Do not plan on Whisper as a live-transcription backup — plan on a second streaming vendor.

**The 4 MB replay buffer.** When a provider fails *before* the first transcript, the platform replays the buffered opening audio into the fallback so the caller's first words are not lost. That buffer is capped at 4 MB to bound memory use per call. In practice 4 MB covers well over a minute of call audio, so the cap only matters on a call where the opening failure stretches past that point — if the buffer fills, replay is disabled for that call and transcription effectively starts fresh from the fallback's first live audio. The 4 MB value is a per-call ceiling, not a quota you manage.

## 4. Language routing

The platform builds the STT chain once at boot in a fixed construction order (Deepgram first, then Whisper, Azure, Google), then **reorders it per call** based on the call's `language` value. Reordering never removes a provider — it only moves providers that declare support for the language to the front and pushes the rest behind them, so the chain degrades to "try it anyway eventually" rather than dropping a vendor.

Matching is on the **primary language subtag**: a region tag like `es-MX` reduces to `es`, and `pt-BR` reduces to `pt`. An unset `language` or the value `multi` (code-switching mode) leaves the chain in its original order.

Worked example, with all four providers provisioned and a default chain of `Deepgram → Whisper → Azure → Google`:

* **`language` unset, or `multi`** — Deepgram stays first. Its multilingual set covers the common Latin-alphabet languages, so no reorder happens.
* **`language: es-MX`** — reduces to `es`, which Deepgram supports. Deepgram stays first; the chain is effectively unchanged.
* **`language: ko` (Korean)** — Deepgram does not declare Korean, so it moves behind the providers that declare broad coverage. The attempt order becomes `Whisper → Azure → Google → Deepgram`: the first try lands on a vendor that claims the language instead of paying a near-guaranteed miss against Deepgram on every call.

Set `language` on the call to a BCP-47 tag; routing handles the subtag reduction. You do not pick a provider — you declare the language, and the chain orders itself around it.

## 5. Customer-managed credentials

If you supply your own speech-to-text key (BYO, registered under **Settings → Voice → Speech-to-text**), your transcription runs **inside that credential's route boundary**. The practical consequence:

* Your calls transcribe through your key only. The platform-managed failover chain does not take over your route, add its providers to it, or move the call to a platform credential mid-call.
* Failover and recovery follow **your own provider's** behavior, not the platform chain's. If your vendor fails, recovery is whatever your credential's path does — the platform does not substitute a different vendor for you.
* Your key does not change the platform chain for anyone else: boot-time provider availability and the chain's fixed order are governed by platform-provisioned credentials, not tenant keys.

This is a routing boundary, not a provider picker. Tenant-supplied keys and the platform chain are two separate routes; picking a platform fallback for one of your calls is not something either route exposes.

## 6. Failure walkthrough

Each failure class fires at a different point and surfaces differently. The rule underneath all four: **a failure before the first transcript replays buffered audio into a fallback; a failure after the first transcript switches forward with no replay.** Some speech at the moment of the switch may not be transcribed — that is the intended boundary, and the alternative (replaying consumed audio) would double-count transcript text.

### Pre-transcript failure

```
Call audio ──► STT provider A
                  │  fails before any transcript
                  ▼
        Replay buffered opening audio (≤ 4 MB)
                  ▼
            STT provider B ──► transcript begins
```

The first words arrive buffered at the gate. When the primary fails before emitting anything, the platform hands that same buffered audio to the next provider in the chain, so the caller's opening is not lost. If the buffer has already hit its 4 MB cap, replay is skipped for the call and transcription starts fresh.

### Reconnect-exhaustion (mid-call)

```
Call ──► STT provider A ──► transcripts flowing
            │  connection dies; retries exhausted
            ▼
        Switch to next LIVE provider (skip Whisper — batch only)
            ▼
        Transcription resumes from new audio
        (speech during the reconnect window is not recovered)
```

This fires after transcripts have already been delivered, when the primary's own reconnection budget is spent. The call advances to the next live-capable provider below the failed one; Whisper is walked past because it cannot take a live stream. No audio is replayed — the consumed audio was already transcribed — so anything spoken while the primary was collapsing is not recoverable. See [Live-call speech failover](/voice/live-call-stt-failover) for the full contract.

### Other mid-call error

```
Call ──► STT provider A ──► transcripts flowing
            │  error that is NOT reconnect-exhaustion
            ▼
        Surface the error; do NOT switch or replay
```

A mid-stream error that is not a permanent connection death keeps the established surface-the-error behavior. Switching or replaying here could duplicate transcript text, so the platform distinguishes "the connection hiccuped" from "the connection is permanently dead" and only the latter changes provider.

### One-shot (post-call) transcription failure

```
Recording ──► provider 1 ──► fails ──► provider 2 ──► fails ──► … ──► chain exhausted
                                                                           ▼
                                                              final provider error returned
```

For on-demand transcription of a complete recording, the ordered chain is tried until one provider succeeds. Only **transient** failures (HTTP 429, 5xx, timeouts, network resets) trigger failover — a deterministic 4xx like a bad credential surfaces immediately instead of silently hopping providers, which would mask the real problem. If every provider fails, the last provider's error is what you get back, and the call's `transcription_status` reads `failed`.

## 7. Alerting and monitoring

Subscribe to the call-level webhook so your systems are told the moment a transcript is ready or missing, and watch the pipeline states for calls that never complete.

**Webhooks to subscribe to** (see [Webhook event payloads](/webhooks/event-payloads)):

* **`call.transcript_ready`** — fires when the post-call transcript is persisted. Carries `call_id`, `contact_id`, `direction`, `duration_sec`, `sentiment`, `sentiment_score`, `keywords`, a `transcript_snippet`, and `analyzed_at`. Use it to pull the full transcript into your CRM or warehouse without polling.

**What to monitor operationally:**

* **`transcription_status` on the recording library** — a rising count of `failed` rows is your primary provider-degradation signal. Filter the library by `transcription_status: failed` to triage recordings that never transcribed; `pending` or `processing` rows that never advance point to a stalled pipeline.
* **Post-call transcribe API failures** — the on-demand transcribe endpoint returns `502` when every provider in the chain failed, and `503` when no provider is configured at all. A sustained rate of these, or of `502` naming a single provider, is the alert condition for a vendor outage.
* **Live-transcript stream health** — if your integration consumes the per-call SSE stream, a stream that opens and delivers no frames for the length of a connected call is a symptom of a live-path provider failure (section 6, reconnect-exhaustion or other-error classes).

When a platform STT provider fails, no action is required from you beyond what section 6 describes — the chain fails over automatically where it can. Alert on the symptoms above so you know transcription is degraded, and check [Troubleshooting transcription and synthetic-voice failures](/troubleshooting/transcription-and-synthetic-voice-failures) for the provider-error matrix. If failover destinations are missing because only one streaming vendor is provisioned for your workspace, contact Devotel support to enable a second.

## Related reading

* [Live call transcription](/voice/live-call-transcription) — the feature model, provider chain, and failover rules this page operationalizes.
* [Live-call speech failover](/voice/live-call-stt-failover) — the reconnect-exhaustion switch in detail.
* [Searchable recording and transcript library](/voice/recording-library) — the `transcription_status` surface and transcript search.
* [STT Playground](/guides/stt-playground) — compare vendors and confirm which are provisioned on your workspace.
* [Voice gateway: the realtime AI-voice media edge](/concepts/voice-gateway-realtime-edge) — the separate AI-agent speech pipeline.
* [Troubleshooting transcription and synthetic-voice failures](/troubleshooting/transcription-and-synthetic-voice-failures) — provider error codes and recovery steps.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.