Camb.ai
Text-to-speech with Camb.ai's MARS models: CambTTSService streams PCM audio over HTTP.
Overview
CambTTSService posts each sentence to Camb.ai's tts-stream endpoint and pushes the streamed 16-bit PCM, kept aligned to whole samples. Models: mars-flash (fast, 22.05 kHz, the default), mars-pro (high quality, 48 kHz) and mars-instruct (22.05 kHz, takes instructions for tone and style).
Upstream page
Pipecat's documentation for the same service.
Source
packages/camb/src/tts.ts.
Camb.ai docs
The streaming TTS endpoint reference.
Installation
bun add @pipedog/cambimport { CambTTSService } from "@pipedog/camb/tts";Prerequisites
- A Camb.ai account and an API key.
- Pass the key as
apiKey. The examples read it fromCAMB_API_KEY.
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new CambTTSService.Settings({...})
(CambTTSSettings). Any setting you leave out keeps the default below.
| Setting | Type | Default | Description |
|---|---|---|---|
model | string | "mars-flash" | mars-flash, mars-pro or mars-instruct. |
voice | number | 147320 | Voice id. Camb.ai uses integer ids. |
language | Language | string | "en-us" | Language, as a lowercase BCP-47 tag. |
userInstructions | string | null | null | Instructions for mars-instruct only, up to 1000 characters. Ignored by the other models. |
Usage
import { CambTTSService } from "@pipedog/camb/tts";
import { TTSUpdateSettingsFrame } from "@pipedog/core/frames/frames";
// mars-flash (22.05 kHz) is the default; mars-pro renders at 48 kHz.
const tts = new CambTTSService({
apiKey: process.env.CAMB_API_KEY ?? "",
settings: new CambTTSService.Settings({ model: "mars-pro", voice: 147320 }),
});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 CambTTSService.Settings({ voice: 12345 }),
});Notes
- Without a
sampleRate, the service uses the model's: 22050 Hz formars-flashandmars-instruct, 48000 Hz formars-pro. AsampleRatethat differs from the model's logs a warning. - Text over 3000 characters is truncated.
timeout(60 seconds by default, the minimum Camb.ai recommends) limits the wait for the response and the wait for each chunk of audio.
Runtime notes
- Upstream uses Camb's Python SDK. That SDK is a thin client over one endpoint, so this port sends the same request (
POST /tts-streamwith anx-api-keyheader) with the globalfetch, which works on Bun, Node, Deno and Cloudflare Workers.baseUrlandfetchare not upstream options. - The deprecated
params(InputParams),voiceIdandmodeloptions are not ported. Usesettings. - Upstream has no Camb.ai tests. Ours run against a local fake server, not against Camb.ai itself.
| 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/camb/package.json: ✅ means the compat smoke test passes on that runtime.
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).