Synthesize once.
Replay from cache.

tts-cache-router sits between your voice agent and Sarvam, Raya or ElevenLabs, using your own provider key. A sentence your agent has said before, in the same voice, plays back as the provider’s own take, without calling the provider again.

One reply, said twice

A real run: Sarvam bulbul:v3, voice shubh

First time

206 characters billed

SourceSentenceStarts at
  1. providerनमस्ते, मैं सिटी हॉस्पिटल से प्रिया बोल रही हूँ।422 ms
  2. providerआपका अपॉइंटमेंट डॉक्टर शर्मा के साथ गुरुवार सुबह दस बजे है।873 ms
  3. providerPlease carry your previous reports and arrive fifteen minutes early.1538 ms
  4. providerक्या यह समय आपके लिए ठीक रहेगा?2192 ms

Said again

0 characters billed

SourceSentenceStarts at
  1. cacheनमस्ते, मैं सिटी हॉस्पिटल से प्रिया बोल रही हूँ।6 ms
  2. cacheआपका अपॉइंटमेंट डॉक्टर शर्मा के साथ गुरुवार सुबह दस बजे है।8 ms
  3. cachePlease carry your previous reports and arrive fifteen minutes early.9 ms
  4. cacheक्या यह समय आपके लिए ठीक रहेगा?10 ms

Repeated sentences start in milliseconds

Greetings, confirmations and disclosures your agent says again play from cache, with no round trip to the provider. Above, the first sentence started after 6 ms instead of 422 ms.

Your key, your bill, fewer characters on it

Save your Sarvam, Raya or ElevenLabs key once; it’s stored encrypted and used only for your own requests. The provider bills you directly, and only for the sentences it actually synthesized.

Hindi replies start at the first sentence

The router’s splitter ends a sentence at the Hindi full stop as well as at English punctuation, so a Hindi reply starts speaking after its first sentence, not after a full stop that never comes.

Providers

  • Sarvambulbul:v3, bulbul:v4-flash
  • Rayastandard, m1
  • ElevenLabsFlash, Turbo, Multilingual, v3, v4
Every model, voice and setting

How it works

One sentence at a time, in the order you wrote it.

  • Split as it streams

    The router cuts your agent’s streamed reply into sentences and sends each one on the moment it’s complete.

  • Looked up by everything that shapes the voice

    The exact text and every setting the provider receives: model, voice, language, speed, sample rate, format and options. Entries belong to your org and never play for another.

  • A hit plays at once. A miss streams as it arrives.

    A hit never contacts the provider. A miss goes to the provider with your key and streams to your agent as it’s produced.

  • Always in order, even when interrupted

    Sentences play in the order your agent wrote them. On barge-in the audio stops, and a sentence already sent still finishes and is cached.

The promise

Same output whether you call the provider directly or through us.

Two identical requests to a TTS provider never return identical audio, so caching can’t mean “close enough.” It has to mean the provider’s own take, for exactly what you asked.

Your text, verbatim

Each sentence reaches the provider exactly as your agent wrote it.

  • Only whitespace is normalized
  • Case and punctuation are kept, because they change how a sentence is spoken

Every setting, unchanged

The settings you choose reach the provider as you set them.

  • Model, voice, language, speed and sample rate
  • Sarvam’s temperature and pronunciation dictionary

Real, complete takes

A hit replays audio the provider made for that exact request.

  • Never spliced, re-encoded or altered
  • A sentence cut off by an error or timeout is never stored

LiveKit Agents

A drop-in TTS for your LiveKit agent.

Swap your agent’s tts= for the plugin and keep everything else.

  • Transcripts stay in step with speech, sentence by sentence
  • Usage metrics count only the characters your provider billed
  • Metrics name the real provider and model, so cost lands in the right place
Terminal
pip install livekit-plugins-tts-cache-routerexport TTS_CACHE_ROUTER_API_KEY=tcr_…   # from your dashboard# Your Sarvam, Raya or ElevenLabs key goes in the dashboard, once.
agent.py
from livekit.agents import AgentSessionfrom livekit.plugins import tts_cache_routertts = tts_cache_router.TTS(    provider=tts_cache_router.Sarvam(        model="bulbul:v3",        speaker="shubh",        language="hi-IN",    ),)session = AgentSession(tts=tts, ...)

How to connect

Three ways in, one cache behind them.

Save your provider key in the dashboard once, then connect with your router API key in whichever way your agent already speaks.

LiveKit plugin

A TTS for LiveKit Agents over the router’s WebSocket. Sentence-aligned transcripts, warm connections kept across barge-ins.

tts_cache_router.TTS(  provider=tts_cache_router.Sarvam(    model="bulbul:v3",    speaker="shubh",    language="hi-IN",  ),)
Read the guide

OpenAI-style HTTP

POST /v1/audio/speech, shaped like OpenAI’s. Use the OpenAI SDK with base_url api.ttscacherouter.dev/v1; audio streams back sentence by sentence.

client.audio.speech.create(  model="sarvam/bulbul:v3",  voice="shubh",  input=text,  extra_body={"language": "hi-IN"},)
Read the guide

Your provider’s own API

Sarvam’s, Raya’s and ElevenLabs’ APIs, mirrored under api.ttscacherouter.dev/sarvam, /raya and /elevenlabs. Keep your client; change only the base URL and the key.

raya.TTS(  voice_id="d6a002d0-…",  base_url="https://api.ttscacherouter.dev/raya",  api_key="tcr_…",)
Read the guide

Pricing

Pay for what the cache serves.

Every new org gets $10 of credit, about 5 million cached characters, with no card. After that, buy prepaid credit from $10. It never expires.

Pricing and billing in the docs
Served from the cache
$0.002
per 1,000 characters. A 50-character sentence costs $0.0001.
Synthesized by your provider
$0
from us. Your provider bills it to your own key, at your own rates.

FAQ

Before you switch.

Something not covered here? Write to us.

How long is audio kept?

365 days by default. Change your org’s retention in the dashboard, in days, or set it to 0 and nothing new is stored. Retention counts from when the audio was made; playing it doesn’t extend it. Audio is deleted within about a day after its retention ends, and a change applies to audio already cached.

What happens if the cache is down?

Your agent keeps speaking. The router sends every sentence to the provider until the cache is back, so a lost cache costs provider calls, never correctness.

Can I use it without LiveKit?

Yes. Call POST /v1/audio/speech with the OpenAI SDK, point your Sarvam, Raya or ElevenLabs client at the drop-in endpoints, or speak the WebSocket protocol from any language.

Open source.
Hosted, or on your own servers.

Use the hosted router with an API key, or run the router and its cache yourself with one Docker Compose stack, and this website as a static site.