Multiplexing audio between containers

Hello,

I have two containers running, and which ever is the first to play audio, holds audio, and if I were to use play for instance, I receive the following error:

ALSA lib pcm_dmix.c:1052:(snd_pcm_dmix_open) unable to open slave
Arithmetic exception (core dumped)

I have created the following within the root resin-OS /etc/asound.conf rebooted and not had luck sharing/multiplexing audio sent by multiple containers:

  pcm.dsp {    
      type plug    
      slave.pcm "dmix"
  }

Does anyone have any ideas or input?

Thanks,

Matt

1 Like

Hi @mbrownnyc, what version of resinOS are you running two containers? Is it a version managed on resin.io, or the open source, unmanaged version? How are you starting the two containers? (is it possible to check out what code are you running on the device?)

Thanks for your reply:

root@hassio:~# cat /etc/*release
ID="resin-os"
NAME="Resin OS"
VERSION="2.3.0+rev1"
VERSION_ID="2.0.9"
PRETTY_NAME="Resin OS 2.3.0+rev1"
RESIN_BOARD_REV="0c6de83"
SLUG="raspberrypi3"
MACHINE="raspberrypi3"
VARIANT="Production"
VARIANT_ID="prod"

This is the home-assistant image (hass.io) which I assume is an unmanaged version.

The containers are started automatically upon boot.

As I didnā€™t create the containers or the resinOS image, Iā€™m a bit at a loss on specific details.

I have no issues with ALSA and sound access within the containers; I would figure it would be fairly simple to allow multiplexing of audio to both containers. This is my first dive into docker though, but if I understand correctly, containers are not VMs, they are somewhat virtualized filesystems only (?). So Iā€™m not sure why the above /etc/asound.conf dmix implementation doesnā€™t work.

Any assistance or direction is appreciated.

Thanks!

I see, thatā€™s useful info. Will have to check how the home-assistant image is createdā€¦
Probably modifying the underlying resinOS image is not the completely correct way to fix this, but definitely good for debugging.

Iā€™ve seen that the ArchLinux wiki (which has a lot of great Linux knowledge, regardless of distro) as some info on simultaneous playback: https://wiki.archlinux.org/index.php/Advanced_Linux_Sound_Architecture/Troubleshooting#Simultaneous_playback_problems and also linking to upstream maybe http://www.alsa-project.org/main/index.php/Asoundrc#dmix

I would guess that the above change you mentioned is not totally correct (or rather, not all the changes that are needed).

Definitely need some more investigation.

Thanks for your reply. The resinOS image they use does not have apt-get or alsatools installed. The containers that can access sound are Alpine and Debian. Again, Iā€™m not sure who goes whereā€¦ as inā€¦ Iā€™ve read that docker containers are ā€œnot VMs!ā€ But, if they were VMs the responsibility for sharing a hardware resource is on the host OS, in this case (well not this case because containers are not VMs) that responsibility would be on resinOS.

However, alsa or alsa-util are not installed in resinOS:

  root@hassio:~# find / -iname *alsa* |  grep -v docker
  /lib/modules/4.4.50/kernel/drivers/media/usb/cx231xx/cx231xx-alsa.ko
  /lib/modules/4.4.50/kernel/drivers/media/usb/em28xx/em28xx-alsa.ko
  /lib/modules/4.4.50/kernel/drivers/media/usb/tm6000/tm6000-alsa.ko
  /lib/udev/rules.d/60-persistent-alsa.rules
  /etc/modprobe.d/alsa-blacklist.conf

Iā€™ve added the following to /etc/asound.conf on both containers:

pcm.dmixer {
    type dmix
    ipc_key 1024
    ipc_key_add_uid 0
    ipc_perm 0660
}
pcm.dsp {
    type plug
    slave.pcm "dmix"
}

Iā€™ve also installed and switched to using alsamixer on mopidy.

I am able to use aplay to play a wav from the same container where mopidy is playing musicā€¦ to me this proves the issue isnā€™t the process locking ALSA, but the actual container locking ALSA. Although, inspecting files below /dev/snd/ shows a PID locking audio that isnā€™t listed in ps within the resinOS, but when killed stops Mopidy from playing (of course).

How is the hardware virtualized/multiplexed (for lack of better terms) between docker containers?

Would /resin-data/addons/core/snips/asoundrc be used by anything?

Thanks,

Matt

I was advised in #alsa on freenode to look at using the ipc switch to share memory between containers.

Is it possible to provide guidance on using that with /dev/snd/?

Thanks,

Matt

Is there already a solution for this interesting problem ?

I am referring to the generic problem where we have multiple containers that want to share the same audio device (e.g. speaker , microphone).

Hello, we donā€™t have any experience with this, but an idea is to maybe set up something like pulse audio in one container and then have all other containers connect to that.

Hi,

I know this is an old post and Iā€™m not a Balena user, but I ran into this exact issue and got it working so wanted to reply, since this was my first Google result.

I am running ALSA in two containers, and want to be able to output to the same hardware device, from both containers, at the same time. There is no ALSA or PulseAudio running on the host OS, and it wouldā€™ve been hard to set that up.

@mbrownnyc almost arrived at the full solution and I wouldnā€™t have got there without this thread.

  • In my Docker compose file I add /dev/snd as a device in both containers.

  • The important missing key not described here yet: both containers need to be run with ipc=host! If youā€™re using Docker compose, add ipc: host to both containers.

  • Then, both containers need an asoundrc file that contains the following PCM definition:

    pcm.mixer {
    	type plug
    	slave.pcm {
    		type dmix
    		ipc_key 1245
    		ipc_key_add_uid 0
    		ipc_perm 0666
    		slave.pcm "hw:youraudiocard"
    	}
    }
    

The important part here is the dmix PCM definition, both containers need a dmix PCM device defined with the SAME ipc_key and with ipc_key_add_uid 0. This last flag disables a feature that would automatically add the uid to the IPC key so there can be no conflicts, but a conflict is exactly what we want so that these PCM devices end up to be the same.

In my case I chose ipc_perm 0666 because one of my two containers running ALSA runs under root while the other runs under user 1000. The slave.pcm can probably be anything but was the actual hardware audio card of the embedded device we are developing in my case.

I wrapped the whole thing in a plug for easier interfacing, thatā€™s optional.

You can now use the ā€˜mixerā€™ PCM device to output from both containers, at the same time, to the same device.

Kind regards,
Ernest