Migrating Text-to-Speech from Deepgram to Sarvam
Migrating Text-to-Speech from Deepgram to Sarvam
This guide covers migrating Deepgram text-to-speech API calls to Sarvam. If you’re building a full voice agent rather than replacing individual TTS calls, 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: split Deepgram’s combined model string into a separate model and speaker, and change your response handling: both platforms return audio bytes, but Sarvam wraps them in JSON as a base64 audios array rather than handing back a raw stream.
Quick start
Base URL and auth header change the same way for every Deepgram migration, so they’re folded in here rather than in a separate page:
With that, replace the synthesis call and add the required language code:
Before (Deepgram)
After (Sarvam)
Deepgram’s generate() yields raw audio chunks/bytes you can write directly. Sarvam’s convert() returns a JSON object; the audio lives in response.audios as a list of base64 strings, one per input text. Join and decode before writing to disk, or use the Python SDK’s sarvamai.play.save() helper, which does this for you.
The REST response is JSON with a base64 audios array, not a file. Decode .audios[0] before writing it out; see the REST API guide for the full decode snippet.
The rest of this page covers the full endpoint and parameter mapping, 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
Streaming
What’s different by design
- Plain speaker names, no combined model string. Sarvam’s
speakeris a name you pick straight from the Voices page, rather than being baked into a singlemodelvalue likeaura-2-asteria-enthat encodes voice, version, and language together. - Two output settings instead of three.
speech_sample_rateandoutput_audio_codeccover what Deepgram splits acrossencoding,container, andsample_rate. - No async/webhook mode to configure. Sarvam’s TTS endpoints are always synchronous or streamed live, so there’s one less delivery mode to decide between.
- Indian language depth is Sarvam’s specific strength. Deepgram’s Aura-2 voices are mostly English, with a handful in Spanish; Sarvam covers Hindi plus 9 other Indian languages (Bengali, Tamil, Telugu, Kannada, Malayalam, Marathi, Gujarati, Punjabi, Odia), natively tuned for code-mixed input like Hinglish.
Full example
A small wrapper function, before and after, showing the complete set of changes together:
Before (Deepgram)
After (Sarvam)
Common mistakes
Writing the response body directly as an audio file
The single most common migration bug. Deepgram’s REST response is the audio stream itself; Sarvam’s is JSON. Code that does f.write(response.content) unmodified will produce a file full of JSON text, not audio. Decode response.audios[0] from base64 first.
Forgetting target_language_code
It’s required on every request, by design: this is what guarantees Sarvam applies the correct pronunciation and prosody instead of inferring language from a combined model string like Deepgram’s. Include it from the start rather than treating it as optional.
Looking for a bit_rate equivalent
There isn’t one, and that’s fine: pick output_audio_codec for the compression and quality tradeoff you need instead of tuning a separate bitrate value.
Porting a combined voice-and-language model string as-is
A value like aura-2-asteria-en doesn’t map to a single Sarvam field. Split it into model (bulbul:v3) and speaker (a name from the Voices page) instead of trying to find a one-to-one string replacement.
See also
- Migration overview: base URL, auth, and SDK client changes
- Migrating Speech-to-Text
- Which Text-to-Speech API to Use
- TTS Best Practices
- Voices
- Errors & Troubleshooting