Add Home Assistant audio output sink selector#333
Conversation
|
Finding a correct sink could be a problem for new to linux users. |
Next PR will include a “test the sink” feature to play a sound over the selected sink to confirm its identity. |
|
good idea! |
|
I am following up on this PR and wondering if there is a maintainer around that could approve the workflow? I have additional improvements to submit and I did not want to bloat this one with more changes. |
|
I think this is a great MR. But with #350 we should have all input and output devices selectable in HA. We also have some merge conflicts in this MR. |
Summary
This PR adds a Home Assistant device-page configuration select entity named Audio Output Sink for Linux Voice Assistant.
The new select exposes available PulseAudio/PipeWire output sinks discovered from the host/container audio environment, allowing users to choose which output sink the satellite should use directly from Home Assistant instead of manually editing
AUDIO_OUTPUT_DEVICEevery time.This is intended to be generic audio-output selection support. It is not Sonos-specific. RAOP/Sonos sinks work because they are exposed as normal PulseAudio/PipeWire sinks.
Motivation
Linux Voice Assistant already supports selecting an output device at startup through
AUDIO_OUTPUT_DEVICE, but there was no Home Assistant UI control for choosing or changing that output once the satellite was running.This matters for systems where the available output sinks are exposed through PulseAudio/PipeWire, including local speakers, USB audio devices, Bluetooth sinks once connected by the OS, and RAOP/AirPlay sinks.
The goal is to make output selection visible and configurable from the Home Assistant device page while preserving existing startup configuration behavior.
Behavior
This PR supports two modes:
1. Environment override mode
If
AUDIO_OUTPUT_DEVICEis set, it remains the hard startup override.Example:
AUDIO_OUTPUT_DEVICE="pulse/raop_sink.Sonos-542A1BFB1574.local.192.168.86.226.7000"
On startup, the configured output device is still passed to mpv, but the underlying raw sink is also copied into
ServerState.audio_output_sink.That keeps the Home Assistant select state honest: the UI shows the actual active sink instead of incorrectly showing
default.2. UI-managed mode
If
AUDIO_OUTPUT_DEVICEis not set, the selected sink is loaded frompreferences.jsonasaudio_output_sink.When the user changes the Home Assistant select value:
defaultclears the persisted sink and returns mpv to automatic/default output.Implementation notes
linux_voice_assistant/audio_sinks.pyAdds helper functions for:
pactl list short sinksThe helper keeps mpv-specific
pulse/<sink>formatting at the mpv boundary. Internally, the selected sink is represented as the raw PulseAudio/PipeWire sink name orNone.linux_voice_assistant/entity.pyAdds
AudioOutputSinkEntity, an ESPHome-style select entity exposed to Home Assistant.The entity:
CONFIGmdi:speaker-wirelesslinux_voice_assistant/models.pyAdds:
Preferences.audio_output_sinkServerState.audio_output_sinkServerState.audio_output_sink_entityServerState.persist_audio_output_sink(...)The persisted preference is used only when
AUDIO_OUTPUT_DEVICEis not configured.linux_voice_assistant/satellite.pyCreates and registers the new Audio Output Sink select entity.
Adds runtime sink switching logic that updates both:
music_playertts_playerThe select entity is added only once and is updated with the current sink options/state.
linux_voice_assistant/mpv_player.pyAdds
MpvMediaPlayer.set_audio_device(...)so the satellite can change the player output device at runtime.linux_voice_assistant/player/libmpv.pyAdds
LibMpvPlayer.set_audio_device(...).The implementation stops current playback before changing the mpv
audio-deviceproperty. This is intentional because changing output sinks is a configuration action and should not try to preserve in-progress playback across devices.If no device is provided, mpv is returned to
auto.linux_voice_assistant/__main__.pyAdds startup reconciliation logic so the effective output device is chosen from:
AUDIO_OUTPUT_DEVICE, when providedpreferences.audio_output_sink, when no environment override existsThis preserves existing
AUDIO_OUTPUT_DEVICEbehavior while enabling UI-managed persistence.Manual testing performed
Tested locally with a Linux Voice Assistant satellite using PulseAudio/PipeWire sinks.
Validated:
AUDIO_OUTPUT_DEVICE.defaultand detected sinks.AUDIO_OUTPUT_DEVICEwas not set.AUDIO_OUTPUT_DEVICEoverride still took precedence when set.AUDIO_OUTPUT_DEVICEwas set.defaultcleared the persisted sink and returned mpv to automatic/default output.Files changed
linux_voice_assistant/audio_sinks.pylinux_voice_assistant/entity.pylinux_voice_assistant/models.pylinux_voice_assistant/satellite.pylinux_voice_assistant/mpv_player.pylinux_voice_assistant/player/libmpv.pylinux_voice_assistant/__main__.pyNotes
This PR intentionally keeps the feature scoped to output sink selection.
Bluetooth pairing/connection management is not included here. Bluetooth sinks can be selected if the host OS/PulseAudio/PipeWire layer has already exposed them as available sinks.