Skip to content

Instantly share code, notes, and snippets.

@jameselsey
Last active August 14, 2025 10:57
Show Gist options
  • Select an option

  • Save jameselsey/40655169ab64db050531e7b02b6412e8 to your computer and use it in GitHub Desktop.

Select an option

Save jameselsey/40655169ab64db050531e7b02b6412e8 to your computer and use it in GitHub Desktop.
Better TTS Using Piper!

Here's the code to support my YouTube video: https://youtu.be/q6upRZ0-qpg

How to run

  1. Try out the voices and decide which one you like https://rhasspy.github.io/piper-samples/#en_GB-southern_english_female-low
  2. Download the voice onnx and onnx.json from HuggingFace https://huggingface.co/rhasspy/piper-voices/tree/main/en/en_GB/southern_english_female/low
  3. python -m venv .venv
  4. source .venv/bin/activate
  5. pip install -r requirements.txt
  6. python main.py
  7. Enjoy!

Linux

On linux, you might get this error:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/jelsey/dev/40655169ab64db050531e7b02b6412e8/.venv/lib/python3.11/site-packages/sounddevice.py", line 71, in <module>
    raise OSError('PortAudio library not found')
OSError: PortAudio library not found

If that happens, ensure these libraries are installed

sudo apt install -y libportaudio2 portaudio19-dev espeak-ng

The do a reinstall of sounddevice

pip install --force-reinstall sounddevice
import time
import pyttsx3
from piper import PiperVoice
import wave
import numpy as np
import sounddevice as sd
# Convenience function to play a filename
def play(target_filename):
# Play the wav using sounddevice
with wave.open(target_filename, 'rb') as wf:
sample_rate = wf.getframerate()
n_channels = wf.getnchannels()
n_frames = wf.getnframes()
audio = wf.readframes(n_frames)
# Convert byte data to numpy array
audio_np = np.frombuffer(audio, dtype=np.int16)
# If stereo, reshape for sounddevice
if n_channels == 2:
audio_np = audio_np.reshape(-1, 2)
# sounddevice expects float32 in [-1, 1]
audio_np = audio_np.astype(np.float32) / 32768.0
sd.play(audio_np, sample_rate)
sd.wait()
# Step 1: Slight pause so I have time to press play and record!
time.sleep(2)
# Step 2: Say the first line using pyttsx3
engine = pyttsx3.init()
engine.say("In this video, I'll show you how to upgrade your text to speech from this")
engine.runAndWait()
# Now try piper...
# Try a Piper voice!
amy_voice = PiperVoice.load("en-us-amy-low.onnx", config_path="en-us-amy-low.onnx.json")
first_voice_file = "piper_output.wav"
with wave.open(first_voice_file, "wb") as wav_file:
amy_voice.synthesize_wav("to this, using the Piper text to speech sdk, this sounds far more natural and there are a variety of voices to try", wav_file)
play(first_voice_file)
# Try another one!
southern_voice = PiperVoice.load("en_GB-southern_english_female-low.onnx", config_path="en_GB-southern_english_female-low.onnx.json")
second_voice_file = "second_voice.wav"
with wave.open(second_voice_file, "wb") as wav_file:
southern_voice.synthesize_wav("like this one, a southern UK female voice", wav_file)
play(second_voice_file)
pyttsx3
piper-tts
sounddevice
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment