Sarvam AI
Speech-to-text for Indian languages with SarvamSTTService and SarvamRealtimeSTTService, over Sarvam's WebSocket APIs.
Overview
SarvamSTTService: streams audio to Sarvam's speech-to-text WebSocket (saaras:v4by default, orsaaras:v3; seeMODEL_CONFIGS). Sarvam's VAD signals can drive the turn.SarvamRealtimeSTTService: Sarvam's realtime endpoint (saaras:v3-realtimeorsaaras:v4), with the server or the pipeline marking turn boundaries, and reconnects.
Upstream page
Pipecat's documentation for the same service.
Source
packages/sarvam/src/stt.ts.
Sarvam docs
The speech-to-text API reference.
Installation
bun add @pipedog/sarvamimport { SarvamRealtimeSTTService, SarvamSTTService } from "@pipedog/sarvam/stt";Prerequisites
- A Sarvam account and an API key from the Sarvam dashboard.
- Pass the key as
apiKey. The examples read it fromSARVAM_API_KEY.
SarvamSTTService
Connects to wss://api.sarvam.ai/speech-to-text/ws, with the key in the Api-Subscription-Key header.
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new SarvamSTTService.Settings({...})
(SarvamSTTSettings). They are the base STT settings (model, language) plus the VAD tuning
fields below, all null (the server's default) unless you set them.
| Setting | Type | Default | Description |
|---|---|---|---|
model | string | "saaras:v4" | Model. Its entry in MODEL_CONFIGS decides the modes and options that apply. |
language | Language | null | null | Language of the audio. null lets models that can detect it do so. |
vadSignals | boolean | null | null | Have Sarvam return VAD signals. |
highVadSensitivity | boolean | null | null | High VAD sensitivity. |
positiveSpeechThreshold | number | null | null | Probability (0 to 1) above which a frame counts as speech. |
negativeSpeechThreshold | number | null | null | Probability (0 to 1) below which a frame counts as silence. |
minSpeechFrames | number | null | null | Consecutive speech frames that start a segment. |
firstTurnMinSpeechFrames | number | null | null | The same, for the first turn. |
negativeFramesCount | number | null | null | Silence frames within the window that end a segment. |
negativeFramesWindow | number | null | null | Window, in frames, for counting silence frames. |
startSpeechVolumeThreshold | number | null | null | Volume (dB) below which audio is too quiet to be speech. |
interruptMinSpeechFrames | number | null | null | Speech frames needed to register a barge-in. |
preSpeechPadFrames | number | null | null | Frames to prepend before the detected start of speech. |
numInitialIgnoredFrames | number | null | null | Leading frames to skip at connection start. |
Usage
import { Language } from "@pipedog/core/transcriptions/language";
import { SarvamSTTService } from "@pipedog/sarvam/stt";
const stt = new SarvamSTTService({
apiKey: process.env.SARVAM_API_KEY ?? "",
settings: new SarvamSTTService.Settings({ language: Language.HI_IN }),
});
Event handlers
| Event | Description |
|---|---|
on_connected | The WebSocket connected. |
on_disconnected | The WebSocket closed. |
on_connection_error | The connection failed. |
Notes
modeis one oftranscribe,translate,verbatim,translitandcodemix, for the models that support it; it defaults to the model's own default.keyterms(at most 50 terms of 64 characters each) are connection-time recognition hints forsaaras:v4.- Only 8000 and 16000 Hz audio is accepted.
- Settings that go in the connection query string reconnect the socket when they change.
SarvamRealtimeSTTService
Connects to Sarvam's realtime speech-to-text WebSocket and maps its VAD and transcript events to frames. A dropped socket is reopened with backoff unless reconnectOnError is false.
Configuration
Prop
Type
Settings
Passed as settings: new SarvamRealtimeSTTService.Settings({...}) (SarvamRealtimeSTTSettings).
| Setting | Type | Default | Description |
|---|---|---|---|
model | string | "saaras:v3-realtime" | saaras:v3-realtime or saaras:v4. |
language | Language | null | Language.EN_IN | Language; null has Sarvam detect it for each utterance. |
streamType | "fast" | "balanced" | "simulated" | "balanced" | Streaming cadence. |
mode | SarvamMode | "transcribe" | Realtime task mode. |
prompt | string | null | null | Decoding prompt. |
threshold | number | null | null | VAD sensitivity. |
silenceDurationMs | number | null | null | Silence that ends speech. |
minSpeechDurationMs | number | null | null | Shortest speech that counts. |
Usage
import { SarvamRealtimeSTTService } from "@pipedog/sarvam/stt";
const realtime = new SarvamRealtimeSTTService({
apiKey: process.env.SARVAM_API_KEY ?? "",
endpointing: "vad",
settings: new SarvamRealtimeSTTService.Settings({ language: Language.HI_IN }),
});
Change settings mid-call with an STTUpdateSettingsFrame:
import { STTUpdateSettingsFrame } from "@pipedog/core/frames/frames";
// Queue it on the worker, or push it from a processor upstream of the service.
const update = new STTUpdateSettingsFrame({
delta: new SarvamRealtimeSTTService.Settings({ streamType: "fast" }),
});Notes
endpointing: "vad"(the default) lets the server mark turn boundaries. With"manual"the pipeline does, so it needs a turn strategy that emitsVADUserStartedSpeakingFrameandVADUserStoppedSpeakingFrame; without one Sarvam never emits a final transcript. It's an option, not a setting, because it decides which turn strategies the user aggregator runs.- A VAD analyzer is needed in both modes: it times the transcription latency.
sampleRateis 8000 or 16000;nulladopts the pipeline's input rate.
| 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/sarvam/package.json: ✅ means the compat smoke test passes on that runtime.
Runtime notes
- Upstream uses the
sarvamaiPython SDK forSarvamSTTService. Here it is a plain WebSocket through the corewebsocketConnect(which sends the auth headers on Workers too), so no SDK is needed. - The deprecated
modelandparamsconstructor options andSettings.language_codeare not ported. - Tested against local WebSocket servers, as upstream's tests do, not against Sarvam 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).