Skip to main content

Overview

GandrTTSService converts text to speech using Gandr. It holds a single WebSocket open and reuses it across turns rather than opening one per utterance, which is what keeps steady-state first-audio latency low.

Source Repository

Source code, examples, and issues for the Gandr integration

Gandr Website

Voices, languages, and pricing

API Keys

Create a Gandr API key

API Reference

The full HTTP and WebSocket contract

Installation

This is a community-maintained package distributed separately from pipecat-ai:

Prerequisites

  1. Gandr account: sign up at gandr.ai
  2. API key: a gnd_… key from your account page

Required environment variables

  • GANDR_API_KEY: your Gandr API key (required)

Configuration

str
required
Gandr API key (gnd_…). Raises ValueError if empty or whitespace.
str
default:"wss://tts.gandr.ai/ws"
WebSocket endpoint. Leave as the default unless you have been given a different one.
GandrTTSService.InputParams
default:"None"
Voice, language and expression configuration. See Input parameters.
TextAggregationMode
default:"None"
How incoming text is aggregated before synthesis.
float
default:"30.0"
How long to wait for an utterance’s closing frame before treating it as failed.
float
default:"0.5"
How long to wait before retrying after the server answers busy.
int
default:"3"
Total attempts per utterance, including retries for busy and for voice registration.
bool
default:"True"
On barge-in, drop and reopen the connection so the next turn’s audio is not queued behind audio the listener has already interrupted. See Interruptions.

Input parameters

Passed via params=GandrTTSService.InputParams(...). Stock voices: gandr-mia, gandr-ava, gandr-jenny, gandr-dane, gandr-leo, gandr-lewis.

Languages

language takes a bare two-letter code: 23 languages are supported. Examples: en, es, fr, de, pt, ar, zh, ja.
A region suffix such as en-GB or zh-CN is not recognised and the request falls back to English without raising an error. If you are populating this from a browser or OS locale, strip the region first.

Usage example

A complete runnable pipeline is in examples/foundational/gandr_tts_basic.py.

Interruptions

The wire protocol has no cancel frame. On barge-in the service therefore drops the connection and reopens it, rather than draining audio nobody is going to hear. Set reconnect_on_interruption=False to keep the connection instead and discard the interrupted render client-side, at the cost of the next turn waiting for that render to finish.

Notes

The first turn on a fresh connection is slower, roughly 700 ms while the session voice cache fills. Every turn after it is materially quicker, which is why the connection is held warm across turns. A benchmark that measures only turn one is measuring the cache filling rather than the engine.
Requests are capped at 2,000 characters. Longer text is split losslessly by split_for_request before sending; you do not need to pre-chunk.
Every failure path closes the turn with TTSStoppedFrame, so a pipeline cannot hang waiting on a connection that has died.

Compatibility

Tested with Pipecat v1.7.0 on Python 3.12.11: clean virtual environment, install, import, unit tests, and service construction. Declared support is pipecat-ai>=0.0.108,<2.0.0.