Migrating Speech-to-Text from Cartesia to Sarvam
Migrating Speech-to-Text from Cartesia to Sarvam
This guide covers migrating Cartesia speech-to-text (transcription) API calls to Sarvam. If you’re building a full voice agent rather than transcribing audio directly, start from the LiveKit or Pipecat voice agent build guides instead: they aren’t a 1:1 API swap and aren’t covered here.
In short: swap model for model, keep passing your audio file directly, and pick the right Sarvam API for the job: REST for short synchronous requests, Batch if you need diarization or very long audio, and WebSocket for real-time streaming.
Quick start
Base URL and auth header change the same way for every Cartesia migration, so they’re folded in here rather than in a separate page:
With that, replace the transcription call:
Before (Cartesia)
After (Sarvam)
Cartesia’s /stt endpoint transcribes audio of any length synchronously, with no separate long-audio mode. Sarvam splits this by use case: REST for requests under 30 seconds, and Batch for longer audio or when you need speaker diarization, which Cartesia’s STT doesn’t offer at all.
The rest of this page covers the full endpoint and parameter mapping, diarization via the Batch API, streaming, and common mistakes.
Endpoint map
The tables below aren’t a checklist to apply field-by-field: Quick Start above already shows the whole call swapped over in one go. Use these tables as a reference for what changed and why, not as a sequence of edits to make yourself.
Parameter concept map
Sarvam’s Batch API returns timestamps per chunk (sentence or phrase segment), which is precise enough for subtitle alignment and audio navigation. If your Cartesia integration reads individual words[].start/end for word-by-word highlighting, adjust it to work at the chunk level instead, or use Sarvam’s REST/Streaming endpoints where per-word timing isn’t part of the response shape either.
Diarization and long-form audio
Cartesia’s /stt has no speaker-labeling mode to migrate from; this is new capability you get on Sarvam’s side, through the Batch API:
See the Batch API guide for webhook setup and its Speaker Diarization section for the current per-job speaker limit.
Streaming
What’s different by design
- Diarization comes standard on longer audio. Cartesia’s STT has no speaker-labeling mode; Sarvam’s Batch API identifies and labels speakers automatically with
with_diarizationandnum_speakers, no separate product or add-on needed. - Flexible output modes on one model.
saaras:v3supportstranscribe,translate,verbatim,translit, andcodemixmodes on the same endpoint, rather than transcription being the only option. - One model, one workflow. There’s no dated version pin to track, and no separate model to switch to for real-time use:
saaras:v3is the same model across REST, Batch, and Streaming. - Indian language depth is Sarvam’s specific strength. Saaras v3 covers 22 Indian languages, including Assamese, Konkani, Kashmiri, Sindhi, Sanskrit, Santali, Manipuri, Bodo, Maithili, and Dogri, with native handling for code-mixed speech like Hinglish.
Full example
A small wrapper function, before and after, showing the complete set of changes together:
Before (Cartesia)
After (Sarvam)
Common mistakes
Assuming diarization exists somewhere in the Cartesia-equivalent call
It doesn’t, so there’s nothing to port over parameter-for-parameter. Add with_diarization=True and num_speakers directly on a Sarvam Batch job; this is new configuration, not a renamed existing one.
Sending long audio to the REST endpoint
Sarvam’s REST endpoint caps at 30 seconds, unlike Cartesia’s /stt, which accepts audio of any length in one call. Route anything longer through the Batch API instead of expecting the REST endpoint to chunk it for you.
Reading Batch timestamps as word-level
Batch API timestamps cover sentence or phrase chunks, not individual words, unlike Cartesia’s optional timestamp_granularities: ["word"]. If your integration builds word-by-word highlighting from words[].start/end, adjust it to work at the chunk level instead.
Sending Batch parameters as top-level fields
Calling the Batch endpoints directly over HTTP (rather than through the SDK) requires nesting parameters under job_parameters, e.g. {"job_parameters": {"model": "saaras:v3", ...}}. A flat body modeled on Cartesia’s request shape won’t be picked up.
Porting the batch model name into a streaming connection
Cartesia’s /stt/turns/websocket only accepts ink-2, not the ink-whisper model used for batch requests. Sarvam has one model name, saaras:v3, to pass everywhere, so there’s no equivalent swap to remember on Sarvam’s side.
See also
- Migration overview: base URL, auth, and SDK client changes
- Which Speech-to-Text API to Use
- Batch API
- Streaming API
- Speaker Diarization
- Errors & Troubleshooting