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

# Speech-to-text

> Rime speech-to-text turns speech into text for voice agents. This overview describes its capabilities, limits, and settings, and helps you choose between the SDK, WebSocket, and gRPC.

Rime speech-to-text turns English or Spanish speech into text. It returns partial transcripts while the person speaks. Then it returns a final transcript that you can send to the language model of your voice agent.

> **[Transcribe your first recording](/docs/stt/quickstart)**
>
> Stream a sample call through the Rime SDK in Python, Node.js, Go, or Rust, and print its transcript.

## Speech-to-text at a glance

| Item | Rime speech-to-text |
| - | - |
| Language | English or Spanish. Set the [language](/docs/stt/recognition#language) to `en` or `es` on every request. Rime does not detect the language from the audio. |
| Language setting | The `language` option in the SDK, `start.language` over WebSocket, or `language` in the gRPC `config` or `options` |
| Utterances | One utterance for each stream. An utterance is one stretch of speech, such as one turn in a conversation. |
| End of speech | Your application ends each utterance, with its own turn detection or a push-to-talk control. Rime does not detect when the speaker stops. |
| Stream time | A stream must finish within [120 seconds](/docs/stt/errors#limits). This time includes the recognition of the audio after the audio ends. |
| Audio format | PCM16, not mu-law. Decode phone audio to PCM16 first. An example is the 8 kHz mu-law of a Twilio media stream. |
| Sample rate | The SDK resamples 8 kHz audio to 16 kHz. See [Where audio flows](/docs/stt/live-audio#where-audio-flows). |
| Authentication | The same API key as Rime text-to-speech |
| SDK packages | The same packages as Rime text-to-speech. In Python, Node.js, Go, and Rust, one SDK client covers both. |

## How a transcription works

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant Client as Browser or phone
    participant Backend as Your backend
    participant Rime
    Backend->>Rime: Open a stream. Set the language.
    Client->>Backend: Audio
    Backend->>Rime: Audio
    Rime->>Backend: Partial transcript
    Backend->>Rime: More audio
    Rime->>Backend: Partial transcript that replaces the last one
    Note over Client,Backend: Your turn detection or push-to-talk ends the utterance.
    Backend->>Rime: End of audio
    Rime->>Backend: Final transcript
```

Keep these points in mind:

1. Keep the API key on your backend. Browsers and phones send their audio to your backend, not to Rime.
2. Open one stream for each utterance. Set the language of the stream.
3. Treat each partial transcript as the whole transcript so far. Each partial transcript replaces the one before it.
4. Use only the final transcript as the complete text. A stream that ends without a final transcript has failed, even if partial transcripts arrived.

## Choose how to connect

Use the Rime SDK if your backend is in a language that the SDK supports. The SDK packages are in alpha. For another language or a [long recording](#long-turns-and-recordings), call the WebSocket API. Use gRPC instead if you already run gRPC. To send a short recording as one WAV file, use the SDK's [`transcribe` call](/docs/stt/quickstart#transcribe-a-whole-file-in-one-call) or gRPC [`Transcribe`](/api-reference/stt/grpc#transcribe).

```mermaid theme={null}
flowchart LR
    Q1{"Is your backend in Python,<br/>Node.js, Go, or Rust?"}
    Q2{"Is the audio a<br/>long recording?"}
    S["Rime SDK<br/>Quickstart"]
    D["WebSocket or gRPC API<br/>Call the API directly"]
    Q1 -- "Yes" --> Q2
    Q1 -- "No" --> D
    Q2 -- "No" --> S
    Q2 -- "Yes" --> D
```

| | Rime SDK (recommended) | WebSocket API | gRPC API |
| - | - | - | - |
| Backend language | [Python](https://pypi.org/project/rimelabs-sdk/), [Node.js](https://www.npmjs.com/package/@rimelabs/sdk), [Go](https://pkg.go.dev/github.com/rimelabs/rime-sdk/go), or [Rust](https://crates.io/crates/rimelabs-sdk) | Any language, with JSON messages | Any language with a protobuf toolchain |
| Connect with | The SDK client, which reads your key from `RIME_API_KEY` and streams over gRPC | `wss://stt.api.rime.ai/ws`, with an `Authorization: Bearer` header on the upgrade | `stt.api.rime.ai:443`, service `rime.SpeechToText`, with `authorization` metadata on each call |
| Audio you send | Headerless PCM16 at 8, 16, 24, or 48 kHz, mono or stereo. The `transcribe` call takes one complete WAV file. | [Headerless PCM16 at 16 kHz, mono](/api-reference/stt/websockets#audio) | [Headerless PCM16 at 16 kHz, mono](/api-reference/stt/grpc#transcribestreaming). `Transcribe` also takes one complete WAV file. |
| Start here | [Quickstart](/docs/stt/quickstart) | [WebSocket reference](/api-reference/stt/websockets) | [gRPC reference](/api-reference/stt/grpc) |

A direct WebSocket stream or gRPC `TranscribeStreaming` call must also name its output contract, because there is no default. The output contract sets the form of the updates. gRPC `Transcribe` and the SDK's `transcribe` call take no output contract, and they return one final transcript.

| Output contract | Choose it when | Each update | Notes |
| - | - | - | - |
| Revised hypotheses | You show text while the person speaks, and you can replace it. | The whole transcript so far, like the partial transcripts of the SDK | The SDK always uses this contract. |
| Append fragments | Your consumer cannot replace text that it already has, or you transcribe a long recording. | The text of the next five seconds of audio | An update never changes after it arrives. |

### Long turns and recordings

A long turn or a long recording can fill the model's context before the stream time runs out. For each partial transcript, the model reads all the audio of the stream again, as the [limits](/docs/stt/errors#limits) explain. For live audio, end the utterance at a pause and start the next stream, as [Split long turns at pauses](/docs/stt/live-audio#split-long-turns-at-pauses) shows. For a recording, send the file with append fragments over the WebSocket or gRPC API, because the SDK cannot do this yet. [Transcribe a long recording](/api-reference/stt/websockets#transcribe-a-long-recording) has the steps.

## What you can control

| Setting | What it does |
| - | - |
| [Word-for-word mode](/docs/stt/recognition#word-for-word-mode) | Asks for every filler, repetition, and false start, with numbers as spoken words. The default is written mode, which asks for numbers as digits. |
| [Language](/docs/stt/recognition#language) | `en` or `es` |
| [Context terms](/docs/stt/recognition#context-terms) | Hints for names and phrases that you expect to hear |

Results are text only. Rime speech-to-text does not offer these items:

* Automatic language detection
* End-of-speech detection
* Word timestamps
* Confidence scores
* Speaker labels

> **Coming from another speech-to-text API**
>
> | In other APIs | In Rime |
> | - | - |
> | Interim results | Partial transcripts |
> | Final results and endpointing | Your application ends the audio. Then the final transcript arrives. |
> | Keyterms or keyword boosting | Context terms. They are hints without weights. |
> | Smart formatting of numbers | Written mode, the default |
> | Filler words | Word-for-word mode |
> | Settings in the URL query string | Settings go in the stream call of the SDK, or in the first message of a direct API session. |
> | A `contextId` for each utterance on one connection, as in Rime's text-to-speech WebSockets | One connection or call for each utterance |
> | Language detection, timestamps, speaker labels | Not available |

## Next

> **[Stream live audio](/docs/stt/live-audio)**
>
> Replace the sample file with audio from your application. Send each final transcript to your language model.


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