pipedog is an unofficial community port of Pipecat, not affiliated with Daily.
pipedog
Speech-to-text

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:v4 by default, or saaras:v3; see MODEL_CONFIGS). Sarvam's VAD signals can drive the turn.
  • SarvamRealtimeSTTService: Sarvam's realtime endpoint (saaras:v3-realtime or saaras:v4), with the server or the pipeline marking turn boundaries, and reconnects.

Installation

bun add @pipedog/sarvam
import { 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 from SARVAM_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.

SettingTypeDefaultDescription
modelstring"saaras:v4"Model. Its entry in MODEL_CONFIGS decides the modes and options that apply.
languageLanguage | nullnullLanguage of the audio. null lets models that can detect it do so.
vadSignalsboolean | nullnullHave Sarvam return VAD signals.
highVadSensitivityboolean | nullnullHigh VAD sensitivity.
positiveSpeechThresholdnumber | nullnullProbability (0 to 1) above which a frame counts as speech.
negativeSpeechThresholdnumber | nullnullProbability (0 to 1) below which a frame counts as silence.
minSpeechFramesnumber | nullnullConsecutive speech frames that start a segment.
firstTurnMinSpeechFramesnumber | nullnullThe same, for the first turn.
negativeFramesCountnumber | nullnullSilence frames within the window that end a segment.
negativeFramesWindownumber | nullnullWindow, in frames, for counting silence frames.
startSpeechVolumeThresholdnumber | nullnullVolume (dB) below which audio is too quiet to be speech.
interruptMinSpeechFramesnumber | nullnullSpeech frames needed to register a barge-in.
preSpeechPadFramesnumber | nullnullFrames to prepend before the detected start of speech.
numInitialIgnoredFramesnumber | nullnullLeading frames to skip at connection start.

Usage

stt.ts
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

EventDescription
on_connectedThe WebSocket connected.
on_disconnectedThe WebSocket closed.
on_connection_errorThe connection failed.

Notes

  • mode is one of transcribe, translate, verbatim, translit and codemix, 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 for saaras: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).

SettingTypeDefaultDescription
modelstring"saaras:v3-realtime"saaras:v3-realtime or saaras:v4.
languageLanguage | nullLanguage.EN_INLanguage; null has Sarvam detect it for each utterance.
streamType"fast" | "balanced" | "simulated""balanced"Streaming cadence.
modeSarvamMode"transcribe"Realtime task mode.
promptstring | nullnullDecoding prompt.
thresholdnumber | nullnullVAD sensitivity.
silenceDurationMsnumber | nullnullSilence that ends speech.
minSpeechDurationMsnumber | nullnullShortest 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 emits VADUserStartedSpeakingFrame and VADUserStoppedSpeakingFrame; 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.
  • sampleRate is 8000 or 16000; null adopts the pipeline's input rate.
RuntimeWorksWhat it needs
Bun✅ yesNothing.
Node.js✅ yesNothing.
Deno✅ yesNothing.
Cloudflare Workers✅ yesNothing.

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 sarvamai Python SDK for SarvamSTTService. Here it is a plain WebSocket through the core websocketConnect (which sends the auth headers on Workers too), so no SDK is needed.
  • The deprecated model and params constructor options and Settings.language_code are 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).

On this page