pipedog is an unofficial community port of Pipecat, not affiliated with Daily.
pipedog
Text-to-speech

Cartesia

Text-to-speech with CartesiaTTSService (WebSocket, word timestamps) and CartesiaHttpTTSService (HTTP), configured with GenerationConfig.

Overview

Cartesia's Sonic models turn text into speech. pipedog ports both of Pipecat's Cartesia text-to-speech services:

  • CartesiaTTSService: streams over Cartesia's WebSocket API. Audio arrives as it is generated, with word-level timestamps that keep the spoken text in step with playback.
  • CartesiaHttpTTSService: posts each request to Cartesia's /tts/bytes HTTP endpoint and gets the audio back in one piece, without word timestamps.
  • GenerationConfig: volume, speed and emotion for sonic-3 series models, shared by both.

Installation

bun add @pipedog/cartesia
import {
  CartesiaEmotion,
  CartesiaHttpTTSService,
  CartesiaTTSService,
  GenerationConfig,
} from "@pipedog/cartesia/tts";

Prerequisites

  • A Cartesia account and an API key from the Cartesia playground.
  • A voice id from the Cartesia voice library. There is no default voice.
  • Pass the key as apiKey. The examples read it from CARTESIA_API_KEY.

CartesiaTTSService

Configuration

Prop

Type

Settings

Runtime-updatable settings, passed as settings: new CartesiaTTSService.Settings({...}). Both services use the same settings class.

SettingTypeDefaultDescription
modelstring"sonic-3.6"Cartesia TTS model.
voicestring | nullnullVoice id. Set one: there is no default.
languageLanguageLanguage.ENSynthesis language.
accentstring | nullnullAccent a multilingual voice speaks the language with, from the accents of Cartesia's Get Voice response. null lets Cartesia pick.
generationConfigGenerationConfig | nullnullVolume, speed and emotion. See below.
pronunciationDictIdstring | nullnullCartesia pronunciation dictionary id.

GenerationConfig

Prop

Type

Fields left null are not sent. CartesiaEmotion lists the emotion names Cartesia supports.

Usage

tts.ts
import {
  CartesiaEmotion,
  CartesiaHttpTTSService,
  CartesiaTTSService,
  GenerationConfig,
} from "@pipedog/cartesia/tts";
import { TTSUpdateSettingsFrame } from "@pipedog/core/frames/frames";
import { TextAggregationMode } from "@pipedog/core/services/tts_service";
import { Language } from "@pipedog/core/transcriptions/language";

const tts = new CartesiaTTSService({
  apiKey: process.env.CARTESIA_API_KEY ?? "",
  settings: new CartesiaTTSService.Settings({
    voice: "your-voice-id",
    model: "sonic-3.6",
    language: Language.EN,
  }),
});

Token streaming and a generation config:

const expressive = new CartesiaTTSService({
  apiKey: process.env.CARTESIA_API_KEY ?? "",
  // Stream LLM tokens straight to Cartesia instead of waiting for whole sentences.
  textAggregationMode: TextAggregationMode.TOKEN,
  settings: new CartesiaTTSService.Settings({
    voice: "your-voice-id",
    generationConfig: new GenerationConfig({ speed: 1.1, emotion: CartesiaEmotion.EXCITED }),
  }),
});

SSML tag helpers and IPA pronunciations:

// Helpers that build Cartesia SSML tags, for use in text transforms.
const spelled = CartesiaTTSService.SPELL("A1B2");
const tagged = `${CartesiaTTSService.EMOTION_TAG(CartesiaEmotion.CALM)} One moment.${CartesiaTTSService.PAUSE_TAG(0.5)}`;

// Say words as IPA describes. Register it last in textTransforms.
const pronounce = CartesiaTTSService.pronunciationTransformIpa({ Metformin: "mɛtˈfɔɹmɪn" });
const withPronunciations = new CartesiaTTSService({
  apiKey: process.env.CARTESIA_API_KEY ?? "",
  settings: new CartesiaTTSService.Settings({ voice: "your-voice-id" }),
  textTransforms: [["*", pronounce]],
});

Change settings mid-call with a TTSUpdateSettingsFrame:

// Queue it on the worker, or push it from a processor upstream of the service.
const update = new TTSUpdateSettingsFrame({
  delta: new CartesiaTTSService.Settings({ voice: "another-voice-id", language: Language.ES }),
});

Event handlers

Inherited from TTSService:

EventDescription
on_connectedConnected to Cartesia.
on_disconnectedDisconnected from Cartesia.
on_connection_errorThe connection failed.
on_tts_requestA text chunk is about to be sent for synthesis.

Notes

  • The service does not push the LLM's text frames itself. It builds TTSTextFrames from Cartesia's word timestamps, so the context only records words the user actually heard.
  • Text is aggregated into sentences by default. TextAggregationMode.TOKEN streams tokens directly for lower latency.
  • maxBufferDelayMs sets Cartesia's server-side buffer. Left null, it is 0 in sentence mode (no double buffering) and unset in token mode (Cartesia's 3000 ms default).
  • A voice, model or language change takes effect from the next sentence, which opens a new Cartesia context.
  • Static helpers build Cartesia SSML tags for text transforms: SPELL, EMOTION_TAG, PAUSE_TAG, VOLUME_TAG and SPEED_TAG. Text inside <spell> tags is never split across aggregates.
  • pronunciationTransformIpa() turns IPA into Cartesia inline phonemes. Register it last in textTransforms so later transforms don't rewrite its markup.

CartesiaHttpTTSService

Configuration

Prop

Type

Settings

Same as CartesiaTTSService, with the same defaults.

Usage

http.ts
const httpTts = new CartesiaHttpTTSService({
  apiKey: process.env.CARTESIA_API_KEY ?? "",
  settings: new CartesiaHttpTTSService.Settings({ voice: "your-voice-id" }),
});

Notes

  • Each request returns its audio in one piece. Use it when streaming does not matter.
  • baseUrl defaults to "https://api.cartesia.ai".

Runtime notes

RuntimeWorksWhat it needs
Bun✅ yesNothing.
Node.js✅ yesNothing.
Deno✅ yesNothing.
Cloudflare Workers✅ yesNothing.

Generated from pipecat.runtimes and pipecat.compat in packages/cartesia/package.json: ✅ means the compat smoke test passes on that runtime.

  • CartesiaTTSService uses the global WebSocket and sends the key as an X-API-Key header on the handshake. The Bun, Node and Deno WebSocket support handshake headers, and on Cloudflare Workers the socket is opened through fetch.
  • CartesiaHttpTTSService uses the global fetch unless you pass fetch. That option replaces upstream's aiohttp_session.
  • The Cartesia API version header is pinned to 2026-03-01. Upstream's cartesia_version option is not ported.
  • Not ported: the deprecated voiceId, model, params (InputParams) and aggregateSentences constructor options. Use settings and textAggregationMode.

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).

On this page