xAI
Text-to-speech with xAI: XAITTSService over WebSocket, with word timestamps, and XAIHttpTTSService over HTTP.
Overview
XAITTSService: streams text over a WebSocket and pushes audio as it arrives, with word timestamps from xAI's character timings.XAIHttpTTSService: one HTTP request per sentence.
Upstream page
Pipecat's documentation for the same service.
Source
packages/xai/src/tts.ts.
xAI docs
The voice API reference.
Installation
bun add @pipedog/xaiimport { XAITTSService, XAIHttpTTSService } from "@pipedog/xai/tts";Prerequisites
- An xAI account and an API key from the xAI console.
- Pass the key as
apiKey. The examples read it fromXAI_API_KEY.
XAITTSService
Connects to wss://api.x.ai/v1/tts.
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new XAITTSService.Settings({...})
(XAIWebsocketTTSSettings). Any setting you leave out keeps the default below.
| Setting | Type | Default | Description |
|---|---|---|---|
model | string | null | null | Speech model. null leaves xAI's default. |
voice | string | "eve" | Voice. |
language | Language | null | Language.EN | Language; null sends "auto". |
speed | number | null | null | Speed, 0.7 to 1.5. |
optimizeStreamingLatency | number | null | null | Latency optimization level: 0, 1 or 2. |
textNormalization | boolean | null | null | Normalize the text before synthesis. |
withTimestamps | boolean | true | Word timestamps, pushed as TTSTextFrames. |
Usage
import { TTSUpdateSettingsFrame } from "@pipedog/core/frames/frames";
import { XAIHttpTTSService, XAITTSService } from "@pipedog/xai/tts";
const tts = new XAITTSService({
apiKey: process.env.XAI_API_KEY ?? "",
settings: new XAITTSService.Settings({ voice: "eve" }),
});Change settings mid-call with an TTSUpdateSettingsFrame:
// Queue it on the worker, or push it from a processor upstream of the service.
const update = new TTSUpdateSettingsFrame({
delta: new XAITTSService.Settings({ speed: 1.1 }),
});Event handlers
| Event | Description |
|---|---|
on_connected | The WebSocket connected. |
on_disconnected | The WebSocket closed. |
on_connection_error | The connection failed. |
Notes
codecis"pcm"by default;wav,mulawandalawalso work.- The end of a turn sends
text.done; an interruption sendstext.clearand keeps the socket open. - Settings are query parameters of the connection, so any settings change reconnects.
XAIHttpTTSService
Posts each sentence to https://api.x.ai/v1/tts.
Configuration
Prop
Type
Settings
Runtime-updatable settings, passed as settings: new XAIHttpTTSService.Settings({...})
(XAITTSSettings). Any setting you leave out keeps the default below.
| Setting | Type | Default | Description |
|---|---|---|---|
model | string | null | null | Speech model. null leaves xAI's default. |
voice | string | "eve" | Voice. |
language | Language | null | Language.EN | Language; null sends "auto". |
speed | number | null | null | Speed, 0.7 to 1.5. |
optimizeStreamingLatency | number | null | null | Latency optimization level: 0, 1 or 2. |
textNormalization | boolean | null | null | Normalize the text before synthesis. |
Usage
const xAIHttpTTSService = new XAIHttpTTSService({
apiKey: process.env.XAI_API_KEY ?? "",
settings: new XAIHttpTTSService.Settings({ voice: "eve" }),
});Notes
fetchreplaces the globalfetch(upstream takes an aiohttp session).encodingis"pcm"by default.
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/xai/package.json: ✅ means the compat smoke test passes on that runtime.
- HTTP goes through
fetchand the WebSocket through the corewebsocketConnect. Both work on Bun, Node, Deno and Cloudflare Workers. - Tested against local servers, as upstream's tests do, not against xAI itself.
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).