Deepgram
Text-to-speech with DeepgramTTSService (Aura over WebSocket), DeepgramHttpTTSService (Aura over HTTP) and DeepgramFluxTTSService (Flux).
Overview
pipedog ports three of Pipecat's Deepgram text-to-speech services:
DeepgramTTSService: Deepgram Aura over a WebSocket (/v1/speak). Streams audio as text arrives and clears Deepgram's buffer on interruption.DeepgramHttpTTSService: Deepgram Aura over HTTP. OnePOSTper sentence, with the audio streamed back in the response body.DeepgramFluxTTSService: Deepgram Flux over a WebSocket (/v2/speak). Streams LLM tokens as they arrive and keeps acoustic state across turns on one connection.
Upstream page
Pipecat's documentation for the same services.
Source
packages/deepgram/src/tts.ts, flux/tts.ts and flux/tts_base.ts.
Deepgram docs
Aura and Flux voices and voice controls.
Installation
bun add @pipedog/deepgramimport { DeepgramHttpTTSService, DeepgramTTSService } from "@pipedog/deepgram/tts";
import { DeepgramFluxTTSService } from "@pipedog/deepgram/flux/tts";Prerequisites
- A Deepgram account and an API key from the Deepgram console. Flux needs a key with Flux TTS access.
- Pass the key as
apiKey. The examples read it fromDEEPGRAM_API_KEY.
DeepgramTTSService
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new DeepgramTTSService.Settings({...}). Any
setting you leave out keeps the default below. DeepgramHttpTTSService uses the same settings
class.
| Setting | Type | Default | Description |
|---|---|---|---|
voice | string | "aura-2-helena-en" | Aura voice. Sent to Deepgram as the model query parameter. |
model | string | null | null | Kept in sync with voice when the voice changes, for metrics. |
language | Language | null | null | Used to split text into sentences. Not sent to Deepgram. |
speed | number | null | null | Speech-rate multiplier, from 0.7 to 1.5. null leaves Aura at its default rate. Aura-2 English and Spanish voices only. |
Usage
import { TTSUpdateSettingsFrame } from "@pipedog/core/frames/frames";
import { TextAggregationMode } from "@pipedog/core/services/tts_service";
import { DeepgramFluxTTSService } from "@pipedog/deepgram/flux/tts";
import { DeepgramHttpTTSService, DeepgramTTSService } from "@pipedog/deepgram/tts";
const tts = new DeepgramTTSService({
apiKey: process.env.DEEPGRAM_API_KEY ?? "",
settings: new DeepgramTTSService.Settings({
voice: "aura-2-helena-en",
speed: 1.1,
}),
});Change settings mid-call with a TTSUpdateSettingsFrame. Any change closes the WebSocket and
reconnects with the new settings:
// Queue it on the worker, or push it from a processor upstream of the service.
// Any change reconnects the WebSocket with the new settings.
const update = new TTSUpdateSettingsFrame({
delta: new DeepgramTTSService.Settings({ voice: "aura-2-thalia-en" }),
});Event handlers
| Event | Description |
|---|---|
on_connected | The WebSocket to Deepgram is open. |
on_disconnected | The WebSocket to Deepgram closed. |
on_connection_error | Connecting failed. Receives the error message. |
on_tts_request | A TTS request is about to be made. Receives the context ID and the text. |
Notes
encodingmust be"linear16","mulaw"or"alaw"; anything else throws in the constructor. The received bytes go intoTTSAudioRawFrames as they are, so only"linear16"plays correctly in a pipedog pipeline.- Text is sent with
Speakmessages. The service sendsFlushwhen the LLM response ends, and emitsTTSStoppedFramewhen Deepgram answers withFlushed. - On interruption it sends
Clear, so Deepgram drops its text buffer and stops sending audio. sampleRatedefaults to the pipeline's output rate.- Aura-2 reads inline pronunciations.
formatPronunciation(word, ipa)renders one as Deepgram's inline object, and returnsnullwhen the IPA is empty or too long for the word (over 128 characters, or over 10 times the word's length with a floor of 15).
DeepgramHttpTTSService
Configuration
Prop
Type
Settings
Same settings and defaults as DeepgramTTSService.
Usage
const httpTts = new DeepgramHttpTTSService({
apiKey: process.env.DEEPGRAM_API_KEY ?? "",
settings: new DeepgramHttpTTSService.Settings({ voice: "aura-2-helena-en" }),
});Notes
- Each request is a
POSTto{baseUrl}/v1/speakwithcontainer=none. A status other than 200 becomes anErrorFramewith the response body. - The response body is read as a stream and cut into sample-aligned
TTSAudioRawFrames, so audio starts before the whole response has arrived. - Upstream requires an
aiohttp_session. Herefetchis optional and defaults to the globalfetch.
DeepgramFluxTTSService
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new DeepgramFluxTTSService.Settings({...}).
| Setting | Type | Default | Description |
|---|---|---|---|
voice | string | "flux-heather-en" | Flux voice, flux-{voice}-{language}. Sent as the model query parameter. |
model | string | null | synced to voice | Always set to voice, for metrics. |
language | Language | null | null | Used to split text into sentences. Not sent to Deepgram. |
speed | number | null | null | Speech-rate multiplier, 0.5 to 1.5 in steps of 0.05. null leaves Flux at its default rate. |
expressivity | -2 | -1 | 0 | 1 | 2 | null | null | Expressive range, calm to animated. null leaves Flux at its default range. |
Usage
const fluxTts = new DeepgramFluxTTSService({
apiKey: process.env.DEEPGRAM_API_KEY ?? "",
settings: new DeepgramFluxTTSService.Settings({
voice: "flux-alexis-en",
speed: 1.05,
expressivity: 1,
}),
});
fluxTts.addEventHandler("on_connection_error", async (_service, error: string) => {
console.error("Flux connection error:", error);
});Flux streams LLM tokens by default (TextAggregationMode.TOKEN). To aggregate text into
sentences first:
// Aggregate text into sentences instead of streaming LLM tokens.
const fluxSentences = new DeepgramFluxTTSService({
apiKey: process.env.DEEPGRAM_API_KEY ?? "",
textAggregationMode: TextAggregationMode.SENTENCE,
});A speed change is applied to the open connection with a Flux Configure message, so the
cross-turn acoustic state is kept. Any other change (voice, expressivity, language)
reconnects:
// A speed change is sent on the open connection with a Configure message.
const fluxSpeed = new TTSUpdateSettingsFrame({
delta: new DeepgramFluxTTSService.Settings({ speed: 0.9 }),
});Event handlers
| Event | Description |
|---|---|
on_connected | The WebSocket to Flux is open. |
on_disconnected | The WebSocket to Flux closed. |
on_connection_error | Connecting failed, or the receive loop reported an error. Receives the error message. |
on_tts_request | A TTS request is about to be made. Receives the context ID and the text. |
Notes
- Audio is always requested as
linear16. Supported sample rates are 8000, 16000, 24000, 32000, 44100 and 48000 Hz. Another rate only logs a warning on connect. - On interruption the service sends
Interrupt, which ends the active turn without closing the connection.Flushends a turn when the LLM response is done. - Clearing
speed(setting it tonull) sendsConfigurewithspeed: 1.0, Flux's default. - Disconnecting closes the socket without a
Closemessage: in Flux,Closeasks the server to finish the active turn's audio first. formatPronunciationis left at the base implementation, so words are spoken as written. Flux rejects inline pronunciations on a connection whose speed is not 1.0.tagadds onetagquery parameter per entry, for Deepgram usage reports.
Runtime notes
| Runtime | Works | What it needs |
|---|---|---|
| Bun | ✅ yes | Nothing. |
| Node.js | ✅ yes | Nothing. |
| Deno | ✅ yes | Nothing. |
| Cloudflare Workers | ✅ yes | Nothing. |
Generated from pipecat.runtimes and pipecat.compat in packages/deepgram/package.json: ✅ means the compat smoke test passes on that runtime.
DeepgramTTSService and DeepgramFluxTTSService use the global WebSocket and send the key as an
Authorization: Token <key> header on the handshake. That works on Bun, Node, Deno and Cloudflare
Workers (where the socket is opened through fetch). Pass webSocketFactory to open the socket
some other way, through a proxy for example. A standard WebSocket does not expose the handshake's
response headers, so the dg-* headers upstream logs on connect are not available.
DeepgramHttpTTSService only needs fetch, available on all four runtimes.
Query values use JS number formatting, so speed: 1.0 is sent as speed=1. The deprecated
voice constructor option is not ported; use settings.voice.
Not ported yet: DeepgramSageMakerTTSService and DeepgramFluxSageMakerTTSService (AWS
SageMaker endpoints).
pipedog is an unofficial community TypeScript port of Pipecat. It is not affiliated with or endorsed by Daily or the Pipecat project.
Portions adapted from the Pipecat documentation, Copyright (c) 2024–2025 Daily, BSD-2-Clause (see apps/docs/LICENSE-pipecat-docs).
Text-to-speech with GoogleTTSService (Cloud TTS streaming), GoogleHttpTTSService (Cloud TTS with SSML) and GeminiTTSService (Gemini TTS models).
Cloudflare Workers AI
Text-to-speech on Workers AI: Deepgram Aura streaming over a WebSocket or per sentence over HTTP, and MeloTTS, over the AI binding or the REST API.