Original Reddit post

​ Indic voice AI doesn’t have a quality problem. It has a switching-cost problem. If you run an IVR, a collections bot, or a vernacular tutoring app in India, you’re probably paying an international provider for voice that was never designed for Hindi, Tamil, or Hinglish code-mixing. You know Sarvam’s Bulbul and Saaras handle your users’ languages better. You’ve probably tested them.Then you open the migration guide, estimate two engineer-weeks, and it goes on the backlog forever. Here’s what convinced me this is the real bottleneck: Sarvam maintains four separate hand-written migration guides — ElevenLabs, Cartesia, Deepgram, Gemini. Four documents whose entire purpose is helping someone rewrite working code. And the ElevenLabs one ends with a section called “Common mistakes” listing five bugs, one of which they describe as "the single most common migration bug."That’s not a warning. That’s a spec for missing infrastructure. What I built sarvam-bridge speaks each vendor’s dialect on the front and Sarvam on the back. Change your base URL, keep your code. Every one of those five documented mistakes becomes structurally impossible: ElevenLabs returns raw bytes; Sarvam returns base64 in JSON → bridge decodes it. Sarvam requires language_code; no other vendor’s client sends one → bridge detects it from the Unicode script. pitch/loudness silently no-op on bulbul:v3 → bridge drops them with a warning header. 2500 char limit → bridge chunks at the danda (।), not mid-word. v2 and v3 speaker names aren’t interchangeable → bridge validates and remaps. The Indic-specific parts that were genuinely hard Chunking. You can’t chunk Indic text the way you chunk English. A splitter that only knows . treats an entire Hindi paragraph as one sentence, because Hindi ends sentences with the danda. Worse — slicing a JS string by index can separate a consonant from its matra. क and ि come apart, the text renders as garbage and the speech comes out wrong. Hard splits go through Intl.Segmenter at grapheme granularity. Audio reassembly. Chunking means one WAV back per chunk. Buffer.concat leaves 44-byte RIFF headers sitting in the middle of your stream, which decoders play as audible clicks. Have to parse each container, extract PCM, write one header. The Odia trap. ISO-639 calls it or. Sarvam expects od-IN. Send the wrong one, get a 400 with no hint which field was wrong. Cost me an hour. Voice selection. Sarvam publishes per-language speaker quality by Critical Error Rate and I don’t think many people use it. mani for Punjabi male, ratan for English, shubh for Hindi/Telugu/Kannada. My favourite detail — varun has a great CER but Sarvam flags it as a villain/suspense character voice, so it’s excluded from auto-selection. Fine in a thriller, catastrophic in a banking IVR. Cost thing worth knowing IVR menus and agent scripts synthesise the same strings thousands of times a day, each billable, each returning byte-identical audio. Cache handles sequential duplicates. But a burst — broadcast goes out, 300 callers hit the same prompt in one second — all miss the cache because none has populated it yet. Single-flight coalescing collapses those into one upstream call. Measured with cache disabled: 100 simultaneous identical requests → 1 upstream call. Then stress testing found six bugs in my own code Including a remote DoS: a voice ID with Devanagari or an emoji crashed the process, because Node throws on non-latin1 header values and I was echoing caller input into a warning header. Ordinary Indian-language input was a crash vector. And a test that passed for the wrong reason — the cache was masking the thing I was actually testing. Green isn’t the same as correct. 168 tests now, zero 5xx across 3,500 hostile requests, 0 dependency CVEs. MIT, not affiliated with Sarvam, built against public docs: https://github.com/thekartikeyamishra/sarvam-bridge Would genuinely value corrections if anyone here knows the Sarvam API better than I do. submitted by /u/iamrealadvait

Originally posted by u/iamrealadvait on r/ArtificialInteligence