Route Home Assistant Assist TTS responses to specific Snapcast clients — with low latency, per-room targeting, and zero firmware changes when routing changes.
Status: Active development — M0 verification in progress. Not yet production-ready.
Home Assistant's media_player.play_media does not preserve streaming TTS behavior in HAOS 2026.5.x. When Piper streams TTS output incrementally, the standard path waits for the full audio to complete before playback begins, adding noticeable lag. This project routes TTS directly from ESPHome's on_intent_progress event into Snapcast clients — bypassing media_player.play_media entirely — so the first audio byte plays before the last is generated.
Additional pain points this solves:
- Music Assistant announcement routing requires per-satellite configuration that breaks when speakers move.
- ESPHome vanilla TTS plays back on the satellite itself, not on whole-room speakers.
- Changing which room a voice command targets normally requires firmware reflashes.
┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────────────┐
│ ESPHome Satellite │ │ HA Custom Integ. │ │ HAOS Add-on │
│ (Atom Echo etc.) │ │ ctrlable_snapcast_ │ │ ctrlable-snapcast- │
│ │ │ tts │ │ streamer │
│ on_intent_progress │──┬──▶│ │ │ │
│ fires homeassistant│ │ │ Service: │ │ HTTP endpoint: │
│ .service call with │ │ │ .announce │─────▶│ POST /announce │
│ url + satellite_id │ │ │ Owns mapping: │ │ │
│ + wake_word │ │ │ (sat_id, wake) → │ │ Snapcast JSON-RPC │
│ │ │ │ target snapclient │ │ topology mgmt │
│ on_tts_end (fallbk)│──┘ │ + UI config flow │ │ │
└─────────────────────┘ └──────────────────────┘ │ Per-client lock │
│ Stream PCM/MP3 to │
│ Snapcast TCP port │
│ Move client to │
│ announce group, │
│ play, restore │
└─────────┬───────────┘
│
┌─────────▼───────────┐
│ Snapcast Server │
│ (existing LXC) │
│ Per-client streams │
│ + announce groups │
└─────────────────────┘
Three components, one URL to install both:
| Component | What it does |
|---|---|
HAOS Add-on (ctrlable-snapcast-streamer) |
Manages Snapcast topology, streams audio, exposes HTTP API + ingress UI |
HA Integration (ctrlable_snapcast_tts) |
Owns satellite→snapclient mapping, exposes announce service, config UI |
| ESPHome YAML Package | Reference satellite config (3 substitution lines per device) |
- In Home Assistant: Settings → Add-ons → Add-on Store → ⋮ → Repositories
- Paste:
https://github.com/Ctrlable/ha-ctrlable-snapcast-tts - Find Ctrlable Snapcast TTS Streamer in the store and install it.
- Configure the add-on with your Snapcast server address, then start it.
- Copy the bearer token from the add-on's ingress UI.
- In HACS: ⋮ → Custom repositories
- Paste:
https://github.com/Ctrlable/ha-ctrlable-snapcast-tts, category: Integration - Install Ctrlable Snapcast TTS
- Restart Home Assistant
- Go to Settings → Devices & Services → Add Integration → search "Ctrlable Snapcast TTS"
- Enter the add-on URL (
http://localhost:8765) and bearer token from step above.
Both use the same repository URL. One URL, two installation flows.
See docs/installation.md for full setup instructions including:
- Snapcast server prerequisites
- SSH access setup (for file-edit mode)
- Satellite ESPHome YAML
- Mapping configuration
Create a per-satellite YAML (3 lines of substitutions):
# living_room_satellite.yaml
substitutions:
name: ctrlable-living-room
friendly_name: "Ctrlable Living Room"
micro_wake_word_model: okay_nabu
packages:
ctrlable_base: !include packages/ctrlable_atom_echo_base.yamlThe name field becomes the satellite_id used in routing mappings. See esphome/packages/ for the base package and examples.
| Feature | This project | Music Assistant | Vanilla ESPHome TTS |
|---|---|---|---|
| Low-latency streaming TTS | Yes (bypasses play_media) | No (buffers) | No (buffers) |
| Route to Snapcast clients | Yes | No | No |
| Change routing without reflash | Yes (UI mapping) | N/A | No |
| Multi-room simultaneous | Yes (M4) | Via MA rooms | No |
| Works without Music Assistant | Yes | Required | Yes |
| Component | Minimum version |
|---|---|
| Home Assistant OS | 2026.5.1 |
| Home Assistant | 2026.5.0 |
| Snapcast server | 0.27+ |
| ESPHome | 2025.5.0 |
| ESP32 board | M5Stack Atom Echo, any compatible |
Apache 2.0 — see LICENSE.
Built by Ctrlable — smart building automation for hospitality and commercial spaces.