I’m trying to figure out a way to play an audio file from an automation in Home Assistant Container. I have come up with several approached but they all were dead ends so far:
Mount /dev/snd into the container and use aplay as a shell command
→ The Home Assistant image doesn’t have aplay or any other ALSA player command that I’ve tried.
Find an integration that would install such an audio player
→ I haven’t found any such integration.
Rhasspy, which I’m using, has an HTTP API endpoint /api/play-wav that can play arbitrary files
→ It requires to POST the file contents as the request body and I haven’t found out how to put a file as the request body of a REST command in Home Assistant.
Rhasspy can also play WAV via MQTT
→ As with the REST command, I haven’t found a way to put a file’s contents into an MQTT message.
Exec a command in another docker container
→ The Home Assistant container is --privileged, so in theory it should be able to access other docker containers, but the Home Assistant image does not contain the docker CLI.
I found VLC to be a bit overkill just to play sounds, but I’m not sure the solution I went with is much better.
What didn’t work:
I mounted /dev/snd and /etc/asound.conf into the container and set --ipc=host. This is how the Rhasspy container plays sound. I also copied aplay from a 32-bit Alpine container (which is the base for Home Assistant).
I got underrun!!! (at least [...] ms long) errors and it wouldn’t play the first half second or so of the sound.
I’m guessing this is because the Home Assistant container is 32 bit (linux/arm/v8) and the ALSA interface might not be compatible with the 64 bit kernel of the host system.
So the solution that did work in the end is this:
I created two scripts on the host: onreceive.sh:
#!/bin/bash
read INCOMING
aplay "${INCOMING}.wav"
run.sh:
#!/bin/bash
cd `dirname "$0"`
socat -u tcp-listen:7777,fork,reuseaddr,bind=127.0.0.1 system:./onreceive.sh
On system start I run run.sh by calling it from rc.local.
Then in Home Assistant’s config directory I created a file play_sound.sh:
#!/bin/bash
echo "$1" | nc localhost 7777
And added to configuration.yaml:
shell_command:
play_sound: '/config/play_sound.sh {{ name }}'
Oh, wow, that would have been the easiest way because I’m already using Rhasspy, but I didn’t try it out because the documentation says that I need to POST the contents of the WAV file:
Well, the documentation isn’t really clear… I struggle with it !
You can POST, as I proposed, but you mustn’t set Content-Type to audio/wav
The only thing you have to do is to post a string starting with “/”, then the wav file from that path will be played (so the file should be on the filesystem of Rhasspy, this is the reason why i mount this in Rhasspy’s container: -v /var/lib/docker/volumes/Media/_data:/profiles/Media \