How to Convert Text to Speech in Bash

How to Convert Text to Speech in Bash

How to Convert Text to Speech in Bash

A while back, I wanted a way to have my terminal read notifications and log summaries out loud while I was working on something else across another monitor. I didn’t want to build a whole app for it, so I put together a simple Bash text-to-speech script using existing command-line tools. It turned out to be far more useful than I expected, and I still use a version of it today for accessibility testing and hands-free notifications. Here’s how I built it.

Why Do Text-to-Speech from Bash

Bash itself has no built-in speech synthesis, but it’s an excellent orchestration layer for tools that do. Building a TTS script in Bash gives you:

The Tools Behind Bash TTS

Bash relies on external TTS engines; the two most common are:

Installing a TTS Engine

On Debian/Ubuntu:

sudo apt update
sudo apt install espeak-ng

On Fedora:

sudo dnf install espeak-ng

On macOS, say is already built in — no installation needed.

The Simplest TTS Script

#!/bin/bash

espeak-ng "Hello, this is your terminal speaking."

That’s genuinely all it takes to hear synthesized speech from a script. On macOS, the equivalent is:

say "Hello, this is your terminal speaking."

A Cross-Platform Wrapper Script

Since I work across both Linux and macOS machines, I built a wrapper that detects the operating system and picks the right TTS command automatically:

#!/bin/bash

set -euo pipefail

speak() {
    local text="$1"

    if command -v say >/dev/null 2>&1; then
        say "$text"
    elif command -v espeak-ng >/dev/null 2>&1; then
        espeak-ng "$text"
    elif command -v espeak >/dev/null 2>&1; then
        espeak "$text"
    else
        echo "Error: no supported text-to-speech engine found." >&2
        exit 1
    fi
}

speak "$1"

How This Works Internally

Adding Voice, Speed, and Pitch Controls

espeak-ng supports a range of options for customizing the voice output:

#!/bin/bash

set -euo pipefail

text="$1"
speed="${2:-150}"   # words per minute
pitch="${3:-50}"    # 0-99

espeak-ng -s "$speed" -p "$pitch" "$text"

You can list available voices with:

espeak-ng --voices

And use a specific voice with:

espeak-ng -v en-us+f3 "This is a female English voice."

Converting Text Files to Speech and Saving as Audio

Rather than speaking directly, you can also render speech to a .wav file for later playback or sharing:

#!/bin/bash

set -euo pipefail

input_file="$1"
output_file="${2:-output.wav}"

espeak-ng -f "$input_file" -w "$output_file"

echo "Audio saved to $output_file"

Reading Long Documents Aloud, One Paragraph at a Time

For longer text, I like breaking output into paragraph chunks so I can pause, skip, or replay a section without restarting the whole thing:

#!/bin/bash

set -euo pipefail

input_file="$1"

while IFS= read -r -d '' paragraph; do
    echo "----"
    echo "$paragraph"
    espeak-ng "$paragraph"
    read -rp "Press Enter for next paragraph, or 'q' to quit: " cmd
    [[ "$cmd" == "q" ]] && break
done < <(awk -v RS='' '{print; print "\0"}' "$input_file")

This uses awk with RS='' (paragraph mode, where blank lines separate records) to split the file into paragraphs, then reads them one at a time using a null-delimited read loop, pausing for user input between each.

Real-World Use Cases

Automation Example

Here’s a script I use to have my machine announce when a long-running backup job finishes:

#!/bin/bash

set -euo pipefail

backup_source="/data"
backup_dest="/backups/backup_$(date +%F).tar.gz"

tar -czf "$backup_dest" "$backup_source"

if [ $? -eq 0 ]; then
    espeak-ng "Backup completed successfully."
else
    espeak-ng "Warning. Backup failed. Please check the logs."
fi

This way, I can start a backup and walk away, trusting I’ll hear whether it succeeded or failed instead of babysitting a terminal window.

Best Practices

Security Considerations

Optimization Tips

ls *.txt | xargs -P 4 -I{} espeak-ng -f {} -w {}.wav

Troubleshooting Common Issues

Problem: espeak-ng: command not found. Install it via your package manager, or verify it’s in your PATH with which espeak-ng.

Problem: No sound is produced despite no errors. Check your system’s audio output device and volume levels; also confirm espeak-ng isn’t only writing to a file (-w flag) instead of playing audio directly.

Problem: Voice sounds robotic or hard to understand. Try a different voice with -v, adjust speed with -s, or consider using festival for a more natural-sounding alternative.

Problem: Script hangs when reading a large text file aloud. Break the file into smaller chunks (by paragraph or sentence) rather than passing the entire file as a single TTS call.

Common Mistakes to Avoid

Frequently Asked Questions

Do I need an internet connection for Bash text-to-speech? Not if you’re using offline engines like espeak-ng, espeak, or festival. Cloud-based options like Google Cloud TTS or Amazon Polly do require network access.

Can I change the language the TTS engine speaks in? Yes, most engines support multiple languages via a voice flag, e.g., espeak-ng -v fr "Bonjour tout le monde" for French.

How do I make the speech faster or slower? Use the -s flag with espeak-ng to set words-per-minute, or adjust the equivalent rate flag for whichever engine you’re using.

Can I use this to build an audiobook from a text file? Yes — render the text to a .wav file using the -f and -w flags, then optionally convert it to MP3 with ffmpeg for smaller file sizes.

Which engine sounds the most natural? Among free, offline options, festival tends to sound more natural than espeak-ng, though neither matches the quality of commercial cloud TTS services.

Summary

Bash doesn’t generate speech on its own, but it’s a fantastic glue layer for tools like espeak-ng, festival, or macOS’s say. Starting from a single line that speaks a string aloud, you can build a fully-featured TTS utility with adjustable speed, pitch, and voice, file-based rendering, and integration into notification pipelines for backups, builds, or accessibility needs. The real value comes from wiring TTS into automation you already run — turning silent scripts into ones that talk back.

References

Exit mobile version