← Back to DevBytes

How to Build a Text-to-Speech App with Python and gTTS

Introduction: What is gTTS?

gTTS (Google Text-to-Speech) is a Python library and CLI tool that interfaces with Google Translate's text-to-speech API. It allows you to convert text into spoken audio files effortlessly, without requiring any API keys or authentication. The library supports multiple languages, offers customizable speech speed, and outputs MP3 files that you can play back or embed in applications.

At its core, gTTS sends a text string to Google's translation service, receives the synthesized audio in return, and saves it as an MP3 file on your local machine. The library handles all the HTTP requests, token generation, and audio processing behind the scenes, giving you a clean, minimal interface to work with.

Why Text-to-Speech Matters

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

Text-to-speech technology bridges the gap between written content and auditory experiences. Here are some key reasons developers integrate TTS into their projects:

Prerequisites and Setup

Before writing any code, you need a Python environment (version 3.6 or higher) and the gTTS package installed. Let's set everything up step by step.

Installing gTTS

Open your terminal and run the following command to install gTTS along with its core dependencies:

pip install gTTS

For audio playback functionality, you'll also want to install a playback library. Two excellent options are:

# Option 1: playsound (simple cross-platform playback)
pip install playsound

# Option 2: pyglet (more advanced audio control)
pip install pyglet

On Linux systems, you may additionally need to install system-level audio dependencies like libportaudio2 or pulseaudio. On macOS and Windows, the standard installations work out of the box.

Verifying the Installation

Run this quick test to confirm everything is working:

from gtts import gTTS
print("gTTS imported successfully!")

If no errors appear, you're ready to build.

Building Your First Text-to-Speech Script

Let's start with the simplest possible TTS script: converting a single sentence into an MP3 file.

from gtts import gTTS

# Define the text you want to convert
text = "Hello, world! Welcome to text-to-speech with Python."

# Create a gTTS object
tts = gTTS(text=text, lang='en')

# Save the audio to a file
tts.save("hello_world.mp3")

print("Audio saved as hello_world.mp3")

This script does three things: it initializes a gTTS instance with your text and language, triggers the API call to Google's servers, and writes the returned MP3 data to disk. The resulting file can be played with any standard media player.

Playing Audio Programmatically

To play the generated audio directly from your script, use the playsound library:

from gtts import gTTS
from playsound import playsound

text = "This audio will play automatically after generation."
tts = gTTS(text=text, lang='en')
tts.save("output.mp3")

# Play the saved file
playsound("output.mp3")

Note: playsound blocks execution until playback finishes. For non-blocking playback in more complex applications, consider using pyglet or threading.

Customizing Speech Output

Specifying Languages

gTTS supports dozens of languages. You specify the language using the lang parameter with an IETF language tag (like 'en', 'es', 'fr', 'ja'). Here's how to generate speech in different languages:

from gtts import gTTS

# English
tts_en = gTTS(text="Good morning, how are you today?", lang='en')
tts_en.save("english_greeting.mp3")

# Spanish
tts_es = gTTS(text="Buenos días, ¿cómo estás hoy?", lang='es')
tts_es.save("spanish_greeting.mp3")

# French
tts_fr = gTTS(text="Bonjour, comment allez-vous aujourd'hui?", lang='fr')
tts_fr.save("french_greeting.mp3")

# Japanese
tts_ja = gTTS(text="Good morning、TEXTnoTEXTHow is it?", lang='ja')
tts_ja.save("japanese_greeting.mp3")

print("Multilingual greetings saved!")

Adjusting Speech Speed

The slow boolean parameter controls the pace of the generated speech. When set to True, the speech is noticeably slower—ideal for language learning or accessibility purposes:

from gtts import gTTS

text = "This is normal speed speech."

# Normal speed (default)
tts_normal = gTTS(text=text, lang='en', slow=False)
tts_normal.save("normal_speed.mp3")

# Slow speed
tts_slow = gTTS(text=text, lang='en', slow=True)
tts_slow.save("slow_speed.mp3")

print("Speed comparison files generated.")

Handling Long Text with Automatic Splitting

Google Translate's API imposes a character limit per request. gTTS automatically splits long text into smaller chunks and stitches the audio together seamlessly. You don't need to worry about chunking manually—just pass your full text:

from gtts import gTTS

long_text = """
Python is a powerful programming language that lets you work quickly
and integrate systems more effectively. It is used in web development,
data science, artificial intelligence, scientific computing, and more.
The gTTS library makes it incredibly easy to convert text to speech
without dealing with complex API authentication or paid services.
Just install the library, write a few lines of code, and you have
a fully functional text-to-speech engine at your disposal.
"""

tts = gTTS(text=long_text, lang='en')
tts.save("long_speech.mp3")

print("Long text processed and saved.")

Behind the scenes, gTTS splits the text at sentence boundaries and makes multiple requests, then concatenates the audio chunks into a single coherent MP3 file.

Building a Complete TTS Application

Now let's build a fully functional command-line text-to-speech application that accepts user input, supports language selection, and handles file naming intelligently.

The Complete CLI App

#!/usr/bin/env python3
"""
Text-to-Speech CLI Application
Converts user-provided text into speech and saves/plays the audio.
"""

from gtts import gTTS
from playsound import playsound
import os
import sys
from datetime import datetime

def display_language_menu():
    """Display available languages and return the user's choice."""
    languages = {
        '1': ('en', 'English'),
        '2': ('es', 'Spanish'),
        '3': ('fr', 'French'),
        '4': ('de', 'German'),
        '5': ('it', 'Italian'),
        '6': ('pt', 'Portuguese'),
        '7': ('ja', 'Japanese'),
        '8': ('ko', 'Korean'),
        '9': ('hi', 'Hindi'),
        '10': ('ar', 'Arabic'),
    }
    
    print("\nAvailable languages:")
    print("-" * 30)
    for key, (code, name) in languages.items():
        print(f"  {key}. {name} ({code})")
    print("-" * 30)
    
    while True:
        choice = input("Select language (1-10, default 1 for English): ").strip()
        if choice == "":
            return 'en'
        if choice in languages:
            return languages[choice][0]
        print("Invalid choice. Please try again.")

def get_speech_speed():
    """Prompt user for speech speed preference."""
    print("\nSpeech speed options:")
    print("  1. Normal speed")
    print("  2. Slow speed")
    
    while True:
        choice = input("Select speed (1 or 2, default 1): ").strip()
        if choice == "" or choice == "1":
            return False
        elif choice == "2":
            return True
        print("Invalid choice. Please enter 1 or 2.")

def generate_filename():
    """Generate a unique filename with timestamp."""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    return f"tts_output_{timestamp}.mp3"

def main():
    print("=" * 50)
    print("   TEXT-TO-SPEECH CONVERTER (powered by gTTS)")
    print("=" * 50)
    
    # Get text input (supports multiline)
    print("\nEnter the text you want to convert to speech.")
    print("(Press Enter twice to finish, or Ctrl+D to end):\n")
    
    lines = []
    empty_count = 0
    while True:
        try:
            line = input()
            if line.strip() == "":
                empty_count += 1
                if empty_count >= 2:
                    break
            else:
                empty_count = 0
            lines.append(line)
        except EOFError:
            break
    
    text = "\n".join(lines).strip()
    
    if not text:
        print("No text entered. Exiting.")
        sys.exit(0)
    
    # Select language
    lang = display_language_menu()
    
    # Select speed
    slow = get_speech_speed()
    
    # Generate speech
    print("\n[*] Generating speech...")
    try:
        tts = gTTS(text=text, lang=lang, slow=slow)
        filename = generate_filename()
        tts.save(filename)
        print(f"[✓] Audio saved to: {filename}")
    except Exception as e:
        print(f"[✗] Error during generation: {e}")
        sys.exit(1)
    
    # Ask if user wants to play the audio
    play_choice = input("\nPlay audio now? (y/n, default y): ").strip().lower()
    if play_choice == "" or play_choice == "y":
        print("[*] Playing audio...")
        try:
            playsound(filename)
        except Exception as e:
            print(f"[✗] Playback error: {e}")
            print("You can manually play the saved MP3 file.")
    
    print("\nDone! Thank you for using the TTS converter.")

if __name__ == "__main__":
    main()

This complete application demonstrates several important patterns: user input validation, error handling, dynamic filename generation with timestamps, and a clean separation of concerns with dedicated functions. Users can paste paragraphs of text, select their target language, choose speech speed, and immediately hear the result.

Working with Audio In-Memory (No File I/O)

Sometimes you don't want to write files to disk—for example, when streaming audio over a network or embedding TTS in a web application. gTTS provides a write_to_fp() method that writes audio data to a file-like object. Combined with io.BytesIO, you can keep everything in memory:

from gtts import gTTS
import io

# Generate speech in memory
text = "This audio stays in memory and never touches the disk."
tts = gTTS(text=text, lang='en')

# Write to a BytesIO buffer
mp3_buffer = io.BytesIO()
tts.write_to_fp(mp3_buffer)

# The buffer now contains the complete MP3 data
mp3_buffer.seek(0)  # Reset buffer position to beginning

# You can now:
# - Upload this buffer to cloud storage
# - Return it as a Flask/FastAPI response
# - Stream it to a media player
# - Store it in a database as binary data

print(f"Audio generated in-memory. Buffer size: {mp3_buffer.getbuffer().nbytes} bytes")

This approach is cleaner for server-side applications and avoids littering the filesystem with temporary audio files.

Advanced Integrations

Combining gTTS with pydub for Audio Manipulation

The pydub library allows you to manipulate the generated audio—trimming silence, concatenating clips, adjusting volume, or converting formats:

from gtts import gTTS
from pydub import AudioSegment
import io

# Generate speech
text = "Segment one. This is the first part of our audio."
tts = gTTS(text=text, lang='en')

# Get audio in memory
buffer1 = io.BytesIO()
tts.write_to_fp(buffer1)
buffer1.seek(0)

# Generate second speech segment
text2 = "Segment two. This is the second part, now combined with the first."
tts2 = gTTS(text=text2, lang='en')
buffer2 = io.BytesIO()
tts2.write_to_fp(buffer2)
buffer2.seek(0)

# Load into pydub AudioSegments
segment1 = AudioSegment.from_mp3(buffer1)
segment2 = AudioSegment.from_mp3(buffer2)

# Add a 2-second silence between segments
silence = AudioSegment.silent(duration=2000)  # 2000 ms = 2 seconds

# Concatenate: segment1 + silence + segment2
combined = segment1 + silence + segment2

# Export the combined audio
combined.export("combined_speech.mp3", format="mp3")
print("Combined audio with silence gap exported.")

Building a Batch PDF-to-Speech Converter

A practical real-world application is converting text documents into audio. Here's how to extract text from a PDF and convert it to speech:

# First install: pip install PyPDF2 gTTS

from gtts import gTTS
from PyPDF2 import PdfReader
import os

def pdf_to_speech(pdf_path, output_path, lang='en'):
    """
    Extract text from a PDF file and convert it to speech.
    """
    # Extract text from PDF
    reader = PdfReader(pdf_path)
    full_text = []
    
    for page_num, page in enumerate(reader.pages, 1):
        text = page.extract_text()
        if text:
            full_text.append(text)
        print(f"Extracted page {page_num}/{len(reader.pages)}")
    
    combined_text = "\n".join(full_text)
    
    if not combined_text.strip():
        raise ValueError("No extractable text found in the PDF.")
    
    print(f"Total characters extracted: {len(combined_text)}")
    
    # Convert to speech
    print("Converting text to speech...")
    tts = gTTS(text=combined_text, lang=lang)
    tts.save(output_path)
    
    print(f"Audio saved to: {output_path}")
    return output_path

# Usage
pdf_to_speech("sample_report.pdf", "report_audio.mp3", lang='en')

Integrating with Flask for a Web TTS API

Here's a minimal Flask endpoint that accepts text via POST request and returns the generated MP3 audio directly to the client:

from flask import Flask, request, send_file, jsonify
from gtts import gTTS
import io

app = Flask(__name__)

@app.route('/tts', methods=['POST'])
def text_to_speech():
    """Convert text to speech and return the MP3 audio."""
    data = request.get_json()
    
    if not data or 'text' not in data:
        return jsonify({"error": "Missing 'text' field in request body"}), 400
    
    text = data['text']
    lang = data.get('lang', 'en')
    slow = data.get('slow', False)
    
    try:
        # Generate audio in memory
        tts = gTTS(text=text, lang=lang, slow=slow)
        audio_buffer = io.BytesIO()
        tts.write_to_fp(audio_buffer)
        audio_buffer.seek(0)
        
        return send_file(
            audio_buffer,
            mimetype='audio/mpeg',
            as_attachment=True,
            download_name='speech.mp3'
        )
    except Exception as e:
        return jsonify({"error": str(e)}), 500

@app.route('/health')
def health():
    return jsonify({"status": "ok"})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

Test the endpoint with curl:

curl -X POST http://localhost:5000/tts \
  -H "Content-Type: application/json" \
  -d '{"text":"Hello from the Flask TTS API!","lang":"en"}' \
  --output response.mp3

Best Practices

1. Handle Network Errors Gracefully

gTTS relies on an internet connection to reach Google's servers. Always wrap your gTTS calls in try/except blocks to handle connectivity issues:

from gtts import gTTS
import time

def generate_speech_with_retry(text, lang='en', max_retries=3):
    """Generate speech with retry logic for network resilience."""
    for attempt in range(1, max_retries + 1):
        try:
            tts = gTTS(text=text, lang=lang)
            tts.save("output.mp3")
            return True
        except Exception as e:
            print(f"Attempt {attempt} failed: {e}")
            if attempt < max_retries:
                wait_time = attempt * 2  # Exponential backoff
                print(f"Retrying in {wait_time} seconds...")
                time.sleep(wait_time)
    print("All retries exhausted. Speech generation failed.")
    return False

2. Respect API Limits

While gTTS doesn't require an API key, Google's Translate API still has rate limits. For batch processing, add delays between requests:

import time

texts = [
    "First paragraph of text.",
    "Second paragraph of text.",
    "Third paragraph of text.",
    # ... many more items
]

for i, text in enumerate(texts):
    tts = gTTS(text=text, lang='en')
    tts.save(f"output_{i}.mp3")
    print(f"Generated file {i+1}/{len(texts)}")
    
    # Respect rate limits: wait 2 seconds between requests
    if i < len(texts) - 1:
        time.sleep(2)

3. Validate and Clean Input Text

Not all characters are supported equally across languages. Clean your text before passing it to gTTS:

import re

def clean_text_for_tts(text, lang='en'):
    """Clean and normalize text for optimal TTS output."""
    # Remove excessive whitespace
    text = re.sub(r'\s+', ' ', text).strip()
    
    # Replace common problematic characters
    text = text.replace('&', ' and ')
    text = text.replace('%', ' percent ')
    text = text.replace('$', ' dollars ')
    
    # For non-Latin script languages, ensure proper encoding
    if lang in ['ja', 'ko', 'zh', 'ar', 'hi']:
        # Keep only script-appropriate characters and punctuation
        text = text.encode('utf-8', errors='ignore').decode('utf-8')
    
    return text

# Usage
raw_text = "The price is $50 & the discount is 20%   off!"
cleaned = clean_text_for_tts(raw_text, lang='en')
tts = gTTS(text=cleaned, lang='en')
tts.save("cleaned_speech.mp3")

4. Use Meaningful Filenames

Instead of generic names like output.mp3, create descriptive filenames that reflect the content:

from datetime import datetime
import re

def create_descriptive_filename(text, lang, prefix="tts"):
    """Generate a filename based on the first few words of text."""
    # Take first 5 words, sanitize for filename
    words = text.split()[:5]
    snippet = "_".join(words).lower()
    snippet = re.sub(r'[^a-z0-9_]', '', snippet)
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    return f"{prefix}_{lang}_{snippet}_{timestamp}.mp3"

# Example
text = "The quick brown fox jumps over the lazy dog"
filename = create_descriptive_filename(text, 'en')
print(filename)  # tts_en_the_quick_brown_fox_jumps_20250115_143022.mp3

5. Cache Frequently Used Phrases

If your application repeats the same phrases (like notifications or system messages), cache the generated MP3 files to avoid redundant API calls:

import hashlib
import os

CACHE_DIR = "tts_cache"

def cached_tts(text, lang='en'):
    """Generate TTS with caching based on text+lang hash."""
    os.makedirs(CACHE_DIR, exist_ok=True)
    
    # Create a unique hash for the text+lang combination
    cache_key = hashlib.md5(f"{text}:{lang}".encode()).hexdigest()
    cache_path = os.path.join(CACHE_DIR, f"{cache_key}.mp3")
    
    # Return cached file if it exists
    if os.path.exists(cache_path):
        print(f"Cache hit! Using cached audio: {cache_path}")
        return cache_path
    
    # Generate new audio
    tts = gTTS(text=text, lang=lang)
    tts.save(cache_path)
    print(f"Generated and cached: {cache_path}")
    return cache_path

# Usage
cached_tts("System alert: backup completed successfully.", lang='en')
# Second call will use cache
cached_tts("System alert: backup completed successfully.", lang='en')

6. Consider Offline Alternatives for Production

gTTS requires internet connectivity. For production environments where offline capability is critical, consider these alternatives alongside gTTS:

You can implement a fallback pattern:

from gtts import gTTS
import pyttsx3

def generate_speech(text, lang='en', prefer_online=True):
    """Generate speech with offline fallback."""
    if prefer_online:
        try:
            tts = gTTS(text=text, lang=lang)
            tts.save("speech.mp3")
            return "speech.mp3"
        except Exception as e:
            print(f"Online TTS failed: {e}. Falling back to offline engine.")
    
    # Offline fallback
    engine = pyttsx3.init()
    engine.setProperty('rate', 150)
    engine.save_to_file(text, 'speech_offline.mp3')
    engine.runAndWait()
    return "speech_offline.mp3"

Common Pitfalls and Troubleshooting

Issue: "gtts_token" Errors or HTTP 403 Responses

Google may occasionally change the token generation algorithm. Update gTTS to the latest version:

pip install --upgrade gTTS

Issue: Long Text Truncation

While gTTS splits text automatically, very long texts (thousands of sentences) may take significant time. For production use with massive texts, consider splitting the text yourself and processing chunks in parallel:

from concurrent.futures import ThreadPoolExecutor
from gtts import gTTS

def process_chunk(args):
    text, index, lang = args
    tts = gTTS(text=text, lang=lang)
    filename = f"chunk_{index:04d}.mp3"
    tts.save(filename)
    return filename

def parallel_tts(long_text, lang='en', workers=4):
    """Process long text in parallel chunks."""
    # Split by paragraph
    paragraphs = [p.strip() for p in long_text.split('\n\n') if p.strip()]
    
    # Group paragraphs into reasonable chunks
    chunks = []
    current_chunk = ""
    for para in paragraphs:
        if len(current_chunk) + len(para) < 4000:
            current_chunk += para + "\n\n"
        else:
            if current_chunk:
                chunks.append(current_chunk.strip())
            current_chunk = para + "\n\n"
    if current_chunk:
        chunks.append(current_chunk.strip())
    
    # Process in parallel
    tasks = [(chunk, i, lang) for i, chunk in enumerate(chunks)]
    with ThreadPoolExecutor(max_workers=workers) as executor:
        results = list(executor.map(process_chunk, tasks))
    
    print(f"Generated {len(results)} audio chunks in parallel.")
    return results

Issue: Poor Pronunciation of Numbers and Abbreviations

Pre-process your text to expand abbreviations and format numbers for better pronunciation:

def normalize_for_speech(text):
    """Expand common abbreviations and format numbers for TTS."""
    replacements = {
        'Dr.': 'Doctor',
        'Mr.': 'Mister',
        'Mrs.': 'Missus',
        'e.g.': 'for example',
        'i.e.': 'that is',
        'etc.': 'and so on',
        'vs.': 'versus',
        '&': 'and',
    }
    
    for abbr, expansion in replacements.items():
        text = text.replace(abbr, expansion)
    
    # Expand numeric ranges
    text = text.replace('$1,000', 'one thousand dollars')
    
    return text

Complete Production-Ready TTS Class

Here's a comprehensive, production-ready class that encapsulates all the best practices discussed above. You can drop this into any project for robust text-to-speech functionality:

import os
import io
import hashlib
import time
import re
from datetime import datetime
from typing import Optional, Union
from gtts import gTTS

class TextToSpeechEngine:
    """
    Production-ready text-to-speech engine with caching, retry logic,
    input validation, and support for multiple languages.
    """
    
    SUPPORTED_LANGUAGES = {
        'en': 'English',    'es': 'Spanish',     'fr': 'French',
        'de': 'German',     'it': 'Italian',     'pt': 'Portuguese',
        'ja': 'Japanese',   'ko': 'Korean',      'hi': 'Hindi',
        'ar': 'Arabic',     'ru': 'Russian',     'zh': 'Chinese (Mandarin)',
    }
    
    def __init__(self, cache_dir: Optional[str] = None, max_retries: int = 3):
        self.max_retries = max_retries
        self.cache_dir = cache_dir
        if cache_dir:
            os.makedirs(cache_dir, exist_ok=True)
    
    def _clean_text(self, text: str, lang: str = 'en') -> str:
        """Normalize text for optimal speech synthesis."""
        text = re.sub(r'\s+', ' ', text).strip()
        
        # Common symbol expansions
        expansions = {
            '&': ' and ',   '%': ' percent ',
            '$': ' dollars ',  '@': ' at ',
            '#': ' hashtag ',
        }
        for symbol, replacement in expansions.items():
            text = text.replace(symbol, replacement)
        
        return text
    
    def _get_cache_path(self, text: str, lang: str) -> str:
        """Generate a unique cache file path based on content hash."""
        cache_key = hashlib.md5(f"{text}:{lang}".encode()).hexdigest()
        return os.path.join(self.cache_dir, f"{cache_key}.mp3")
    
    def generate_to_file(self, text: str, output_path: str, 
                         lang: str = 'en', slow: bool = False) -> str:
        """Generate speech and save to a file, with retry and caching."""
        text = self._clean_text(text, lang)
        
        if not text:
            raise ValueError("Empty text provided after cleaning.")
        
        # Check cache first
        if self.cache_dir:
            cache_path = self._get_cache_path(text, lang)
            if os.path.exists(cache_path):
                print(f"[Cache] Using cached audio for: {text[:50]}...")
                return cache_path
        
        # Generate with retries
        last_error = None
        for attempt in range(1, self.max_retries + 1):
            try:
                tts = gTTS(text=text, lang=lang, slow=slow)
                tts.save(output_path)
                
                # Copy to cache if enabled
                if self.cache_dir:
                    cache_path = self._get_cache_path(text, lang)
                    if output_path != cache_path:
                        import shutil
                        shutil.copy2(output_path, cache_path)
                
                return output_path
                
            except Exception as e:
                last_error = e
                if attempt < self.max_retries:
                    wait = attempt * 2
                    print(f"[Retry] Attempt {attempt} failed, waiting {wait}s...")
                    time.sleep(wait)
        
        raise RuntimeError(f"Failed after {self.max_retries} attempts. "
                           f"Last error: {last_error}")
    
    def generate_to_bytes(self, text: str, lang: str = 'en', 
                          slow: bool = False) -> io.BytesIO:
        """Generate speech in memory and return a BytesIO buffer."""
        text = self._clean_text(text, lang)
        
        for attempt in range(1, self.max_retries + 1):
            try:
                tts = gTTS(text=text, lang=lang, slow=slow)
                buffer = io.BytesIO()
                tts.write_to_fp(buffer)
                buffer.seek(0)
                return buffer
            except Exception as e:
                if attempt == self.max_retries:
                    raise RuntimeError(f"Failed to generate speech: {e}")
                time.sleep(attempt * 2)
    
    def batch_generate(self, items: list, lang: str = 'en', 
                       output_dir: str = "batch_output") -> list:
        """Generate speech for multiple text items with rate limiting."""
        os.makedirs(output_dir, exist_ok=True)
        results = []
        
        for i, item in enumerate(items):
            text = item if isinstance(item, str) else item.get('text', '')
            filename = f"batch_{i:04d}_{datetime.now().strftime('%H%M%S')}.mp3"
            output_path = os.path.join(output_dir, filename)
            
            try:
                self.generate_to_file(text, output_path, lang)
                results.append({'index': i, 'status': 'success', 'path': output_path})
                print(f"[Batch] {i+1}/{len(items)} completed.")
            except Exception as e:
                results.append({'index': i, 'status': 'failed', 'error': str(e)})
            
            # Rate limiting between requests
            if i < len(items) - 1:
                time.sleep(1.5)
        
        return results
    
    @classmethod
    def list_languages(cls) -> dict:
        """Return the dictionary of supported languages."""
        return cls.SUPPORTED_LANGUAGES

# Usage demonstration
if __name__ == "__main__":
    engine = TextToSpeechEngine(cache_dir="tts_cache", max_retries=3)
    
    # Generate to file
    engine.generate_to_file(
        text="Hello! This is a production-ready text-to-speech engine.",
        output_path="demo_output.mp3",
        lang='en',
        slow=False
    )
    
    # Generate in memory
    audio_buffer = engine.generate_to_bytes(
        text="This audio stays in memory for API responses.",
        lang='en'
    )
    print(f"In-memory audio size: {audio_buffer.getbuffer().nbytes} bytes")
    
    # List supported languages
    print("\nSupported languages:")
    for code, name in engine.list_languages().items():
        print(f"  {code}: {name}")

Conclusion

Building a text-to-speech application with Python and gTTS is remarkably straightforward yet opens up powerful possibilities. You've learned how to generate speech from text in multiple languages, control speech speed, handle long documents, work with audio in memory, and integrate TTS into web applications and batch processing pipelines. The library's simplicity—no API keys, no authentication

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles