DevelopmentJanuary 20, 20257 min read

Text-to-Speech App using gTTS and Streamlit

Convert text to natural speech with Python, gTTS, and Streamlit — language selection, speed control, and instant audio download.

Galvan

Galvan

Founder & Creator

Introduction

Text-to-Speech (TTS) technology has become a core part of modern applications — from accessibility tools and language learning platforms to podcast generators and voice assistants. Thanks to Python's gTTS (Google Text-to-Speech) library, you can convert any text into natural-sounding audio in over 30 languages with just a few lines of code.

In this tutorial you will build a polished TTS web app using gTTS and Streamlit. The finished app will let users type or paste any text, choose a language and speech speed, preview the audio directly in the browser, and download the generated MP3 file.

This project pairs naturally with our Translator App — you can translate text first, then feed the translation into this TTS app to hear it spoken aloud. It is also a core module of the larger SANGAM AI toolkit.


> 🎬 Watch the Full Video Tutorial:

> Watch the walkthrough on YouTube: Building a Simple Text-to-Speech Converter with Python and Streamlit


What is gTTS?

gTTS (Google Text-to-Speech) is a Python library that interfaces with Google Translate's TTS API. It sends your text to Google's servers and returns an MP3 audio stream, which you can then save or play back.

gTTS vs Other TTS Libraries

LibraryFreeOfflineLanguagesQualityEase of Use
gTTS✅ Yes❌ No30+⭐⭐⭐⭐⭐⭐⭐⭐⭐
pyttsx3✅ Yes✅ YesSystem voices⭐⭐⭐⭐⭐⭐⭐
AWS Polly❌ Paid❌ No60+⭐⭐⭐⭐⭐⭐⭐⭐
ElevenLabs❌ Paid❌ No28⭐⭐⭐⭐⭐⭐⭐⭐
Azure TTS❌ Paid❌ No100+⭐⭐⭐⭐⭐⭐⭐
Coqui TTS✅ Yes✅ Yes20+⭐⭐⭐⭐⭐⭐

gTTS is the perfect choice for beginners and small projects: it is completely free, requires zero API key setup, and produces Google's polished TTS voices.


Prerequisites

Make sure you have the following installed before starting:

  • Python 3.8+ — Download from python.org.
  • Libraries — Install with pip:
  • code
    pip install streamlit gTTS
    PackagePurpose
    streamlitWeb app framework
    gTTSGoogle Text-to-Speech engine
    ioBuilt-in Python module for in-memory byte streams

    Supported Languages

    gTTS supports over 30 languages and regional variants. Here is a selection of the most commonly used ones:

    LanguageCodeRegional Variants Available
    Englishenen-us, en-gb, en-au, en-in
    Hindihi
    Spanisheses-es, es-us, es-mx
    Frenchfrfr-fr, fr-ca
    Germande
    Portugueseptpt-br, pt-pt
    Japaneseja
    Koreanko
    Arabicar
    Chinesezh-CNzh-TW
    Italianit
    Russianru
    Dutchnl
    Polishpl

    For the full list, visit the gTTS documentation.


    Project Structure

    code
    tts_app/
    ├── tts_app.py          ← Main Streamlit application
    └── requirements.txt    ← pip dependencies

    Create requirements.txt:

    code
    streamlit
    gTTS

    Step 1: Create the Basic App

    Create tts_app.py and set up the page:

    code
    import streamlit as st
    from gtts import gTTS, lang
    import io
    
    st.set_page_config(
        page_title="Text to Speech",
        page_icon="🔊",
        layout="centered"
    )
    
    st.title("🔊 Text-to-Speech Converter")
    st.write(
        "Convert any text into natural-sounding speech. "
        "Choose your language, adjust the speed, then preview or download the audio."
    )

    Step 2: Build the Language Selector

    gTTS provides a helper function lang.tts_langs() that returns a dictionary of all supported language codes and their names. We can use this to build a dynamic dropdown:

    code
    # Get all supported languages from gTTS
    all_langs = lang.tts_langs()  # Returns {"en": "English", "hi": "Hindi", ...}
    
    # Flip to {name: code} for display
    lang_name_to_code = {v: k for k, v in all_langs.items()}
    lang_names = sorted(lang_name_to_code.keys())
    
    col1, col2 = st.columns(2)
    
    with col1:
        selected_lang_name = st.selectbox(
            "🌍 Language",
            lang_names,
            index=lang_names.index("English"),
        )
        lang_code = lang_name_to_code[selected_lang_name]
    
    with col2:
        slow_mode = st.radio(
            "🐢 Speech Speed",
            options=["Normal", "Slow"],
            horizontal=True,
        )
        is_slow = slow_mode == "Slow"

    Step 3: Text Input Area

    Add a large text area where users can type or paste any content:

    code
    st.divider()
    
    text_input = st.text_area(
        "📝 Enter your text:",
        height=220,
        placeholder=(
            "Type or paste your text here...\n\n"
            "Examples:\n"
            "• A paragraph you want to hear read aloud\n"
            "• A script for a video or podcast\n"
            "• A translated phrase you want to pronounce correctly"
        ),
        max_chars=5000,
    )
    
    char_count = len(text_input)
    st.caption(f"{char_count} / 5,000 characters used")

    The 5,000 character limit prevents accidental very large requests to Google's TTS API.


    Step 4: Generate and Play the Audio

    This is the core of the app — converting text to speech and playing it in the browser:

    code
    if st.button("🎙️ Convert to Speech", type="primary", use_container_width=True):
        if not text_input.strip():
            st.warning("Please enter some text before converting.")
        else:
            with st.spinner("Generating audio..."):
                try:
                    # Generate TTS audio
                    tts = gTTS(text=text_input, lang=lang_code, slow=is_slow)
    
                    # Write to an in-memory byte buffer (no temp files needed)
                    audio_buffer = io.BytesIO()
                    tts.write_to_fp(audio_buffer)
                    audio_buffer.seek(0)
    
                    st.success(f"✅ Audio generated in {selected_lang_name}!")
    
                    # Display the inline player
                    st.audio(audio_buffer, format="audio/mp3")
    
                    # Download button
                    audio_buffer.seek(0)
                    st.download_button(
                        label="⬇️ Download MP3",
                        data=audio_buffer,
                        file_name="speech.mp3",
                        mime="audio/mpeg",
                        use_container_width=True,
                    )
    
                except Exception as e:
                    st.error(f"Something went wrong: {e}")
                    st.info(
                        "Tip: Check your internet connection — "
                        "gTTS requires access to Google's servers."
                    )

    Using io.BytesIO() instead of saving to a file on disk is the correct pattern for Streamlit: it keeps everything in memory and works perfectly in cloud environments where writing to disk is restricted.


    Step 5: Add Multi-Language Demo

    Let us add a helpful demo section that converts a greeting phrase into multiple languages at once — great for showcasing the app's capabilities:

    code
    st.divider()
    with st.expander("🌐 Multi-Language Demo — Hear 'Hello' in 6 languages"):
        demo_phrases = {
            "English": ("en",  "Hello! Welcome to the Text-to-Speech app."),
            "Hindi":   ("hi",  "नमस्ते! टेक्स्ट-टू-स्पीच ऐप में आपका स्वागत है।"),
            "Spanish": ("es",  "¡Hola! Bienvenido a la aplicación de texto a voz."),
            "French":  ("fr",  "Bonjour! Bienvenue dans l'application de synthèse vocale."),
            "German":  ("de",  "Hallo! Willkommen bei der Text-to-Speech-App."),
            "Japanese":("ja",  "こんにちは!テキスト読み上げアプリへようこそ。"),
        }
    
        for language, (code, phrase) in demo_phrases.items():
            col_a, col_b = st.columns([1, 3])
            with col_a:
                st.write(f"**{language}**")
            with col_b:
                if st.button(f"▶️ Play", key=f"demo_{code}"):
                    tts = gTTS(text=phrase, lang=code, slow=False)
                    buf = io.BytesIO()
                    tts.write_to_fp(buf)
                    buf.seek(0)
                    st.audio(buf, format="audio/mp3")

    Complete tts_app.py

    Here is the complete, final version of the app:

    code
    import streamlit as st
    from gtts import gTTS, lang
    import io
    
    st.set_page_config(page_title="Text to Speech", page_icon="🔊", layout="centered")
    st.title("🔊 Text-to-Speech Converter")
    st.write("Convert text to natural speech in 30+ languages. Preview and download the audio.")
    
    all_langs = lang.tts_langs()
    lang_name_to_code = {v: k for k, v in all_langs.items()}
    lang_names = sorted(lang_name_to_code.keys())
    
    col1, col2 = st.columns(2)
    with col1:
        selected_lang_name = st.selectbox("🌍 Language", lang_names, index=lang_names.index("English"))
        lang_code = lang_name_to_code[selected_lang_name]
    with col2:
        is_slow = st.radio("🐢 Speed", ["Normal", "Slow"], horizontal=True) == "Slow"
    
    st.divider()
    text_input = st.text_area("📝 Enter your text:", height=220, max_chars=5000,
                               placeholder="Type or paste your text here...")
    st.caption(f"{len(text_input)} / 5,000 characters")
    
    if st.button("🎙️ Convert to Speech", type="primary", use_container_width=True):
        if not text_input.strip():
            st.warning("Please enter some text.")
        else:
            with st.spinner("Generating audio..."):
                try:
                    tts = gTTS(text=text_input, lang=lang_code, slow=is_slow)
                    buf = io.BytesIO()
                    tts.write_to_fp(buf)
                    buf.seek(0)
                    st.success(f"✅ Ready in {selected_lang_name}!")
                    st.audio(buf, format="audio/mp3")
                    buf.seek(0)
                    st.download_button("⬇️ Download MP3", buf, "speech.mp3", "audio/mpeg",
                                       use_container_width=True)
                except Exception as e:
                    st.error(f"Error: {e}")
    
    st.divider()
    with st.expander("🌐 Multi-Language Demo"):
        demos = {"English": ("en", "Hello! Welcome."), "Hindi": ("hi", "नमस्ते!"),
                 "Spanish": ("es", "¡Hola!"), "French": ("fr", "Bonjour!")}
        for name, (code, phrase) in demos.items():
            c1, c2 = st.columns([1, 3])
            c1.write(f"**{name}**")
            with c2:
                if st.button("▶️ Play", key=f"d_{code}"):
                    t = gTTS(phrase, lang=code)
                    b = io.BytesIO()
                    t.write_to_fp(b)
                    b.seek(0)
                    st.audio(b, format="audio/mp3")

    Run the App

    code
    streamlit run tts_app.py

    How gTTS Works Internally

    Under the hood, gTTS:

  • Splits your text into chunks of ~100 characters (Google's TTS API has a per-chunk limit).
  • Sends each chunk as a GET request to https://translate.google.com/translate_tts.
  • Concatenates the MP3 chunks into a single audio stream.
  • Returns the combined stream, which you write to a file or BytesIO buffer.
  • This is why a working internet connection is required — gTTS is not an offline library.


    Common Use Cases

    Use CaseHow to Adapt the App
    Language LearningAdd phonetic transcription alongside audio
    Accessibility ToolIncrease font size, add keyboard shortcuts
    Podcast Script ReaderUpload a .txt script file and convert in bulk
    Pronunciation CheckerPair with the Translator App
    E-learning PlatformEmbed audio players next to quiz questions
    Audio DigestSummarise articles and convert to MP3

    Troubleshooting

    ProblemLikely CauseFix
    No module named 'gtts'Library not installedRun pip install gTTS
    gTTSError: 429Rate limited by GoogleWait 30 seconds and retry
    Empty or silent audioWhitespace-only inputAdd text_input.strip() check
    AssertionError: No textText is empty stringValidate before calling gTTS()
    Truncated audioText too longSplit into paragraphs and convert separately
    Language not foundWrong language codeUse lang.tts_langs() to get valid codes

    Extending the App

    Batch File Conversion

    You can extend the app to convert an uploaded .txt file into speech:

    code
    uploaded = st.file_uploader("Upload a .txt file", type=["txt"])
    if uploaded:
        file_text = uploaded.read().decode("utf-8")
        st.text_area("File Preview", file_text[:500] + "...", disabled=True)
        if st.button("Convert File to Speech"):
            tts = gTTS(text=file_text[:5000], lang=lang_code, slow=is_slow)
            buf = io.BytesIO()
            tts.write_to_fp(buf)
            buf.seek(0)
            st.audio(buf, format="audio/mp3")

    Speaking Numbers and Abbreviations

    gTTS reads numbers as digits by default. To have it read 2025 as "twenty twenty-five" instead of "two thousand and twenty-five", convert it first:

    code
    import inflect
    p = inflect.engine()
    number_as_words = p.number_to_words(2025)  # → "two thousand and twenty-five"

    Install inflect with pip install inflect.


  • Translator App — Translate text first, then paste it into this TTS app to hear the pronunciation.
  • SANGAM AI Toolkit — The TTS module in SANGAM AI is built on the same gTTS foundation shown here.
  • Chatbot with Mistral AI — Combine the chatbot with this TTS app so the AI speaks its responses aloud.

  • Conclusion

    You have built a production-ready Text-to-Speech web app using Python, gTTS, and Streamlit. The app handles text input, language selection, speed control, in-browser audio playback, and MP3 downloads — all in under 50 lines of core logic.

    TTS is a remarkably versatile tool. Whether you are building a language-learning assistant, an accessibility aid, or a voice-over generator for your content, the techniques in this tutorial give you a solid, extensible foundation.

    Resources:

  • gTTS Documentation
  • gTTS on PyPI
  • Streamlit Audio API
  • Streamlit Download Button
  • Google Text-to-Speech Overview