Mistral
Realtime speech-to-text with MistralSTTService, Mistral's Voxtral over WebSocket.
Overview
MistralSTTService: streams audio to Mistral's Voxtral realtime transcription over a WebSocket, pushes the text deltas as interim transcriptions, and the final transcript when the user stops speaking.
Upstream page
Pipecat's documentation for the same service.
Source
packages/mistral/src/stt.ts.
Mistral docs
Voxtral and the audio APIs.
Installation
bun add @pipedog/mistralimport { MistralSTTService } from "@pipedog/mistral/stt";Prerequisites
- A Mistral account and an API key from Mistral.
- Pass the key as
apiKey. The examples read it fromMISTRAL_API_KEY. - A VAD in the pipeline: the end of the user's speech flushes the audio buffer.
MistralSTTService
Connects to wss://api.mistral.ai/v1/audio/transcriptions/realtime.
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new MistralSTTService.Settings({...})
(MistralSTTSettings). Any setting you leave out keeps the default below.
| Setting | Type | Default | Description |
|---|---|---|---|
model | string | "voxtral-mini-transcribe-realtime-2602" | Realtime transcription model. |
language | Language | null | null | Not sent: Voxtral detects the language, which is reported on the final transcript. |
Usage
import { STTUpdateSettingsFrame } from "@pipedog/core/frames/frames";
import { MistralSTTService } from "@pipedog/mistral/stt";
const stt = new MistralSTTService({
apiKey: process.env.MISTRAL_API_KEY ?? "",
});Change settings mid-call with an STTUpdateSettingsFrame:
// Queue it on the worker, or push it from a processor upstream of the service.
const update = new STTUpdateSettingsFrame({
delta: new MistralSTTService.Settings({ model: "voxtral-mini-transcribe-realtime-2602" }),
});Event handlers
| Event | Description |
|---|---|
on_connected | The session was created. |
on_disconnected | The WebSocket closed. |
on_connection_error | The connection failed. |
Notes
targetStreamingDelayMstrades latency for accuracy, when set. It is sent in thesession.updatemessage (target_streaming_delay_ms); Mistral accepts 80 to 1200, or 2400, and recommends 480.- The service waits for
session.createdbefore it sends the session settings, as Mistral's SDK does. - Any settings change reconnects.
Runtime notes
| Runtime | Works | What it needs |
|---|---|---|
| Bun | ✅ yes | Nothing. |
| Node.js | ✅ yes | Nothing. |
| Deno | ✅ yes | Nothing. |
| Cloudflare Workers | ✅ yes | Nothing. |
Generated from pipecat.runtimes and pipecat.compat in packages/mistral/package.json: ✅ means the compat smoke test passes on that runtime.
- The WebSocket goes through the core
websocketConnect(upstream uses themistralaiSDK's realtime connection). It works on Bun, Node, Deno and Cloudflare Workers. - The protocol follows Mistral's SDK (
mistralai3.3.0 and@mistralai/mistralai3.1.0,extra/realtime) and the realtime transcription docs.input_audio.flushandtranscription.languageare in the SDK but not in the docs. - Tested against a local fake that follows that protocol, not against Mistral itself.
pipedog is an unofficial community TypeScript port of Pipecat. It is not affiliated with or endorsed by Daily or the Pipecat project.
Portions adapted from the Pipecat documentation, Copyright (c) 2024–2025 Daily, BSD-2-Clause (see apps/docs/LICENSE-pipecat-docs).