Other clients
Deepgram API drop-in
Deepgram's own speak APIs, Aura and Flux, through the cache: keep the Deepgram SDK, change the base URL and key.
Deepgram's Python SDK#
Deepgram’s speak APIs, mirrored under https://api.ttscacherouter.dev/deepgram: /v1/speak (Aura) and /v2/speak (Flux), REST and WebSocket. Keep the Deepgram SDK: give it the router as its environment and your router API key as its api_key.
import asyncioimport osfrom deepgram import AsyncDeepgramClientfrom deepgram.environment import DeepgramClientEnvironmentasync def main(): client = AsyncDeepgramClient( api_key=os.environ["TTS_CACHE_ROUTER_API_KEY"], environment=DeepgramClientEnvironment( base="https://api.ttscacherouter.dev/deepgram", production="wss://api.ttscacherouter.dev/deepgram", agent="wss://agent.deepgram.com", agent_rest="https://agent.deepgram.com", ), ) with open("speech.mp3", "wb") as f: async for chunk in client.speak.v1.audio.generate( text="Your order has shipped. It arrives on Friday.", model="aura-2-thalia-en", ): f.write(chunk)asyncio.run(main())speak.v1 and speak.v2, REST (audio.generate) and WebSocket (connect), work through the router with every model, voice, encoding and setting. Requests are forwarded as you sent them, with the Deepgram key stored under Provider keys; your key goes in Authorization: Token, as Deepgram’s does. For a LiveKit agent, see Deepgram with LiveKit.
REST#
POST /deepgram/v1/speak: Aura. The audio in the encoding and container the query asks for, with Deepgram’s ownContent-Type.POST /deepgram/v2/speak: Flux, batch.
Any other path under /deepgram answers 404.
curl -N "https://api.ttscacherouter.dev/deepgram/v1/speak?model=aura-2-thalia-en&encoding=linear16&container=none&sample_rate=24000" \ -H "Authorization: Token $TTS_CACHE_ROUTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"text": "Your order has shipped."}' \ --output speech.pcmcurl -N "https://api.ttscacherouter.dev/deepgram/v2/speak?model=flux-alexis-en" \ -H "Authorization: Token $TTS_CACHE_ROUTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"text": "Your order has shipped."}' \ --output speech.mp3WebSocket#
wss://api.ttscacherouter.dev/deepgram/v1/speak: Aura’s streaming API. SendSpeaktext andFlush; you get the audio as binary messages,Flushedafter each flush’s audio,ClearedafterClear.wss://api.ttscacherouter.dev/deepgram/v2/speak: Flux. Each turn (the text up to aFlush) getsSpeechStarted, its audio,FlushedandSpeechMetadata;Interrupt,ConfigureandClosework as at Deepgram.
The router splits your text into sentences and serves each sentence from the cache or synthesizes it at Deepgram, so the messages are Deepgram’s with these differences:
- Audio for a sentence starts once the sentence is complete. Deepgram’s Aura starts at a comma.
- Aura’s opening
Metadataand Flux’sConnectedcarry the router’s own request and model ids, andmodel_versionisunknown: no Deepgram request exists yet when you connect. A Flux turn’sspeech_idis the router’s own too. - A Flux turn’s
SpeechMetadatacovers the whole turn.billable_character_countcounts only the sentences Deepgram synthesized: sentences served from the cache cost nothing at Deepgram. SpeechInterruptedsplits the turn’s text intotext_spokenandtext_remainingat sentence boundaries: a sentence whose audio had started playing atplayback_offsetcounts as spoken.Configureapplies to the sentences after it.- Aura’s limit of 20 flushes a minute doesn’t apply.
- A failure at Deepgram (a wrong voice, your Deepgram quota) arrives as an
Errormessage once a sentence needs Deepgram, then the router closes the connection (code 1011). A connection idle for 30 minutes is closed.
What is cached#
- REST: each request as a whole. The same query and text again replays the same audio.
- WebSocket: each sentence, so a sentence you have sent before with the same settings comes from the cache whatever came around it. Aura’s sentences share the cache with the router’s own /v1/stream and REST requests with the same settings.
- A reply from the cache carries only
Content-Type: no Deepgram request produced it, so there are nodg-*headers. - Aura: the first sentence of a reply after a pause of about five seconds or more takes about 0.7–1.2 s longer to start than Deepgram’s own WebSocket, because Deepgram closes idle connections and the router opens a new one. Sentences from the cache, and Flux, start as fast as ever.
Errors#
A wrong or missing router key gets Deepgram’s own refusal, HTTP 401, on REST and at the WebSocket handshake. So does an org with no Deepgram key stored, with a message that links to the dashboard. Errors from Deepgram, such as a model your Deepgram project can’t use, reach you as Deepgram sent them.
HTTP/1.1 401 Unauthorized{"err_code": "INVALID_AUTH", "err_msg": "Invalid credentials.", "request_id": null}