Self-HostingAI

Piper Text-to-Speech: Fast Local Voices on a Raspberry Pi, Linux, Windows or Mac

Before you start

  • 21 min read

Boxes marked Run in terminal are what you type; plain text explains why. Check what you need first

What you get in one minute#

Piper is a fast, free text-to-speech engine that turns text into spoken audio on your own computer, with no cloud account, and it is light enough to run on a Raspberry Pi.

Piper official logo

Logo: the official Piper project (github.com/OHF-Voice/piper1-gpl)

You give Piper a sentence and a voice file, and it writes a WAV file or streams audio. It speaks about 40 languages, from a command line, a small web server or Home Assistant. People use it for smart-home announcements, screen readers and any project that needs a voice without a cloud service.

The project moved. Read this before you search. Most older tutorials use rhasspy/piper. That repository is now archived and read-only (since October 2025), and its README says "Development has moved" to OHF-Voice/piper1-gpl, run by the Open Home Foundation. The old code was MIT; the new code is GPL-3.0. It is alive (a release in September 2026, commits in November 2026), but its README also asks for new maintainers, and many issues have no reply. We say this plainly so you can decide.

Current versionpiper-tts 1.8.0, released September 2026 (PyPI and GitHub)
Time neededAbout 20 minutes plus the voice download (our estimate)
SizeInstall wheel about 34 MB; one medium voice 63 MB; a high voice 114 MB
Ports5000 for the HTTP server (Piper docs); 10200 for the Home Assistant wrapper
LicenceCode: GPL-3.0. Each voice has its own licence, some non-commercial
Official docsgithub.com/OHF-Voice/piper1-gpl and its docs folder

At a glance:

  • What it is: a Python package, piper-tts, with a command line, an HTTP server and a Python API.
  • Where it runs: Linux (x86_64 and 64-bit Arm, so Raspberry Pi 4 and 5 with a 64-bit system), Windows, Mac.
  • Voices: two files per voice, a .onnx model and a .onnx.json config, downloaded once from Hugging Face.
  • No login: the HTTP server has no password. Keep it on 127.0.0.1 or behind a proxy that asks for one.
  • Not OpenAI-style: the API is Piper's own (/synthesize). Open WebUI needs an OpenAI-style address; see our Kokoro-FastAPI guide.
  • Related guides: Home Assistant voice control uses Piper as its voice; Chatterbox clones voices on a stronger computer.

How it fits together#

Text comes in through one of three doors. The engine turns it into phonemes with espeak-ng, then a voice model on your disk turns the phonemes into sound.

Flow diagram: you or your script send text to the Piper command line or HTTP server on port 5000, and Home Assistant optionally reaches the Wyoming server on port 10200; all three feed the Piper engine, which turns text into phonemes with espeak-ng; a voice model of two files on your disk, downloaded once from Hugging Face, turns the phonemes into speech; the result is a WAV file or raw audio stream

Drawn for this guide from the Piper docs (CLI, HTTP API, Voices) and the wyoming-piper README, November 2026. Dashed parts are optional.

Before you start#

Linux and Raspberry PiWindowsMac
Systemx86_64, or 64-bit Arm (Raspberry Pi OS 64-bit)Windows, 64-bit Intel or AMDIntel or Apple Silicon (see the warning in Step 1)
Python3.9 or newer (PyPI lists 3.9 to 3.13)samesame
RAMNot documented by Pipersamesame
DiskAbout 100 MB for the install and one medium voicesamesame

Check Python, and Docker only if you use Step 5:

Run in terminalbash
python3 --version
docker --version
docker compose version
Run in terminalpowershell
python --version
docker --version
docker compose version

Checklist:

  • [ ] Python 3.9 or newer
  • [ ] Internet for the install and the one-time voice download
  • [ ] Port 5000 free if you run the HTTP server
  • [ ] You know what the voice licence allows (see "Voices and licences")
  • [ ] For Step 5 only: Docker, and port 10200 free
  • [ ] For the HTTPS section only: a DNS name pointing at this machine and ports 80 and 443 free

Tested on November 2026: not run by DIY Lab Hub on Linux, Windows or Mac (a rule for this batch); every command comes from the official docs listed in Sources.

Raspberry Pi: Piper publishes wheels for 64-bit Arm (aarch64) and no 32-bit Arm wheel, so use 64-bit Raspberry Pi OS. Home Assistant's docs say medium voices run at usable speed on a Pi 4, and suggest low or x_low voices if you want more speed.

Step 1: Install Piper in a virtual environment#

Use a virtual environment, not a system-wide install. Recent Debian and Ubuntu systems refuse system-wide pip install with error: externally-managed-environment (issue #318 reports it on Ubuntu 24.04), and a virtual environment is the standard way around that.

Linux#

Run in terminalbash
mkdir -p ~/piper-tts/voices
cd ~/piper-tts
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install "piper-tts[http]==1.8.0"

If python3 -m venv fails, install the venv package for your distribution (the Ubuntu message in issue #318 names python3-full). The [http] part adds Flask for the web server (Piper's HTTP API page). We pin 1.8.0 so a later release cannot change the commands under you.

Windows (PowerShell)#

Codepowershell
New-Item -ItemType Directory -Force "$HOME\piper-tts\voices" | Out-Null
Set-Location "$HOME\piper-tts"
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install "piper-tts[http]==1.8.0"

If PowerShell refuses Activate.ps1, the Python docs say to allow scripts for your user once: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser.

Mac (Terminal)#

Same commands as Linux:

Run in terminalbash
mkdir -p ~/piper-tts/voices
cd ~/piper-tts
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
python3 -m pip install "piper-tts[http]==1.8.0"

The quotes matter on the Mac: zsh, its default shell, reads [http] as a pattern.

Warning, Apple Silicon: issue #272 (open since August 2026) reports that the macOS arm64 wheel of 1.6.1 failed on every sentence with a build-machine path in the error. We did not confirm that for 1.8.0. If you see it, the reporter's workaround was a Linux container; see Troubleshooting.

Check it worked. The package should report version 1.8.0 and the command should print its options:

Run in terminalbash
python3 -m pip show piper-tts
python3 -m piper --help

On Windows use python in place of python3.

Step 2: Download a voice#

A voice is two files: en_US-lessac-medium.onnx and en_US-lessac-medium.onnx.json. Names follow <language>_<REGION>-<name>-<quality>. Listen to samples first at rhasspy.github.io/piper-samples, then download. --data-dir is the folder to save to; without it, Piper saves to the current folder.

Linux#

Run in terminalbash
python3 -m piper.download_voices
python3 -m piper.download_voices en_US-lessac-medium --data-dir ~/piper-tts/voices

The first command lists all voices. The second downloads one.

Windows (PowerShell)#

Run in terminalpowershell
python -m piper.download_voices
python -m piper.download_voices en_US-lessac-medium --data-dir "$HOME\piper-tts\voices"

Mac (Terminal)#

Same commands as Linux:

Run in terminalbash
python3 -m piper.download_voices
python3 -m piper.download_voices en_US-lessac-medium --data-dir ~/piper-tts/voices

Check it worked. The folder has the two files. The .onnx file should be about 63 MB (63,201,294 bytes in the voice list on Hugging Face):

Run in terminalbash
ls -l ~/piper-tts/voices
Codepowershell
Get-ChildItem "$HOME\piper-tts\voices"

Tip: Quality levels, from the Home Assistant Piper docs: x_low (16 kHz, smallest and fastest), low (16 kHz), medium (22.05 kHz, the usual choice), high (22.05 kHz, slowest, best). Start with medium; go down a level only if your Pi is too slow.

Step 3: Say your first sentence#

Linux#

Run in terminalbash
python3 -m piper -m en_US-lessac-medium --data-dir ~/piper-tts/voices -f test.wav -- 'This is a test.'
aplay test.wav

aplay comes with the ALSA tools on most Linux systems; any audio player works.

Windows (PowerShell)#

Run in terminalpowershell
python -m piper -m en_US-lessac-medium --data-dir "$HOME\piper-tts\voices" -f test.wav -- 'This is a test.'
(New-Object System.Media.SoundPlayer "$PWD\test.wav").PlaySync()

Mac (Terminal)#

Same Piper command as Linux, then play it with the built-in afplay:

Run in terminalbash
python3 -m piper -m en_US-lessac-medium --data-dir ~/piper-tts/voices -f test.wav -- 'This is a test.'
afplay test.wav

Check it worked. You hear "This is a test." and test.wav exists. The playback commands are standard system tools, not Piper docs. Piper can also read text from a pipe, and from files with --input-file.

If you leave out -f, Piper tries to play through ffplay. Without ffplay it logs Audio playback is not available (ffplay). Writing audio to output.wav. and writes output.wav for you.

Step 4: Run the HTTP server (on this machine only)#

The server loads the voice once, so every request is fast. The Piper docs say the command-line way is slow for repeated use because it reloads the model each time.

The default is wide open. In the 1.8.0 source the --host default is 0.0.0.0 (every network interface), the server has no login, and it runs on Flask's built-in development server. Set --host 127.0.0.1 unless you put a proxy in front (see the HTTPS section).

Linux#

Run in terminalbash
cd ~/piper-tts
source .venv/bin/activate
export ORT_DISABLE_TELEMETRY=1
python3 -m piper.http_server -m en_US-lessac-medium --host 127.0.0.1 --data-dir ~/piper-tts/voices

In a second terminal:

Run in terminalbash
curl http://127.0.0.1:5000/info
curl -X POST -H 'Content-Type: application/json' -d '{ "text": "This is a test." }' -o test2.wav http://127.0.0.1:5000/synthesize

To keep it running on a Raspberry Pi or server, this is a standard systemd service (not from the Piper docs). Replace <your-user>:

File contentini
[Unit]
Description=Piper HTTP server
After=network.target

[Service]
User=<your-user>
WorkingDirectory=/home/<your-user>/piper-tts
Environment=ORT_DISABLE_TELEMETRY=1
ExecStart=/home/<your-user>/piper-tts/.venv/bin/python -m piper.http_server -m en_US-lessac-medium --host 127.0.0.1 --data-dir /home/<your-user>/piper-tts/voices
Restart=on-failure

[Install]
WantedBy=multi-user.target

Save it as /etc/systemd/system/piper-http.service, then run sudo systemctl daemon-reload and sudo systemctl enable --now piper-http.

Windows (PowerShell)#

Codepowershell
Set-Location "$HOME\piper-tts"
.\.venv\Scripts\Activate.ps1
$env:ORT_DISABLE_TELEMETRY = "1"
python -m piper.http_server -m en_US-lessac-medium --host 127.0.0.1 --data-dir "$HOME\piper-tts\voices"

In a second PowerShell window (curl in PowerShell is a different command, so use Invoke-RestMethod):

Codepowershell
Invoke-RestMethod http://127.0.0.1:5000/info
Invoke-RestMethod -Method Post -Uri http://127.0.0.1:5000/synthesize -ContentType 'application/json' -Body '{"text":"This is a test."}' -OutFile test2.wav

Mac (Terminal)#

Same commands as Linux:

Run in terminalbash
cd ~/piper-tts
source .venv/bin/activate
export ORT_DISABLE_TELEMETRY=1
python3 -m piper.http_server -m en_US-lessac-medium --host 127.0.0.1 --data-dir ~/piper-tts/voices

Check it worked. /info returns JSON with the voice name, language and number of speakers (Piper docs). test2.wav plays like test.wav. Opening http://127.0.0.1:5000 shows a page where you type text and click Speak. The request fields are text (required), voice, speaker, speaker_id, length_scale (speed), noise_scale and noise_w_scale.

Tip: ORT_DISABLE_TELEMETRY=1 is explained in "Security and testing". Setting it costs nothing, and it is already in the service file above.

Step 5: Use Piper with Home Assistant (optional)#

Home Assistant talks to Piper through the Wyoming protocol, not through the HTTP server above. The maintained wrapper is OHF-Voice/wyoming-piper (version 2.5.2, MIT). If you run Home Assistant OS, you do not need Docker: install the Piper app from Settings > Apps and Home Assistant finds it. Otherwise run the wrapper's image. Our Home Assistant voice guide shows the rest of the chain.

The image is published for amd64 and arm64 only, so a 32-bit Raspberry Pi OS cannot run it. Data goes in ~/docker_volumes/piper.

Linux#

Run in terminalbash
mkdir -p ~/docker_volumes/piper/data ~/docker_volumes/piper/backups
cd ~/docker_volumes/piper
cat > docker-compose.yml << 'EOF'
services:
  piper:
    image: rhasspy/wyoming-piper:2.5.2
    container_name: wyoming-piper
    restart: unless-stopped
    command: --voice en_US-lessac-medium
    ports:
      - "10200:10200"
    volumes:
      - ./data:/data
EOF
docker compose up -d
docker compose ps
docker compose logs --tail=50 piper

Windows (PowerShell)#

Use Docker Desktop. The Compose file is the same as on Linux.

Codepowershell
New-Item -ItemType Directory -Force "$HOME\docker_volumes\piper\data", "$HOME\docker_volumes\piper\backups" | Out-Null
Set-Location "$HOME\docker_volumes\piper"
Set-Content -Path docker-compose.yml -Value @'
services:
  piper:
    image: rhasspy/wyoming-piper:2.5.2
    container_name: wyoming-piper
    restart: unless-stopped
    command: --voice en_US-lessac-medium
    ports:
      - "10200:10200"
    volumes:
      - ./data:/data
'@
docker compose up -d
docker compose ps

Mac (Terminal)#

Same commands as Linux, with Docker Desktop.

Check it worked. The container is running. The voice downloads on first start, so the first start takes longer. Then test that the port answers (the Wyoming port speaks TCP, not HTTP):

Run in terminalbash
nc -z 127.0.0.1 10200 && echo "piper port open"
Codepowershell
Test-NetConnection 127.0.0.1 -Port 10200

In Home Assistant, go to Settings > Devices & services, add Wyoming Protocol, enter this machine's address and port 10200. Then pick Piper as the text-to-speech engine in Settings > Voice assistants.

Tip: Wyoming has no login either. Publish port 10200 to your home network only, and never to the internet.

Voices and licences#

The Piper docs say: "Piper is intended for personal use and text to speech research only; we do not impose any additional restrictions on voice models. Some voices may have restrictive licenses, however, so please review them carefully!" The MODEL_CARD file next to each voice has the licence of the data it was trained on.

We read the model cards of all 156 voices in the voice list in November 2026: 17 list a non-commercial licence, 9 list none or "Unknown", and 33 more say only "See URL" or similar. A few examples from the cards:

VoiceLicence on its model cardWhat it means
en_US-lessac (the default almost everywhere)The Lessac Blizzard 2013 research licenceThat licence excludes commercial use, including developing voice-synthesis products
en_US-ryanCC BY-NC-SA 4.0Non-commercial, share-alike; fine-tuned from Lessac
en_US-libritts_rCC BY 4.0Give credit; fine-tuned from Lessac
en_US-ljspeechPublic domainThe card lists no limit
en_US-joeCC0The card lists no limit

For personal and home use this is usually fine. If you sell a product, publish audio or train another model on the output, check the card, and note that three questions about Lessac and the commercial-use position (issues #314, #333 and #340) were open with no maintainer answer when we read them. This is not legal advice. The code licence also matters: Piper itself is GPL-3.0, which brings obligations if you build it into software you distribute.

Put it behind HTTPS (with or without Traefik)#

You only need this if other computers call the HTTP server (Step 4) or you want a browser lock icon. If everything runs on one machine, keep 127.0.0.1 and skip this section. Because the server has no login, put a password at the proxy. This route is for Linux; on Windows and Mac use the Caddy route with Caddy installed natively.

With Traefik#

The HTTP server runs on the host, not in Docker, so use Traefik's file provider rather than labels. Start Piper with --host <piper-host-ip> (not 127.0.0.1, so Traefik can reach it) and block port 5000 for everyone except Traefik with your firewall. On a server with Traefik v3 and an https entrypoint, add piper.yml to the folder set in providers.file.directory. Make the user line with htpasswd -nB <user>:

File contentyaml
http:
  routers:
    piper:
      rule: "Host(`tts.<your-domain>`)"
      entryPoints:
        - https
      tls: {}
      middlewares:
        - piper-auth
      service: piper
  middlewares:
    piper-auth:
      basicAuth:
        users:
          - "<user>:<hash-from-htpasswd>"
  services:
    piper:
      loadBalancer:
        servers:
          - url: "http://<piper-host-ip>:5000"

Check it worked. curl -I https://tts.<your-domain>/ returns an HTTP status line over HTTPS (401 without the password).

Without Traefik: Caddy#

Caddy gets a Let's Encrypt certificate for a public domain by itself, or makes a local one with tls internal. It can run in Docker with host networking on Linux, so it reaches Piper on 127.0.0.1. We mount the folder conf, not the single Caddyfile (the Caddy Docker docs warn against single-file mounts). Our Caddy guide goes deeper.

Run in terminalbash
mkdir -p ~/docker_volumes/caddy/conf ~/docker_volumes/caddy/data ~/docker_volumes/caddy/config
cd ~/docker_volumes/caddy
cat > docker-compose.yml << 'EOF'
services:
  caddy:
    image: caddy:2.11.8
    container_name: caddy
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./conf:/etc/caddy
      - ./data:/data
      - ./config:/config
EOF
docker run --rm -it caddy:2.11.8 caddy hash-password

The last command asks for a password (it is not echoed) and prints a hash. Paste the hash into conf/Caddyfile. For a public domain:

File contenttext
tts.example.com {
    basic_auth {
        <user> <paste-the-hash-here>
    }
    reverse_proxy 127.0.0.1:5000
}

For a name used at home only (tls internal makes Caddy's own local certificate):

File contenttext
tts.home.arpa {
    tls internal
    basic_auth {
        <user> <paste-the-hash-here>
    }
    reverse_proxy 127.0.0.1:5000
}

Then start it and test:

Run in terminalbash
docker compose up -d
curl -I https://tts.example.com/

Windows and Mac: install Caddy natively (Caddy's install page lists Homebrew for Mac with brew install caddy and Chocolatey for Windows with choco install caddy, both community-maintained), save the same Caddyfile, and run caddy run --config Caddyfile. For a local certificate, caddy trust (run as administrator on Windows) installs Caddy's root on that machine. On other devices, copy the root file out of Caddy's data folder and trust it there; Linux Docker users can use docker compose cp caddy:/data/caddy/pki/authorities/local/root.crt ./caddy-root.crt first.

Tip: A certificate error usually means the name in the Caddyfile differs from the DNS record you opened. Let's Encrypt needs ports 80 and 443.

Security and testing#

  • No login anywhere. Piper's HTTP server and the Wyoming port have none. Use --host 127.0.0.1, a firewall, or the proxy above.
  • The /download endpoint lets any client that can reach the server make it fetch voices onto your disk. Another reason not to expose port 5000.
  • Development server. Flask's docs say its built-in server is not for production (issue #185 asks for a better one). Behind a proxy on a home network it is acceptable; never put it straight on the internet.
  • Telemetry in the engine under Piper. Piper uses ONNX Runtime. The ONNX Runtime privacy page says its official builds on Windows, Linux and macOS have telemetry on by default (added in version 1.29.0), and that setting ORT_DISABLE_TELEMETRY=1 before it starts turns it off. A user of the Wyoming image saw it send traffic, and wyoming-piper 2.5.1 now sets the variable itself. Plain pip install does not, so set it. We did not capture any traffic ourselves.
  • Setting the variable for good. Linux and Mac: add export ORT_DISABLE_TELEMETRY=1 to ~/.bashrc or ~/.zshrc. Windows: setx ORT_DISABLE_TELEMETRY 1, then open a new window.

Functional test. One command proves the whole chain:

Run in terminalbash
python3 -m piper -m en_US-lessac-medium --data-dir ~/piper-tts/voices -f check.wav -- 'Piper works.'
Run in terminalpowershell
python -m piper -m en_US-lessac-medium --data-dir "$HOME\piper-tts\voices" -f check.wav -- 'Piper works.'

Check it worked. check.wav plays. For the container: docker compose ps shows running and the log has no error.

Common mistakes#

Each row comes from the Piper docs or source, or a real issue in the Piper tracker (state as read in November 2026). The last row is about AI assistants.

MistakeWhy it happensDo this instead
Following a 2023 tutorial and the old rhasspy/piper repoThat repository was archived in October 2025 and says development moved; the current package is GPL-3.0, not MITUse OHF-Voice/piper1-gpl and pip install piper-tts as in this guide
Running pip install piper-tts system-wideUbuntu 24.04 answers externally-managed-environment (issue #318)Use a virtual environment (Step 1)
Starting the HTTP server with defaultsThe source binds 0.0.0.0, has no login and offers /downloadAdd --host 127.0.0.1; add a password at a proxy for remote use
Starting Piper from the wrong folder--data-dir defaults to the current folder, so the voice is not found: Unable to find voicePass --data-dir with the full path of the voices folder
Asking the server for a voice that is not downloadedIt does not fail; it logs "Voice not found ... Using default voice" and speaks with the default oneDownload the voice first and check the log
Using the default voice in a productThe Lessac voice's licence excludes commercial voice-synthesis use; 17 of 156 voice cards say non-commercial (issues #314, #333, #340 are open questions)Read each voice's MODEL_CARD before you ship
Believing "local" means "no network at all"ONNX Runtime 1.29 and newer telemetry is on by default in official builds (wyoming-piper issue #64)Set ORT_DISABLE_TELEMETRY=1
Windows with Smart App Control onIt blocks the unsigned espeakbridge.pyd (issue #323, open since October 2026; the reporter later got audio working)Check the issue for the current state, or turn the setting off if your policy allows
An AI assistant gives you OpenAI-style calls, such as /v1/audio/speech with an input fieldPiper's routes are /, /info, /voices, /all-voices, /download and /synthesize with a text field. Our assessment from the source, not a test of any assistantUse the fields in Step 4, or use Kokoro-FastAPI if you need an OpenAI-style address

Tip: Run python3 -m piper --help and python3 -m piper.http_server --help before you trust any command from a blog or a chatbot. They list every flag of the version you installed.

Tip: Listen to a voice sample before you download it. The samples page plays every voice, and a 114 MB high voice is a waste if medium sounds the same to you.

Tip: Pin the version (piper-tts[http]==1.8.0). There were eight releases between January and September 2026, and issue #254 shows one that changed behaviour for the C library.

Troubleshooting#

ProblemSolution
error: externally-managed-environmentMake a virtual environment (Step 1)
Unable to find voice: ... (use piper.download_voices)Download the voice, and pass --data-dir
Activate.ps1 is blocked on WindowsSet-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser (Python docs)
Speech is slow on a PiUse a low or x_low voice (Home Assistant docs)
No sound with ffplay and a BrokenPipeErrorWrite a file with -f and play it with a normal player (issue #149)
The new voice is not in Home AssistantReload the Wyoming integration for Piper

[ONNXRuntimeError] : 7 : INVALID_PROTOBUF - Protobuf parsing failed#

Issue #318 (open, October 2026): the voice file was corrupt after piper.download_voices; the reporter got working files by downloading the same voice from the Hugging Face page. Try python3 -m piper.download_voices <voice> --force-redownload, and download the two files by hand if it repeats.

Error processing file '/Users/runner/work/piper1-gpl/...phontab': No such file or directory#

Issue #272 (open, August 2026): on Apple Silicon the wheel looked for its data at the build machine's path (reported on 1.6.1). The reporter ran Piper in a Linux arm64 container (python:3.12-slim, pip install piper-tts flask, then piper.http_server). We did not confirm whether 1.8.0 is affected.

Known bugs (open on November 5, 2026)#

  • #323: Windows Smart App Control can block the unsigned espeakbridge.pyd.
  • #318: corrupt voice downloads and the externally-managed message.
  • #272: macOS arm64 data path (reported on 1.6.1).
  • #185: the HTTP server uses the Flask development server.
  • #182: the package name piper clashes with an unrelated tool of the same name if both are installed system-wide.
  • #116 and #102: GPU use can be slower than CPU, and memory can keep growing on a GPU.

Updates and backups#

Update. Piper has no auto-update. Read the release notes first (they list changes), then change the pinned version:

Run in terminalbash
python3 -m pip install --upgrade "piper-tts[http]==<new-version>"
Run in terminalpowershell
python -m pip install --upgrade "piper-tts[http]==<new-version>"

For the container, change the tag on the image: line, then docker compose pull && docker compose up -d.

Back up what you cannot download again: voices you trained or got elsewhere, and your Caddyfile. The Hugging Face voices can be downloaded again. On Linux and Mac:

Run in terminalbash
mkdir -p ~/piper-tts/backups
tar -czf ~/piper-tts/backups/piper-voices-$(date +%F).tar.gz -C ~/piper-tts voices
Codepowershell
New-Item -ItemType Directory -Force "$HOME\piper-tts\backups" | Out-Null
Compress-Archive -Path "$HOME\piper-tts\voices" -DestinationPath "$HOME\piper-tts\backups\piper-voices-$(Get-Date -Format yyyy-MM-dd).zip"

Run it at 03:00 with crontab -e on Linux and Mac (0 3 * * * tar -czf ~/piper-tts/backups/piper-voices-$(date +\%F).tar.gz -C ~/piper-tts voices), or with Windows Task Scheduler. For the container, back up ~/docker_volumes/piper/data the same way.

Restore test. Unpack into a new empty folder, never over the live one, and speak with the restored voice:

Run in terminalbash
mkdir -p ~/restore-test && tar -xzf ~/piper-tts/backups/piper-voices-<date>.tar.gz -C ~/restore-test
python3 -m piper -m en_US-lessac-medium --data-dir ~/restore-test/voices -f restore.wav -- 'Restore works.'

Performance and resources#

  • Speed on a Pi: Home Assistant's docs say a Raspberry Pi with medium voices makes about 1.6 seconds of speech in one second. We took no timings ourselves.
  • Quality ladder: x_low and low are 16 kHz and faster; medium and high are 22.05 kHz. Medium is the usual compromise.
  • Memory: Piper does not publish a RAM figure. Check it yourself: docker stats for the container, or Task Manager, Activity Monitor or top for the Python process.
  • GPU: --cuda needs the onnxruntime-gpu package (CLI docs). Issue #116 reports a GPU run slower than CPU, so measure before you buy hardware for it.
  • Repeated use: use the HTTP server or the Python API; the command line reloads the model for each call.
  • Python API: load the voice once with PiperVoice.load(...), then call voice.synthesize_wav(...) as often as you like (API docs).

FAQ#

Is Piper still maintained? Yes, by the Open Home Foundation, but thinly. There were releases through 2026, the newest in September, and commits in November. The README asks for new maintainers, and many issues are unanswered. Pin a version and expect slow fixes.

Why is it GPL now? The new repository is licensed GPL-3.0; the old rhasspy/piper was MIT. The docs give no reason, but the README says Piper embeds espeak-ng. If you only use Piper as a tool, the licence changes little for you. If you build it into software you distribute, read the GPL.

Does it work offline? After the voice download, speaking needs no network. Set ORT_DISABLE_TELEMETRY=1 so the engine underneath does not try to call out, and test on your own network before you rely on it.

Can I use Piper voices commercially? Piper's own docs say it is meant for personal use and research. Each voice has its own licence, and some are non-commercial. See "Voices and licences".

How is Piper different from Kokoro or Chatterbox? Piper is the small, quick one for a Pi: a 63 MB voice, a 34 MB install, no GPU needed. Kokoro-FastAPI is a bigger model behind an OpenAI-style API. Chatterbox can clone a voice but needs a stronger machine.

Sources#

Checked against the official docs on 2026-11-05.