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

AWS Polly

Text-to-speech from Amazon Polly with AWSPollyTTSService, with SSML prosody, engines and lexicons.

Overview

AWSPollyTTSService synthesizes each sentence with Amazon Polly's SynthesizeSpeech API. It wraps the text in SSML (with prosody when rate, pitch or volume are set), requests 16 kHz PCM and resamples it to the pipeline's output rate.

Installation

bun add @pipedog/aws
import { AWSPollyTTSService } from "@pipedog/aws/tts";

Prerequisites

  • An IAM identity allowed polly:SynthesizeSpeech.

  • Keys, in this order of precedence:

    1. awsAccessKeyId, apiKey (the secret access key) and awsSessionToken.
    2. The AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN environment variables.
    3. A credentialsProvider function, called for every request.

    The region comes from region, else AWS_REGION, else us-east-1.

AWSPollyTTSService

Configuration

Prop

Type

Settings

Runtime-updatable settings, passed as settings: new AWSPollyTTSService.Settings({...}).

SettingTypeDefaultDescription
voicestring"Joanna"Polly voice ID.
languagestring"en-US"Polly language code. A Language is mapped with languageToAwsLanguage.
enginestring | nullnull"standard", "neural", "long-form" or "generative". null uses Polly's default.
ratestring | nullnullSSML prosody rate, e.g. "110%" or "slow".
pitchstring | nullnullSSML prosody pitch (standard engine only).
volumestring | nullnullSSML prosody volume, e.g. "loud" or "+3dB".
lexiconNamesstring[] | nullnullPronunciation lexicons to apply.

Usage

tts.ts
import { AWSPollyTTSService } from "@pipedog/aws/tts";
import { TTSUpdateSettingsFrame } from "@pipedog/core/frames/frames";

const tts = new AWSPollyTTSService({
  // Or leave these out to read the AWS_* environment variables.
  awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
  apiKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: "us-east-1",
  sampleRate: 24000,
  settings: new AWSPollyTTSService.Settings({
    voice: "Joanna",
    engine: "generative",
    language: "en-US",
    rate: "105%",
  }),
});

Change the voice mid-call with a TTSUpdateSettingsFrame:

// Queue it on the worker, or push it from a processor upstream of the service.
const update = new TTSUpdateSettingsFrame({
  delta: new AWSPollyTTSService.Settings({ voice: "Matthew" }),
});

Notes

  • One HTTP request per sentence. The audio is pushed as TTSAudioRawFrames of chunkSize bytes once the response has arrived.
  • Text is XML-escaped and sent as SSML (TextType: "ssml").
  • Any failed request (an HTTP error, a network error, missing credentials) becomes an ErrorFrame. Upstream does this for botocore errors only.

Runtime notes

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

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

  • Runs on Bun, Node, Deno and Cloudflare Workers: POST /v1/speech with fetch, signed with SigV4 on WebCrypto.
  • There is no default AWS credential chain (profiles, IMDS, ECS roles, SSO). Use keys, the environment, or credentialsProvider.
  • endpointUrl and fetch replace the Polly host and the global fetch.
  • Not ported: the deprecated InputParams, and the voiceId and params constructor options. 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