Metadata-Version: 2.5
Name: pipecat-tts-cache-router
Version: 0.8.0
Summary: Pipecat TTS service for tts-cache-router (https://ttscacherouter.dev), a caching TTS router for Maya Open-Source, Sarvam, Raya, ElevenLabs, OpenAI, Deepgram, xAI, Soniox, Smallest AI, Cartesia, Gemini and 60db
Project-URL: Homepage, https://ttscacherouter.dev
Project-URL: Documentation, https://docs.ttscacherouter.dev/pipecat
Project-URL: Source, https://github.com/talqing/tts-cache-router
Project-URL: Changelog, https://github.com/talqing/tts-cache-router/blob/main/plugin/pipecat-tts-cache-router/CHANGELOG.md
Author: Oggnai Technologies Private Limited
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: 60db,ai,audio,cache,cartesia,deepgram,elevenlabs,gemini,maya,openai,pipecat,raya,realtime,router,sarvam,smallestai,soniox,tts,voice,xai
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Requires-Dist: pipecat-ai>=1.12.0
Description-Content-Type: text/markdown

# pipecat-tts-cache-router

[Pipecat](https://github.com/pipecat-ai/pipecat) TTS service for
[tts-cache-router](https://ttscacherouter.dev): Maya Open-Source (hosted by the router, no key
needed), Sarvam, Raya, ElevenLabs, OpenAI, Deepgram, xAI, Soniox, Smallest AI, Cartesia, Gemini and
60db text-to-speech, with every sentence your bot has said before served from a per-account cache.

Same output whether you call the provider directly or through the router: each sentence reaches
the provider verbatim with your exact settings, and a cache hit replays a real provider take for
that exact request.

Full documentation: [docs.ttscacherouter.dev/pipecat](https://docs.ttscacherouter.dev/pipecat). For
LLMs and coding agents: [llms.txt](https://docs.ttscacherouter.dev/llms.txt), and this page as
Markdown at [pipecat.md](https://docs.ttscacherouter.dev/pipecat.md).

Tested with Pipecat v1.12.0. Maintained by Oggnai Technologies, the company that runs
tts-cache-router.

## Install

```bash
pip install pipecat-tts-cache-router
```

## Usage

```python
import os

from pipecat_tts_cache_router import TTSCacheRouterTTSService

tts = TTSCacheRouterTTSService(
    api_key=os.environ["TTS_CACHE_ROUTER_API_KEY"],
    settings=TTSCacheRouterTTSService.Settings(
        model="maya/maya-2-native", voice="Ahana", language="hi"
    ),
)

pipeline = Pipeline(
    [transport.input(), stt, user_aggregator, llm, tts, transport.output(), assistant_aggregator]
)
```

Maya Open-Source runs on the router's own GPUs and needs no provider key. For any other provider,
give its model and voice (e.g. `model="sarvam/bulbul:v3", voice="shubh", language="hi-IN"`), and
before the first request store your Sarvam, Raya, ElevenLabs, OpenAI, Deepgram, xAI, Soniox,
Smallest AI, Cartesia, Gemini or 60db API key in the dashboard at
[ttscacherouter.dev](https://ttscacherouter.dev/dashboard/provider-keys). The router keeps it
encrypted and uses it only to call that provider for your requests. Your bot authenticates with
your router API key alone, from the same dashboard.

### `TTSCacheRouterTTSService(...)`

| Argument | Default | |
|---|---|---|
| `api_key` | required | your router API key |
| `settings` | required | `TTSCacheRouterTTSService.Settings(...)`, below |
| `base_url` | `wss://api.media.ttscacherouter.dev` | the router for every provider; your own router when self-hosting (locally `ws://localhost:8090`) |
| `sample_rate` | the pipeline's output rate | one the provider streams: 8000, 16000, 22050 or 24000 for most (Maya Open-Source, OpenAI and Gemini: 24000 only); see [Models and options](https://docs.ttscacherouter.dev/reference/models) |

Other keyword arguments go to Pipecat's `WebsocketTTSService`, except `text_aggregation_mode`: the
router splits the text into sentences itself, so the service streams the LLM's text to it as it
arrives.

### `TTSCacheRouterTTSService.Settings(...)`

The settings are in the router's own names, the same for every provider:

| Setting | | |
|---|---|---|
| `model` | required | `"<provider>/<model>"`: `"maya/maya-2-native"`, `"sarvam/bulbul:v3"`, `"raya/standard"`, `"elevenlabs/eleven_flash_v2_5"`, `"openai/gpt-4o-mini-tts"`, `"deepgram/aura-2"`, `"xai/xai-tts"`, `"soniox/tts-rt-v2"`, `"smallestai/lightning_v3.1_pro"`, `"cartesia/sonic-3"`, `"gemini/gemini-3.8-flash-tts"`, `"60db/60db-fast-v01"`, … |
| `voice` | required | the provider's voice id (`GET /v1/voices` lists them); `None` for a Gemini multi-speaker voice, whose `options["speakers"]` names the voices |
| `language` | `None` | the provider's own language code, where it takes one (`"hi"` for Maya Open-Source and Raya, `"hi-IN"` for Sarvam, `"en"` for the rest) |
| `speed` | `None` | the speaking rate, where the provider takes one |
| `options` | `{}` | the provider's other settings, e.g. `{"temperature": 0.6}` for Sarvam, `{"voice_settings": {"stability": 0.5}}` for ElevenLabs, `{"instructions": "Speak warmly."}` for OpenAI |
| `split` | `"sentences"`, or your org's setting | `"sentences"`: each sentence of a reply is synthesized and cached on its own, and the first plays as soon as the LLM has written it. `"none"`: the whole reply is one request and one cache entry, synthesized once all its text has arrived, so its audio starts only after the LLM has finished; for fixed lines, such as a greeting spoken with a `TTSSpeakFrame`. Left out, your org's setting for the provider in the dashboard decides (`"sentences"` unless you changed it) |

Every provider's models, voices, languages and options are in
[Models and options](https://docs.ttscacherouter.dev/reference/models). The router checks the
settings when the pipeline starts, so a wrong one is reported then as an `ErrorFrame`.

### Hosted router

With no `base_url`, the service connects to the hosted router, `wss://api.media.ttscacherouter.dev`
in Mumbai, India, for every provider, with one cache. `wss://api.in.ttscacherouter.dev` and
`wss://api.us.ttscacherouter.dev` reach the same router and keep working.

### Changing settings mid-session

```python
from pipecat.frames.frames import TTSUpdateSettingsFrame

await worker.queue_frame(
    TTSUpdateSettingsFrame(delta=TTSCacheRouterTTSService.Settings(voice="priya"))
)
```

Replies that start afterwards use the new settings. A `model` of another provider starts from no
`language`, `speed` or `options` unless the update gives them.

### Interruptions

When the user interrupts, the service tells the router to stop the reply, and the provider stops
the sentence it was synthesizing. The next reply starts on the same connection.

### Transcripts

The service's `TTSTextFrame`s follow the audio: each sentence's words as its audio starts, or word
by word with ElevenLabs and Cartesia.

### Metrics

With usage metrics on, each reply's `TTSUsageMetricsData` counts only the characters the provider
synthesized (and billed); sentences served from the cache count zero. Its `model` is
`"<provider>/<model>"`.

Once a reply is all sent, the service also calls its `on_cache_stats` handlers with a `CacheStats`:
the reply's `context_id`, `sentences`, `cached_sentences`, `characters` and `billed_characters`
(and `cached_characters`, the difference):

```python
@tts.event_handler("on_cache_stats")
async def on_cache_stats(tts, stats):
    print(stats.cached_sentences, "of", stats.sentences, "sentences from the cache")
```

An interrupted reply reports both too, counting the sentences the router sent in full before the
interruption. This needs a router that reports them (the hosted router does); with an older one, the
service logs an error and reports nothing for the interrupted reply.

## Example

[`examples/pipecat_agent.py`](https://github.com/talqing/tts-cache-router/blob/main/examples/pipecat_agent.py)
is a complete bot: Deepgram speech-to-text, an OpenAI LLM and this service, on Pipecat's local
WebRTC runner. With `TTS_CACHE_ROUTER_API_KEY`, `DEEPGRAM_API_KEY` and `OPENAI_API_KEY` set:

```bash
cd examples
uv run pipecat_agent.py
```

Then open http://localhost:7860/client and talk to it.

## License

Apache-2.0.
