I am using several raspis that basically only run snapclient at the moment to stream music around the house. Now, I would like to attach a mic to them and turn them into voice satellites. This works well as long as snapclient is not streaming anything. But as soon as snapclient is playing the speakers are busy, resulting the satellite to complain:
aplay: main:830: audio open error: Device or resource busy
I am thankful for any hints how to mute snapclient once the wakeword is detected (it gets detected and spoken commands are run fine) and unmute it after the conversation with HA is done.
You need to stop SnapCast completely or pipe your sound into the SnapCast service.
SnapCast require a timing on the sound device and that seems impossible to do with a shared device, which is why SnapCast makes an exclusive reservation of the sound device.
Thanks a lot for the hints. I guess stopping and restarting snapcast would be fine - I just have no clue how I could do that based on the detected wakeword… Well, I could actually do it using HA - as it is controlling snapcast - but there is no event like “Wakeword detected on Kitchen-Satellite”, right? That would make it all very easy…
I guess for my skillset, I need more detailed help / links / direction to get this done.
You need to stop the service from running on the satellite. Not just stop it in HA.
You would probably have to set up something like a SSH command to do it.
And I think there is a location on the wakeword, but it might be called something different, like client, id, satellite or something like that.
Actually it would be enough to stop snapcast from within HA. When I mute the satellites in HA, assist works just fine.
But I cannot find any events or entities in HA that would give me the state of wake word detection on clients. Any more hints?
I have not set it up yet with the new protocols, so it is still Rhasspy here, but satellite id is part of the packet pipeline and the HA assist is a new built based on Rhasspy, so I can not imagine Mike not having made satellite id part of it.
It might be an event and it might be something you need to catch in the pipeline.
Most likely your snapclient uses ALSA to play audio, which allows only one program to use the audio device at the same time. That’s why homeassistant-satellite cannot play sounds. Trying to stop/start snapclient is maybe doable, but it’s certainly error prone and messy as a solution. It’s much cleaner to configure your system so that multiple programs can play audio at the same time.
This can be achieved by installing pulseaudio on your pis (or even better pipewire which is a more recent fully compatible variant). Recent versions of raspberry pi desktop actually do this by default, while on raspberry OS lite you need to install it yourself. Note that pulseaudio/pipewire needs to run as a user service, so you need to configure a user session to start automatically on boot (on the OS lite you can achieve this with loginctl enable-linger pi).
You then need to configure snapclient and homeassistant-satellite to use pulseaudio, both support it. This will allow homeassistant-satellite to play audio even when snapclient is working.
In fact, when used with pulseaudio, homeassistant-satellite is clever enough to lower the volume of all other programs while an assist pipeline is in progress, so that your music does not interfere. Just start it with --ducking=0.2.
PulseAudio and Pipewire is worse than Alsa, because they are meant to be run in usermode and that makes them tricky and very error prone on a headless system.
PulseAudio also have the issue with timing on a shared device, so snapcast client will complain and fail on that one too.
Great discussion. I guess trying to switch to pulseaudio would be my 2nd option (esp. seeing my relevant skill set…). So I would actually try the messy ALSA solution first where I simply want to stop the satellite snapclient via an automation on HA once a wake word is detected on that satellite.
Could you give me any pointers how to trigger an automation, when a wake word is being detected? I cannot find anything and tbh I don’t really understand the concepts of the pipeline and how I access or listen to it.
Running a user service on a headless system is as easy as loginctl enable-linger. Ok it’s a bit harder, but ALSA’s limitation to a single program is a huge deal breaker.
If you want to try this path, don’t do it via an automation, it will be close to impossible to time it correctly so that snapclient stops before the satellite tries to play a sound and properly restarts afterwards.
Your best bet IMHO is to use the --snd-command option of homeassistant-satellite, it receives a script that is executed every time the satellite wants to play a sound. Within your script you have 2 options:
either stop snapclient, play the sound and restart it
or send the audio to snapserver (the method depends on where snapserver is located), so that it is played the same way as your music.