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

Inworld

Text-to-speech with InworldTTSService (WebSocket) and InworldHttpTTSService (HTTP).

Overview

pipedog ports both of Pipecat's Inworld text-to-speech services:

  • InworldTTSService: Inworld TTS over a bidirectional WebSocket, with several audio contexts on one connection and word-level timestamps. Lowest latency.
  • InworldHttpTTSService: Inworld TTS over HTTP, streaming (/tts/v1/voice:stream) or in one piece (/tts/v1/voice), also with word-level timestamps.

Installation

bun add @pipedog/inworld
import { InworldHttpTTSService, InworldTTSService } from "@pipedog/inworld/tts";

Prerequisites

  • An Inworld account and an API key from the Inworld portal.
  • Pass the key as apiKey (the Base64 key Inworld gives you). The examples read it from INWORLD_API_KEY.

InworldTTSService

Configuration

Prop

Type

Settings

Runtime-updatable settings, passed as settings: new InworldTTSService.Settings({...}) (InworldTTSSettings). Any setting you leave out keeps the default below. InworldHttpTTSService uses the same settings class.

SettingTypeDefaultDescription
voicestring"Ashley"Inworld voice id.
modelstring"inworld-tts-2"TTS model.
languageLanguage | nullnullLanguage of the text.
speakingRatenumber | nullnullSpeaking rate.
temperaturenumber | nullnullSampling temperature.
deliveryMode"STABLE" | "BALANCED" | "CREATIVE" | nullnullStability vs. expressiveness. Only inworld-tts-2.

Usage

tts.ts
import { TTSUpdateSettingsFrame } from "@pipedog/core/frames/frames";
import { Language } from "@pipedog/core/transcriptions/language";
import { InworldHttpTTSService, InworldTTSService } from "@pipedog/inworld/tts";

const tts = new InworldTTSService({
  apiKey: process.env.INWORLD_API_KEY ?? "",
  settings: new InworldTTSService.Settings({
    voice: "Ashley",
    model: "inworld-tts-2",
    language: Language.EN,
    deliveryMode: "BALANCED",
  }),
});

Change the voice mid-call with a TTSUpdateSettingsFrame:

// Applies from the next context the service opens.
const update = new TTSUpdateSettingsFrame({
  delta: new InworldTTSService.Settings({ voice: "Dennis", temperature: 0.9 }),
});

InworldHttpTTSService

Configuration

Prop

Type

Usage

tts-http.ts
const httpTts = new InworldHttpTTSService({
  apiKey: process.env.INWORLD_API_KEY ?? "",
  // false posts to /tts/v1/voice and gets the audio in one piece.
  streaming: true,
  settings: new InworldHttpTTSService.Settings({ voice: "Ashley", speakingRate: 1.1 }),
});

Notes

  • Both output PCM at the pipeline's sample rate and push TTSTextFrames aligned to Inworld's word timestamps. When no timestamps arrive, the text is pushed as a whole.
  • InworldTTSService lets the server decide when to flush buffered text (autoMode, on by default) and closes a context on interruption.

Runtime notes

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

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

  • InworldTTSService opens its socket with websocketConnect() from core, with the key in the Authorization header (through fetch on Cloudflare Workers). InworldHttpTTSService uses the global fetch; pass fetch to use another one (upstream takes an aiohttp session).
  • Deprecated options are not ported: voiceId, model and params (InputParams) on the constructor, and aggregateSentences. The WebSocket buffer settings that only params could set always use their defaults.

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