Whole-home audio for Home Assistant, without the stutter. Play from your phone, your PC or any Bluetooth device, send it to any speakers in the house from one dashboard card, and let Home Assistant talk over the top of it — ducked, not interrupted.
Under the hood the audio path is PipeWire's own realtime graph, driven by a small Rust daemon. Mixing and re-clocking several streams for several rooms is a realtime-scheduling problem: on a Raspberry Pi 4 a Python engine doing that job stuttered audibly and took seconds to start a stream, while PipeWire's graph is a C daemon built for precisely it. This sits under a music library rather than in place of one — see Works with Music Assistant.
- Play in from an iPhone, Mac or PC over AirPlay · anyone's Spotify app, as a Spotify Connect device that plays from their account · any Bluetooth device, via a small ESP32 or Raspberry Pi bridge box · a Linux PC, via a receiver agent · the YouTube Music app's own Cast button, via a second add-on in this repository.
- Play out to AirPlay-2 receivers, AV receivers and HomePods · ESPHome speakers such as Home Assistant Voice PE · any Linux PC running the agent.
- Ordinary Home Assistant entities: a
media_playerper output plus one per group, with volume, and routing you can drive from automations and scripts — not just from the card. - Announcements that duck, per room: TTS plays over the music at full clarity, the music dips and comes back, and a PC's own audio (a browser, a game) dips with it.
- Discovery you stay in charge of. Every compatible device on the LAN is offered, including the neighbours' AirPlay speakers; nothing is routable, gets an entity, or is ever sent audio until you add it — each with a test-tone button so you can tell which speaker is which.
The add-on's own web UI, in Home Assistant's sidebar — and the device it adds to Home Assistant itself. Click any shot for full size.
Music Assistant answers what to play; this answers where it goes and when it has to be exact. Point MA at this add-on's AirPlay input and it becomes one more AirPlay player in its list: MA keeps the library and the queue, and the audio it sends is routed, grouped and ducked here like anything else that streams in.
| Music Assistant | this project | |
|---|---|---|
| Knows about | libraries, playlists, web radio, providers, queues, artwork | PipeWire nodes, AirPlay/RTP/sendspin transports, clocks |
| Multiroom | in sync within one ecosystem; across ecosystems, unsynced | in sync across protocols |
| Routing | a queue to its player | any input to any set of outputs, live |
| Latency | not a design driver | the design driver |
Playlists, queues, gapless and library browsing are deliberately not built here — that is MA's job. Setup and troubleshooting: docs/music_assistant_compatibility.md.
This is the piece that moves the audio. Add the repository, then install PipeWire Audio Router from the store and start it. There are no options to fill in: outputs and sources are added at runtime in its own web UI.
This is what turns the add-on's outputs into media_player entities and brings
the routing card to your dashboard. Download it with HACS:
If HACS does not open the repository, add it by hand first — HACS → ⋮ →
Custom repositories → this repo's URL, category Integration. Without
HACS, copy custom_components/pipewire_audio_router/
into your config's custom_components/.
Then restart Home Assistant and go to Settings → Devices & Services → Add
integration → PipeWire Audio Router, and give it the add-on's host and port
(default 8099). Setup calls the add-on to check it is reachable, so a typo
fails loudly instead of silently.
Turns any phone, tablet or laptop that can pair over Bluetooth into a source.
Flash firmware/bt-bridge/ onto an
original-ESP32 board (not S2/S3/C3/C6 — that README explains why), or use
firmware/pi-bridge/ on a Raspberry Pi Zero 2 W
for higher-quality codecs.
Turns any Linux machine running PipeWire — your desk PC, a media box, a Pi in
the workshop — into an output the router can stream to. Its master volume and
mute become Home Assistant's, and its own audio (a browser, a game) dips while
an announcement plays. That takes a small helper pwrouter-agent.
Get the binary for that machine's architecture (uname -m) either from the
add-on — Outputs → Setup Linux/PipeWire host or from this repository's
Releases
page. Then, on that machine:
chmod +x pwrouter-agent-*
# copies it to ~/.local/bin, writes the systemd user unit
./pwrouter-agent-* autostart enable
systemctl --user start pwrouter-agentPuts the house in the Cast menu of the YouTube Music app. It is a second add-on in the same repository, so it is already in your store from step 1 — install it, start it, open its panel, and it walks you through the two things it needs: one button to create its audio route on the router, and to setup your account.
With the integration installed it is also an ordinary media_player
(media_player.youtube_music): pause and skip from Home Assistant, see the queue,
and start one of the recently played playlists without a phone.
It plays from your signed-in account and leans on unofficial protocols and
on yt-dlp keeping pace with YouTube, so treat it as the least stable thing
here. Details in ytmusic_receiver/, reasoning and
every measured gotcha in
docs/ytmusic-receiver.md.
What it buys you: the house in the app's own Cast menu.
In daily use.
Last tested against Home Assistant 2026.8.1.
Requires a minimum of 2026.7.0 (hacs.json).
- docs/system-architecture.md — how the pieces fit together, with diagrams.
- docs/decisions.md — why it's built this way: real investigations with concrete findings (RAOP quirks, PipeWire's actual volume/module-loading capabilities, ESP32 hardware constraints, and more), not preferences.
- docs/music_assistant_compatibility.md — pointing Music Assistant at this add-on, who owns what, and what to do when it does not connect.
- docs/api-reference.md — the bridge daemon's REST/WebSocket API.
- docs/addon_maintenance.md — keeping up with Home Assistant: which HA version the tests run against and how to bump it, what past bumps broke, and the commands for testing and deploying against the real instance.
- docs/ytmusic-receiver.md — the YouTube Music Cast receiver.
- docs/branding/ — the icon and logo, and how to re-render them.
- tests/ — the runnable scripts backing those write-ups; nothing
here is "verified" without one. All of it — the Rust daemon
(rustfmt/clippy/tests), the web UI (svelte-check/build), the HA integration
(pytest), and the add-on end-to-end scripts — runs in CI on every push to
mainand every PR (.github/workflows/ci.yml). Av*tag also publishes the add-on images to GHCR (build-addon.yml) and a GitHub release carrying the receiver-agent binaries for x86-64 and aarch64 (release.yml).
Phones, PCs and a Bluetooth bridge box stream in; a Rust daemon routes and
mixes them through a native PipeWire graph and out to AirPlay-2 receivers,
ESPHome speakers and PCs; Home Assistant sees ordinary media_player entities
at the far end.
Independently installable pieces, plus supporting dev tooling. Each has its own README with install/config/usage details.
| Component | What | README |
|---|---|---|
| Bridge daemon add-on | Rust + PipeWire/WirePlumber, packaged as a real HA add-on (repository.yaml at repo root) |
pipewire_audio_router/ |
| Home Assistant integration | media_player entities backed by the add-on's REST API, plus the custom:pipewire-router-card dashboard card |
custom_components/pipewire_audio_router/ |
| Bluetooth bridge firmware | ESP32 + ESPHome, turns any Bluetooth device into a whole-home-audio source | firmware/bt-bridge/ |
| Raspberry Pi bridge | the same job on a Pi Zero 2 W, for higher-quality Bluetooth codecs | firmware/pi-bridge/ |
| pw-sink receiver agent | makes a Linux PC an output the router can stream to, and duck | pipewire_audio_router/pwrouter-agent/ |
| YouTube Music Cast receiver | the YouTube Music app's Cast button, as a source — an add-on in this repo's store, with its own setup page | ytmusic_receiver/ |
pipewire_audio_router/ the HA add-on: bridge daemon (Rust) + Dockerfile + config.yaml
custom_components/pipewire_audio_router/ HA integration (Python)
firmware/bt-bridge/ ESPHome firmware for the Bluetooth bridge box
firmware/pi-bridge/ Raspberry Pi Bluetooth bridge
firmware/pi-ytmusic/ Raspberry Pi YouTube Music receiver (canonical receiver app)
ytmusic_receiver/ the same receiver as a local HA add-on
container/ throwaway bare-PipeWire dev sandbox — not the real add-on
docs/ architecture, decisions, API reference, branding
tests/ verification scripts
scripts/ dev tooling (e.g. arm64 cross-build, branding render)
- trudenboy/sendspin-bt-bridge — the mirror image of this repo's Bluetooth bridges: instead of making a Bluetooth device a source for the house, it turns ordinary Bluetooth speakers into sendspin players (Python, runs as an HA add-on, Docker or on a Pi). Useful if the speaker you want to reach only speaks A2DP.









