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

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.

Installation

bun add @pipedog/xai
import { 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 from XAI_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.

SettingTypeDefaultDescription
modelstring | nullnullSpeech model. null leaves xAI's default.
voicestring"eve"Voice.
languageLanguage | nullLanguage.ENLanguage; null sends "auto".
speednumber | nullnullSpeed, 0.7 to 1.5.
optimizeStreamingLatencynumber | nullnullLatency optimization level: 0, 1 or 2.
textNormalizationboolean | nullnullNormalize the text before synthesis.
withTimestampsbooleantrueWord timestamps, pushed as TTSTextFrames.

Usage

tts.ts
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

EventDescription
on_connectedThe WebSocket connected.
on_disconnectedThe WebSocket closed.
on_connection_errorThe connection failed.

Notes

  • codec is "pcm" by default; wav, mulaw and alaw also work.
  • The end of a turn sends text.done; an interruption sends text.clear and 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.

SettingTypeDefaultDescription
modelstring | nullnullSpeech model. null leaves xAI's default.
voicestring"eve"Voice.
languageLanguage | nullLanguage.ENLanguage; null sends "auto".
speednumber | nullnullSpeed, 0.7 to 1.5.
optimizeStreamingLatencynumber | nullnullLatency optimization level: 0, 1 or 2.
textNormalizationboolean | nullnullNormalize the text before synthesis.

Usage

const xAIHttpTTSService = new XAIHttpTTSService({
  apiKey: process.env.XAI_API_KEY ?? "",
  settings: new XAIHttpTTSService.Settings({ voice: "eve" }),
});

Notes

  • fetch replaces the global fetch (upstream takes an aiohttp session).
  • encoding is "pcm" by default.

Runtime notes

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

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

  • HTTP goes through fetch and the WebSocket through the core websocketConnect. 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).

On this page