Use case · Text to speech

Self-hosted text to speech on a dedicated server, with Piper

Piper is a local neural text-to-speech engine from the Open Home Foundation, licensed GPL-3.0-or-later and installed with pip. It ships a small HTTP server that turns a JSON request into a WAV file, runs on the CPU by default and uses an NVIDIA card only if you ask for CUDA. One caution before anything else: that server listens on 0.0.0.0:5000 unless you tell it otherwise.

Choose a dedicated server

What Piper is

Piper synthesises speech with VITS voices exported to ONNX Runtime and embeds espeak-ng to turn text into phonemes. Development moved from rhasspy/piper, now archived, to OHF-Voice/piper1-gpl; the PyPI package is piper-tts, version 1.8.0 at the time of writing, marked Alpha and declared GPL-3.0-or-later. Home Assistant and the NVDA screen reader are among the projects its README lists as users.

It offers four ways in: a command line, a Python API (PiperVoice.synthesize_wav, plus synthesize for streaming chunks), a C/C++ library and a Flask web server. The CLI reloads the model on every call, and its own documentation recommends the web server for repeated use. That is the piece this page sets up.

Voice licences: read the model card

The engine licence and the voice licence are separate questions. The rhasspy/piper-voices repository on Hugging Face is tagged MIT, yet each voice has a MODEL_CARD that names the dataset it was trained on and that dataset's licence. Piper's voices page says the project is intended for personal use and text-to-speech research only, adds no restrictions of its own on voice models, and warns that some voices carry restrictive licences. A few English examples from the cards:

VoiceDataset licence on the model card
en_US-libritts_r-medium (904 speakers)CC BY 4.0
en_US-ryan-highCC BY-NC-SA 4.0 (non-commercial)
en_US-lessac-mediumLinks the Blizzard 2013 Lessac data, issued under a research licence agreement
en_US-amy-medium, en_GB-alan-medium"See URL": the Mycroft mimic3-voices repository

python3 -m piper.download_voices fetches only the .onnx and .onnx.json files, not the MODEL_CARD. Open the card on Hugging Face for every voice you put in front of customers, and keep a copy with your deployment notes. We are not lawyers and this is not legal advice.

CPU or GPU

Synthesis runs on the CPU out of the box. Both the CLI and the web server accept --cuda, and the Python API takes use_cuda=True; all three need the onnxruntime-gpu package in place of the CPU runtime. Piper's documentation publishes no throughput figures, so measure: the built-in web page reports the synthesis time of the last utterance, which makes a CPU-versus-GPU comparison on your own text a few minutes' work.

Training is where a graphics card stops being optional. The training guide says most official voices were trained or fine-tuned on a Threadripper 1900X with 128 GB of RAM and an NVIDIA A6000 (48 GB) or 3090 (24 GB), and that users report success on cards with only 8 GB of VRAM. If you plan to fine-tune a voice from your own recordings, pick a machine from the GPU server list; for serving existing voices, start on a plain dedicated server and add a card only if your measurements call for it.

Install it as a locked-down service

On Ubuntu, switch the firewall on before anything listens, run Piper under its own account, and keep voices in one directory. Ubuntu's ufw defaults file, /etc/default/ufw, ships with IPV6=yes; confirm it, so the rules fence IPv6 traffic too.

sudo apt install -y python3-venv ufw
sudo ufw allow OpenSSH && sudo ufw enable
sudo useradd --system --create-home --home-dir /opt/piper --shell /usr/sbin/nologin piper
sudo -u piper bash -c 'cd /opt/piper && python3 -m venv venv && venv/bin/pip install "piper-tts[http]"'
sudo -u piper bash -c 'cd /opt/piper && mkdir -p voices && venv/bin/python -m piper.download_voices --data-dir voices en_US-libritts_r-medium'

Then a systemd unit, /etc/systemd/system/piper-tts.service, with --host 127.0.0.1 so the API never answers on a public address:

[Unit]
Description=Piper text-to-speech HTTP server
After=network-online.target
Wants=network-online.target

[Service]
User=piper
WorkingDirectory=/opt/piper
ExecStart=/opt/piper/venv/bin/python -m piper.http_server --host 127.0.0.1 --port 5000 --data-dir /opt/piper/voices -m en_US-libritts_r-medium
Restart=on-failure

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload && sudo systemctl enable --now piper-tts, then test from the server itself: curl -X POST -H 'Content-Type: application/json' -d '{"text": "Hello from the rack."}' -o test.wav http://127.0.0.1:5000/synthesize. To use the browser test page, forward the port over your own SSH login with ssh -L 5000:127.0.0.1:5000 you@your-server and visit localhost:5000 there.

The API, and what not to expose

  • POST /synthesize takes JSON with text (required) and optional voice, speaker, speaker_id, length_scale, noise_scale and noise_w_scale, and returns WAV. Omitted fields fall back to the command line, then to the voice config.
  • GET /info reports the default voice (the one passed with -m), its speakers and defaults; GET /voices lists the voices on disk.
  • A voice named in a request is loaded from the data directory on first use and stays in memory afterwards, so each extra voice costs memory rather than a reload on every call.
  • POST /download makes the server fetch any voice from Hugging Face onto its own disk. Nobody outside should reach it.

The server has no authentication of its own. Where other machines must call it, front it with a TLS-terminating reverse proxy that forwards only /synthesize behind HTTP basic auth or an API key, caps the request body, and returns 404 for everything else. If you package it in Docker instead, publish it as -p 127.0.0.1:5000:5000: a bare -p 5000:5000 binds to all IPv4 and IPv6 interfaces, and Docker's rules sit in front of ufw.

The machine

A dedicated server is the entire machine, with root, an unmetered port and one IPv4 address; IPv6 is added at checkout at no charge. Ubuntu is among the images in the configurator, and the OS reinstalls from the control panel. A racked machine is live about 30 minutes after the order is approved, and a build to order takes 4-24 hours.

  • Moonshot cartridges: the service page's class for one service per machine. A speech API that does nothing else is that kind of job; time your longest typical request on it before committing.
  • Desktop platform: an Intel Core i5-9500 with an NVIDIA GeForce RTX 3050 6GB, the place to try --cuda against the CPU on identical text.
  • Single socket: a web or application host with its own out-of-band console, when Piper sits next to the application that calls it.
  • Out-of-band console: every racked single-, dual- and quad-socket server has iLO, iDRAC or a Supermicro BMC, as do the m510 and m710x cartridges; the other cartridges have power control only. It is the way back in if a firewall rule locks you out.

Speech synthesis pairs naturally with the opposite direction. A self-hosted Whisper server transcribes audio on your own hardware, and the two together give a voice interface where no recording or reply leaves machines you control. The data centers page lists the five cities; put the server near the people who will listen.

Questions

Can I use Piper commercially?

The engine itself is GPL-3.0-or-later. Each voice is a separate question: its MODEL_CARD names the training data's licence, and some, such as en_US-ryan-high under CC BY-NC-SA 4.0, are non-commercial. Check every voice you serve, and ask a lawyer if the answer matters to your business.

Does Piper need a GPU?

No. It runs on the CPU by default. --cuda with the onnxruntime-gpu package moves synthesis to an NVIDIA card. Training new voices is the job that needs a GPU; the guide notes users training successfully on 8 GB cards.

Which port does the Piper HTTP server use?

Port 5000, bound to 0.0.0.0 by default. Pass --host 127.0.0.1 and reach it through a proxy or an SSH tunnel.

Can Piper copy someone's voice from a short sample?

Piper's documentation describes no such feature. A new voice is trained from a set of audio files with matching transcripts, ideally fine-tuned from an existing checkpoint, and exported to ONNX.

What audio format does the API return?

/synthesize returns a WAV file. The Python API can also stream raw 16-bit chunks if you build your own service.

Put your voices on your own hardware

Pick a dedicated server, install Ubuntu, and Piper is answering on localhost a few commands later.

Choose a dedicated server

Related on Server Room

Other use cases