Play audio file from Home Assistant Container

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.

Ideas?

1 Like

Maybe

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. :yum:


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 }}'

Now I can play sounds by calling a service:

service: shell_command.play_sound
data:
  name: ding-dong
1 Like

An other way, with Rhasspy, an open source, fully offline set of voice assistant services for many human languages, if this should help you :

Container

docker run -p 12101:12101 \
      -v "$HOME/.config/rhasspy/profiles:/profiles" \
      -v "/etc/localtime:/etc/localtime:ro" \
      -d --restart unless-stopped \
      -v /var/lib/docker/volumes/Media/_data:/profiles/Media \
      --device /dev/snd:/dev/snd \
      --name rhasspy \
      rhasspy/rhasspy \
      --user-profiles /profiles \
      --profile fr

Configuration

rest_command:
  rhasspy_play:
    url: 'http://192.168.1.6:12101/api/play-wav'
    method: 'POST'
    payload: '{{ payload }}'

Automation

- id: '1636909817124'
  alias: Il est l or
  description: ''       
  trigger:       
  - platform: event
    event_type: rhasspy_GetTimePlus
  condition: []                
  action:      
  - service: rest_command.rhasspy_play
    data:                              
      payload: /profiles/Media/monsignor.wav
  mode: single
1 Like

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:

/api/play-wav

  • POST to play WAV data
  • Make sure to set Content-Type to audio/wav

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 \

Hope this help !

1 Like

thanks so much for this!