Skip to main content
AWS Polly TTS Tool Logo

aws-polly-tts-tool

Python Version License: MIT Code style: ruff Type checked: mypy Built with Claude Code

Professional AWS Polly TTS CLI and library for text-to-speech synthesis with agent-friendly design.

Table of Contents

About

aws-polly-tts-tool is a comprehensive CLI tool and Python library for Amazon Polly text-to-speech synthesis. Built with a CLI-first philosophy, it provides both command-line convenience and programmatic access to AWS Polly's full feature set.

What is Amazon Polly?

Amazon Polly is AWS's fully-managed text-to-speech service that converts text into lifelike speech using deep learning. It offers 60+ voices in 30+ languages with multiple quality tiers.

Why This Tool?

  • Agent-Friendly: Designed for Claude Code and AI agents with self-documenting help and structured errors
  • Composable: JSON output to stdout, logs to stderr - perfect for Unix piping
  • Dual-Mode: Use as CLI or import as Python library
  • Production-Ready: Type-safe, tested, linted with comprehensive error handling
  • Cost-Transparent: Real-time cost estimates and AWS billing integration

Why CLI-First?

This tool prioritizes CLI design to enable:

  • 🤖 AI Agent Integration: Claude Code and other AI tools can use structured commands and parse outputs
  • 🔄 ReAct Loops: Clear error messages help agents self-correct and retry operations
  • 🔗 Composability: Standard Unix patterns (stdin/stdout/stderr) enable piping and automation
  • 🧱 Building Blocks: Commands serve as reusable components for skills, MCP servers, and scripts
  • 📊 Predictability: Type-safe implementation ensures consistent behavior in automated workflows

Features

Voice Engines

  • ✅ Standard - Cost-effective traditional TTS ($4/1M chars)
  • ✅ Neural - Natural, human-like voices ($16/1M chars)
  • ✅ Generative - Most advanced, emotionally engaged ($30/1M chars)
  • ✅ Long-form - Optimized for audiobooks ($100/1M chars)

Voice Selection

  • 📢 60+ voices across 30+ languages
  • 🔍 Dynamic fetching from Polly API (always up-to-date)
  • 🎚️ Filter by engine, language, gender
  • 🌍 Multiple accents and speaking styles

Output Options

  • 🎵 mp3 - General purpose (default)
  • 🎶 ogg_vorbis - Open format for web
  • 🎙️ pcm - Raw audio, lowest latency

Advanced Features

  • 📝 Full SSML support (prosody, breaks, emphasis, phonemes)
  • 💰 Dual cost tracking (estimates + AWS Cost Explorer)
  • 📊 Billing queries with engine breakdown
  • 🔐 AWS environment variable authentication
  • 📤 Stdin support for piping

Installation

Prerequisites

  • Python 3.12+ (Python 3.13+ has pydub compatibility issues - see Known Issues)
  • uv package manager (recommended)
  • AWS credentials configured
  • ffmpeg (for audio playback - not required for file output)

Note: For a detailed explanation of how the TTS pipeline works and why these dependencies are needed, see TTS Pipeline Architecture

Install from Source

# Clone repository
git clone https://github.com/dnvriend/aws-polly-tts-tool.git
cd aws-polly-tts-tool

# Install with uv (Python 3.12)
uv tool install . --python 3.12

# Verify installation
aws-polly-tts-tool --version

Install with mise (Development)

cd aws-polly-tts-tool
mise use python@3.12
uv sync
uv tool install .

Configuration

AWS Credentials

Configure AWS credentials using any of these methods:

# Method 1: AWS CLI configuration
aws configure

# Method 2: Environment variables
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"

# Verify credentials
aws-polly-tts-tool info

IAM Permissions Required

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "polly:DescribeVoices",
        "polly:SynthesizeSpeech"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": ["ce:GetCostAndUsage"],
      "Resource": "*"
    }
  ]
}

Usage

Basic Synthesis

# Play text with default voice (Joanna, neural engine)
aws-polly-tts-tool synthesize "Hello world"

# Save to file instead of playing
aws-polly-tts-tool synthesize "Hello world" --output speech.mp3

# Read from stdin
echo "Hello world" | aws-polly-tts-tool synthesize --stdin

# Read from file
cat article.txt | aws-polly-tts-tool synthesize --stdin --output article.mp3

Voice Selection

# List all available voices
aws-polly-tts-tool list-voices

# Filter by language
aws-polly-tts-tool list-voices --language en-US

# Filter by engine and gender
aws-polly-tts-tool list-voices --engine neural --gender Female

# Use specific voice
aws-polly-tts-tool synthesize "Hello" --voice Matthew
aws-polly-tts-tool synthesize "Bonjour" --voice Celine  # French

Engine Selection

# List all engines with pricing
aws-polly-tts-tool list-engines

# Use standard engine (cheapest)
aws-polly-tts-tool synthesize "Hello" --engine standard

# Use neural engine (recommended)
aws-polly-tts-tool synthesize "Hello" --engine neural

# Use generative engine (highest quality)
aws-polly-tts-tool synthesize "Hello" --engine generative

# Use long-form for audiobooks
aws-polly-tts-tool synthesize "$(cat book.txt)" --engine long-form --output book.mp3

SSML Support

# Basic SSML with pauses
aws-polly-tts-tool synthesize '<speak>Hello <break time="500ms"/> world</speak>' --ssml

# Prosody control (speed, pitch, volume)
aws-polly-tts-tool synthesize '<speak><prosody rate="slow" pitch="low">Deep voice</prosody></speak>' --ssml

# Emphasis
aws-polly-tts-tool synthesize '<speak>I <emphasis level="strong">really</emphasis> like this</speak>' --ssml

# Newscaster style (select voices only)
aws-polly-tts-tool synthesize '<speak><amazon:domain name="news">Breaking news today</amazon:domain></speak>' --ssml --voice Matthew

Cost Tracking

# Show cost estimate after synthesis
aws-polly-tts-tool synthesize "Hello world" --show-cost

# View pricing for all engines
aws-polly-tts-tool pricing

# Query AWS billing (last 30 days)
aws-polly-tts-tool billing

# Custom date range
aws-polly-tts-tool billing --start-date 2025-01-01 --end-date 2025-01-31

# Last 7 days
aws-polly-tts-tool billing --days 7

Verbosity and Debugging

Multi-level verbosity for progressive debugging detail:

# Default: No verbose output (errors/warnings only)
aws-polly-tts-tool synthesize "Hello world" --output test.mp3

# -V: INFO level (high-level operations)
aws-polly-tts-tool synthesize "Hello world" -V --output test.mp3
[INFO] Using voice: Joanna (neural engine)
[INFO] Synthesizing audio to file: test.mp3

# -VV: DEBUG level (detailed operations, validation, character counts)
aws-polly-tts-tool synthesize "Hello world" -VV --output test.mp3
[DEBUG] Validating engine: neural
[DEBUG] Validating output format: mp3
[DEBUG] Initializing AWS Polly client
[DEBUG] Resolving voice ID for: Joanna
[INFO] Using voice: Joanna (neural engine)
[INFO] Synthesizing audio to file: test.mp3
[DEBUG] Synthesized 11 characters

# -VVV: TRACE level (full AWS SDK details, API requests/responses)
aws-polly-tts-tool synthesize "Hello world" -VVV --output test.mp3
[DEBUG] Validating engine: neural
[DEBUG] Validating output format: mp3
[DEBUG] Initializing AWS Polly client
[DEBUG] Looking for credentials via: env
[DEBUG] Looking for credentials via: shared-credentials-file
[INFO] Found credentials in shared credentials file: ~/.aws/credentials
[DEBUG] Event creating-client-class.polly: calling handler
[DEBUG] Starting new HTTPS connection (1): polly.eu-central-1.amazonaws.com:443
[DEBUG] https://polly.eu-central-1.amazonaws.com:443 "POST /v1/speech HTTP/1.1" 200 None
[INFO] Using voice: Joanna (neural engine)
[INFO] Synthesizing audio to file: test.mp3
[DEBUG] Synthesized 11 characters

# Works with all commands
aws-polly-tts-tool list-voices -V --engine neural
aws-polly-tts-tool billing -VV --days 7

Verbosity Levels:

  • Default: Errors and warnings only - clean output
  • -V (INFO): High-level operations (voice selection, file operations)
  • -VV (DEBUG): Detailed steps (validation, API calls, character counts)
  • -VVV (TRACE): Full AWS SDK internals (credentials, HTTP requests, boto3 events)

Note: All log output goes to stderr, keeping stdout clean for data/piping.

Shell Completion

Enable tab completion for bash, zsh, or fish shells to autocomplete commands, options, and arguments:

# View installation instructions
aws-polly-tts-tool completion --help

# Bash - add to ~/.bashrc for persistent completion
eval "$(aws-polly-tts-tool completion bash)"

# Zsh - add to ~/.zshrc for persistent completion
eval "$(aws-polly-tts-tool completion zsh)"

# Fish - one-time installation
aws-polly-tts-tool completion fish > ~/.config/fish/completions/aws-polly-tts-tool.fish

# File-based installation (recommended for better performance)
aws-polly-tts-tool completion bash > ~/.aws-polly-tts-tool-complete.bash
echo 'source ~/.aws-polly-tts-tool-complete.bash' >> ~/.bashrc

After installation, restart your shell or source the config file:

source ~/.bashrc  # for bash
source ~/.zshrc   # for zsh

Shell completion enables:

  • Command completion: Type aws-polly-tts-tool <TAB> to see all commands
  • Option completion: Type --<TAB> to see available options
  • Value completion: Auto-complete for choices like engines (standard, neural, generative)

Library Usage

Import and use as a Python library:

from aws_polly_tts_tool import (
    get_polly_client,
    synthesize_audio,
    save_speech,
    VoiceManager,
    calculate_cost,
)

# Initialize client
client = get_polly_client(region="us-east-1")

# Synthesize audio
audio_bytes, char_count = synthesize_audio(
    client=client,
    text="Hello world",
    voice_id="Joanna",
    output_format="mp3",
    engine="neural"
)

# Save to file
save_speech(
    client=client,
    text="Hello world",
    voice_id="Joanna",
    output_path=Path("output.mp3"),
    engine="neural"
)

# List voices
voice_manager = VoiceManager(client)
voices = voice_manager.list_voices(engine="neural", language="en")

# Calculate cost
cost = calculate_cost(character_count=5000, engine="neural")
print(f"Estimated cost: ${cost:.4f}")

Commands

synthesize

Convert text to speech with full control over voice, engine, and output.

aws-polly-tts-tool synthesize [TEXT] [OPTIONS]
  -s, --stdin         Read from stdin
  --voice TEXT        Voice ID (default: Joanna)
  -o, --output PATH   Save to file
  -f, --format TEXT   mp3, ogg_vorbis, pcm
  -e, --engine TEXT   standard, neural, generative, long-form
  --ssml              Treat input as SSML
  --show-cost         Display cost estimate
  -r, --region TEXT   AWS region override
  -V, --verbose       Verbosity (-V, -VV, -VVV for progressive detail)

list-voices

List and filter available Polly voices.

aws-polly-tts-tool list-voices [OPTIONS]
  -e, --engine TEXT    Filter by engine
  -l, --language TEXT  Filter by language
  -g, --gender TEXT    Filter by gender
  -r, --region TEXT    AWS region override
  -V, --verbose        Verbosity (-V, -VV, -VVV for progressive detail)

list-engines

Display all voice engines with features and pricing.

aws-polly-tts-tool list-engines

billing

Query AWS Cost Explorer for actual Polly usage costs.

aws-polly-tts-tool billing [OPTIONS]
  -d, --days INT       Number of days (default: 30)
  --start-date TEXT    Custom start date (YYYY-MM-DD)
  --end-date TEXT      Custom end date (YYYY-MM-DD)
  -r, --region TEXT    AWS region override
  -V, --verbose        Verbosity (-V, -VV, -VVV for progressive detail)

pricing

Show Polly pricing information and examples.

aws-polly-tts-tool pricing

info

Display AWS credentials and tool configuration.

aws-polly-tts-tool info

completion

Generate shell completion scripts for bash, zsh, or fish.

aws-polly-tts-tool completion [bash|zsh|fish]

# Install for bash
eval "$(aws-polly-tts-tool completion bash)"

# Install for zsh
eval "$(aws-polly-tts-tool completion zsh)"

# Install for fish
aws-polly-tts-tool completion fish > ~/.config/fish/completions/aws-polly-tts-tool.fish

See Shell Completion section for detailed installation instructions.

Known Issues

pydub Python 3.13+ Compatibility

Issue: The pydub library depends on Python's audioop module, which was removed in Python 3.13.

Impact: Audio playback through speakers fails on Python 3.13+. File output (--output) works fine.

Workarounds:

  1. Use Python 3.12 (recommended)

    mise use python@3.12
    uv tool install . --python 3.12
    
  2. Save to file instead of playback

    # This works on any Python version
    aws-polly-tts-tool synthesize "Hello" --output speech.mp3
    
  3. Future fix: We plan to replace pydub with a Python 3.13+ compatible library (pygame or sounddevice)

Development

Setup

# Clone and setup
git clone https://github.com/dnvriend/aws-polly-tts-tool.git
cd aws-polly-tts-tool

# Install with Python 3.12
mise use python@3.12
uv sync

# Run quality checks
make check

Available Commands

make install              # Install dependencies
make format               # Format with ruff
make lint                 # Lint with ruff
make typecheck            # Type check with mypy
make test                 # Run tests with pytest
make security-bandit      # Run bandit security linter
make security-pip-audit   # Run pip-audit for vulnerabilities
make security-gitleaks    # Run gitleaks secret scanner
make security             # Run all security checks
make check                # Run all checks (lint, typecheck, test, security)
make pipeline             # Full pipeline (format, lint, typecheck, test, security, build, install)
make build                # Build package
make clean                # Remove artifacts

Security Checks

The project includes three security tools integrated into the development pipeline:

  • bandit - Python security linter that scans for common security issues
  • pip-audit - Dependency vulnerability scanner checking for known CVEs
  • gitleaks - Secret detection tool that scans git history for leaked credentials

Note: gitleaks requires separate installation via brew install gitleaks (macOS) or from GitHub releases

Architecture

aws-polly-tts-tool/
├── aws_polly_tts_tool/
│   ├── __init__.py           # Public API exports
│   ├── cli.py                # CLI entry point
│   ├── voices.py             # VoiceManager (dynamic API)
│   ├── engines.py            # Engine metadata & validation
│   ├── billing.py            # Cost calculations
│   ├── utils.py              # Shared utilities
│   ├── core/                 # Core library (CLI-independent)
│   │   ├── client.py         # AWS client initialization
│   │   ├── synthesize.py     # TTS functions
│   │   └── cost_explorer.py  # Billing queries
│   └── commands/             # CLI command implementations
│       ├── synthesize_commands.py
│       ├── voice_commands.py
│       ├── engine_commands.py
│       ├── billing_commands.py
│       └── info_commands.py
├── tests/
├── pyproject.toml
└── Makefile

Resources

License

MIT License - see LICENSE file for details.

Author

Dennis Vriend


Built with Claude Code

This project was created using Claude Code, featuring AI-assisted development with human review and testing.

Made with ❤️ and AI • Python 3.12+

Metadata

Release files for aws-polly-tts-tool 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aws-polly-tts-tool 0.2.0
File Size Uploaded
aws_polly_tts_tool-0.2.0.tar.gz 283.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aws-polly-tts-tool 0.2.0
File Interpreter ABI Platform
aws_polly_tts_tool-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 323.7 kB

Release files / aws_polly_tts_tool-0.2.0.tar.gz

Download URL aws_polly_tts_tool-0.2.0.tar.gz
Size 283.8 kB
Tags Source
SHA-256 checksum
How to use checksums
8103ac1a6066b4efd39291493aa7158bbbfabadfb6607ab6680510835d2a3c22
BLAKE2b-256 checksum
How to use checksums
a9bf13816b1b3430f9e63c1cc362928608daae778984191141716a046787fd57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 5, 2025.

Transparency log

Release files / aws_polly_tts_tool-0.2.0-py3-none-any.whl

Download URL aws_polly_tts_tool-0.2.0-py3-none-any.whl
Size 39.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2a3ccaf0f12c6c5e60f78fbdc31cd8eb3470b5b6a920cd362fdf2e87573bfa79
BLAKE2b-256 checksum
How to use checksums
e7eeeef07aa4ac0b34389700ae991b1e0daff5f93f7b897a0a3dcea2f171011b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 5, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page