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

OpenAI

Text-to-speech with OpenAITTSService, streaming 24 kHz PCM from OpenAI's speech API.

Overview

  • OpenAITTSService: sends each sentence to OpenAI's speech API (audio.speech) and streams the reply back as raw 24 kHz PCM. Supports the gpt-4o-mini-tts instructions and speed controls.

Installation

bun add @pipedog/openai
import { OpenAITTSService } from "@pipedog/openai/tts";

Prerequisites

  • An OpenAI account and an API key from the OpenAI dashboard.
  • Pass the key as apiKey. If you leave it out, the OpenAI SDK reads OPENAI_API_KEY. The examples read it from OPENAI_API_KEY.

OpenAITTSService

Configuration

Prop

Type

Settings

Runtime-updatable settings, passed as settings: new OpenAITTSService.Settings({...}) (OpenAITTSSettings). Any setting you leave out keeps the default below.

SettingTypeDefaultDescription
modelstring"gpt-4o-mini-tts"Speech model.
voicestring"alloy"One of alloy, ash, ballad, cedar, coral, echo, fable, marin, nova, onyx, sage, shimmer, verse.
languagenullnullNot used by this service.
instructionsstring | nullnullHow the voice should speak (tone, pace, accent).
speednumber | nullnullSpeed, 0.25 to 4.0. null leaves OpenAI's default (1.0).

Usage

tts.ts
import { TTSUpdateSettingsFrame } from "@pipedog/core/frames/frames";
import { OpenAITTSService } from "@pipedog/openai/tts";

const tts = new OpenAITTSService({
  apiKey: process.env.OPENAI_API_KEY ?? "",
  sampleRate: 24000,
  settings: new OpenAITTSService.Settings({
    model: "gpt-4o-mini-tts",
    voice: "marin",
    instructions: "Speak in a calm, friendly tone.",
  }),
});

Change the voice or speed mid-call with a TTSUpdateSettingsFrame:

const update = new TTSUpdateSettingsFrame({
  delta: new OpenAITTSService.Settings({ voice: "cedar", speed: 1.2 }),
});

Event handlers

EventDescription
on_tts_requestA synthesis request is about to be made.

This comes from the TTSService base class.

Notes

  • Requests response_format: "pcm" and emits TTSAudioRawFrames (mono, chunkSize bytes each) between TTSStartedFrame and TTSStoppedFrame.
  • OpenAI only returns 24 kHz audio. Set sampleRate: 24000 (or a 24 kHz pipeline output rate); any other rate logs a warning, and the frames are still labelled with that rate.
  • An unknown voice, or a request OpenAI rejects, produces an ErrorFrame instead of audio.
  • httpClient replaces the SDK's fetch, for example to set a longer request timeout.

Runtime notes

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

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

  • The client is the openai JS SDK over fetch. The audio is read from the response body stream, so it works on Bun, Node, Deno and Cloudflare Workers.
  • httpClient takes a fetch function where upstream takes an httpx client.
  • The deprecated OpenAITTSService.InputParams and the voice, model, instructions, speed and params constructor options are not ported. Use settings.

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