Migrating Speech-to-Text from Gemini to Sarvam
Migrating Speech-to-Text from Gemini to Sarvam
This guide covers migrating Gemini audio transcription calls to Sarvam. If you’re building a full voice agent with live, bidirectional audio rather than transcribing recorded audio one call at a time, 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: Gemini transcribes audio by passing it, along with a natural-language instruction, to a general model. Sarvam has a dedicated transcription endpoint. Swap the text-plus-audio input list for a transcribe() call with a mode parameter, and read the result from a guaranteed-clean transcript field instead of interaction.output_text.
Quick start
Base URL and auth header change the same way for every Gemini migration, so they’re folded in here rather than in a separate page:
With that, replace the transcription call:
Before (Gemini)
After (Sarvam)
Gemini’s reply is a model’s response to your prompt, so its exact wording and formatting can vary between calls unless your prompt constrains it carefully. Sarvam’s response.transcript is a dedicated field that always contains just the transcript.
The rest of this page covers the full endpoint and parameter mapping, long audio, 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
Long audio and diarization
For files over 20 MB, upload first instead of inlining the audio.
Sarvam’s REST endpoint caps at 30 seconds of audio regardless of file size. For a file like this one, use the Batch API instead, shown next, rather than the direct transcribe() call above.
Move diarized or long-form audio to the Batch API.
See the Batch API guide for webhook setup and its Speaker Diarization section for the current per-job speaker limit.
What’s different by design
- A dedicated transcription endpoint.
POST /speech-to-textandmode="transcribe"are purpose-built for turning audio into text, rather than a general model interpreting a natural-language request. - A guaranteed-clean transcript field.
response.transcriptalways holds just the transcript, with no prompt-engineering needed to keep a general-purpose model from adding commentary or reformatting the text. - Flexible output modes on one model.
saaras:v3also supportstranslate,verbatim,translit, andcodemixmodes as explicit parameters, rather than needing a differently worded prompt for each. - Diarization comes standard, not prompted for. Sarvam’s Batch API identifies and labels speakers with
with_diarizationandnum_speakers, returning a structureddiarized_transcript, rather than relying on a model’s best-effort attempt inside free-text output. - 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 (Gemini)
After (Sarvam)
Common mistakes
Trusting interaction.output_text as a clean transcript
It’s a model’s reply to your prompt, so it can include extra phrasing, partial answers, or formatting depending on how the prompt was worded. Read response.transcript on Sarvam’s side instead, which is always transcript-only.
Wording a prompt instead of setting a parameter
Sarvam’s mode parameter (transcribe, translate, verbatim, translit, codemix) replaces the need to phrase a natural-language instruction carefully and hope the model interprets it the same way every time.
Expecting structured diarization from a prompted request
Asking Gemini to “label each speaker” in the prompt returns free text, not a structured, per-segment breakdown. Sarvam’s with_diarization and num_speakers are Batch API parameters that return a dedicated diarized_transcript field, so route diarized requests through the Batch workflow instead of relying on prompt wording.
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 won’t be picked up.
See also
- Migration overview: base URL, auth, and SDK client changes
- Migrating Chat Completion
- Migrating Text-to-Speech
- Which Speech-to-Text API to Use
- Batch API
- Streaming API
- Errors & Troubleshooting