WIP: Self-Hosting voice services for Home Assistant (TTS, ASR, Wake Word)

TL;DR Crane Wyoming
HA App Crane Wyoming HA App

I use Home Assistant, and for text-to-speech (TTS) I’ve been running
Piper through
Wyoming Piper.

Piper is a fast, local neural TTS engine originally built for the Rhasspy
project and now maintained by the Open Home Foundation. It’s designed to run
entirely offline, even on modest hardware like a Raspberry Pi.

Wyoming is the open protocol Home Assistant uses to talk to voice
components like TTS, speech-to-text, wake word, voice activity detection (VAD,
which decides when someone has started or stopped speaking) over the
network, so any service that speaks Wyoming can be plugged in as a
satellite. Wyoming Piper just wraps Piper so it can be served this way.

Both work well and I have no complaints about reliability. My issue is
quality: the German voices aren’t great. Piper depends on open datasets for
training, and good open German speech data is scarce, so the German models
lag behind the English ones. I also run TTS locally on my desktop for event
reminders, so voice quality matters to me beyond just Home Assistant.

Looking for something better

I wanted better output quality, so I started looking at alternatives and
found Crane, a Rust inference
framework built on Candle.

An “inference model” is a trained neural network used to actually produce
output like text, speech, an image, rather than to learn from data (that’s
“training”). An “inference framework” is the software that loads such a
model and runs it efficiently: managing GPU/CPU memory, batching requests,
and exposing an API around it. Piper and Crane are both inference
frameworks.

Crane already had
Qwen3-TTS support, and its
Serena voice’s German output sounded noticeably better. I also wanted to try
Voxtral-4B-TTS-2603,
Mistral’s open-weight TTS model, so I added support for it. Voxtral TTS
produces expressive, natural-sounding speech across 9 languages including
German, with low time-to-first-audio and streaming support. It is a good fit
for a voice assistant that needs to start speaking quickly.

Adding Wyoming support

Once Voxtral was working in Crane, I built
crane-wyoming, a standalone
Wyoming protocol server, so Home Assistant could use these models as its
TTS service. To make that possible, I added the Tts trait and the
surrounding TTS abstractions to Crane, since there was no stable interface
for driving a TTS model on its own, separate from Crane’s full inference
engine (tokenizer/LLM/VLM machinery). Those abstractions have since been
merged upstream:
lucasjinreal/Crane#44.

crane-wyoming depends on Crane only for that Tts trait and the concrete
model types it needs to construct, not Crane’s engine crate. So it carries
its own small TTS-only model runtime (one dedicated worker thread per loaded
model) and its own on-disk response cache.

The project grew into a small Cargo workspace. Besides the Wyoming server
itself, it now has cw-say, a standalone CLI client for scripting. It also
has sd_crane_wyoming, a speech-dispatcher output module. That lets
screen readers and other accessibility tools use the same running server on
the desktop, not just Home Assistant.

What’s next

  • Speech-to-text. I’m looking into Qwen3-ASR and Voxtral-Mini-4B-Realtime-2602 for automatic speech recognition (ASR).
  • VAD. Crane already has a Silero VAD implementation adding it to STT is easy.
  • Wake word. Once VAD is in place, add
    Open Wake Word support.

With all of that implemented, you’d have a complete self-hosted Wyoming voice
stack with no cloud dependency.

Current limitations

The catch is that you need a GPU to run it well.

If you only need TTS for occasional things like reminders, short
announcements, running it on CPU with caching is enough, since repeated
phrases just get served from cache instead of resynthesized.

All of this is for advanced users and hackers right now. There’s no
polished packaging yet. Systemd units exist for both system and user
services, including socket activation, but you still have to build from
source. However testing and feedback are welcome.

I’ve added Automatic Speech Recognition (ASR) support, aka Speech-To-Text to crane-wyoming. I’m working on Voice Activity Detection (VAD) now. Once that is done I will look into creating a Container so you can run it as a HA App.

I’ve added voice-activity-detection (VAD) for automatic speech recongnition (ASR) also known as speech to text. I will add support for a VAD service too. It has been added to the wyoming protocol recently.

So for all the people who want to try it and give feedback, I created and HA App now.