Pass USB audio card through to unprivileged LXC Container

Hi,

Ah, alright, that explains it. Thanks for clarifying.

Sorry, I should have made this more clear: You could run
Code:
aplay -v /usr/share/sounds/alsa/Front_Left.wav
on the host to find out which plugin it is using to play sounds.
@fweber

Thanks!

Host with working audio
Bash:
root@proxmox:~# aplay -v /usr/share/sounds/alsa/Front_Left.wav
Playing WAVE '/usr/share/sounds/alsa/Front_Left.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Plug PCM: Rate conversion PCM (44100, sformat=S16_LE)
Converter: libspeex (builtin)
Protocol version: 10002
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 17832
  period_size  : 1114
  period_time  : 23219
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1114
  period_event : 0
  start_threshold  : 17832
  stop_threshold   : 17832
  silence_threshold: 0
  silence_size : 0
  boundary     : 5019261784704417792
Slave: Route conversion PCM (sformat=S16_LE)
  Transformation table:
    0 <- 0
    1 <- 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 44100
  exact rate   : 44100 (44100/1)
  msbits       : 16
  buffer_size  : 16384
  period_size  : 1024
  period_time  : 23219
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 16384
  stop_threshold   : 16384
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
Slave: Direct Stream Mixing PCM
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 44100
  exact rate   : 44100 (44100/1)
  msbits       : 16
  buffer_size  : 16384
  period_size  : 1024
  period_time  : 23219
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 16384
  stop_threshold   : 16384
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
Hardware PCM card 0 'Sound BlasterX G1' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 44100
  exact rate   : 44100 (44100/1)
  msbits       : 16
  buffer_size  : 16384
  period_size  : 1024
  period_time  : 23219
  tstamp_mode  : ENABLE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 4611686018427387904
  silence_threshold: 0
  silence_size : 4611686018427387904
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0

Container with non-working audio
Bash:
[userland@container ~]# aplay -v /usr/share/sounds/gnome/default/alerts/drip.ogg
ALSA lib pulse.c:242:(pulse_connect) PulseAudio: Unable to connect: Connection refused
aplay: main:867: audio open error: Connection refused
 
Hi,
Host with working audio
Bash:
root@proxmox:~# aplay -v /usr/share/sounds/alsa/Front_Left.wav
Playing WAVE '/usr/share/sounds/alsa/Front_Left.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Plug PCM: Rate conversion PCM (44100, sformat=S16_LE)
Okay, so apparently, aplay on the host doesn't use PulseAudio ...

Bash:
[userland@container ~]# aplay -v /usr/share/sounds/gnome/default/alerts/drip.ogg
ALSA lib pulse.c:242:(pulse_connect) PulseAudio: Unable to connect: Connection refused
aplay: main:867: audio open error: Connection refused
... but aplay in the container tries to use PulseAudio, which is (apparently?) installed within the container. The "Connection refused" error seems to be more of a PulseAudio permissions issue, see e.g. [1].

I guess there are some more things you could try (possibly even more):
  • In the container, uninstall or mask (as the audio group member, run systemctl --user mask pulseaudio.service and restart the container) PulseAudio and see whether aplay in the container works then. However, even if this works, there might be applications inside the container which depend on PulseAudio and break?
  • Keep PulseAudio inside the container, try to fix the PulseAudio "Connection refused" issue (e.g. [1]) and check whether it recognizes the sound card(s), and/or install PulseAudio on the host and let PulseAudio in the container connect to PulseAudio on the host using [2].
Hope this helps!

[1]: https://unix.stackexchange.com/a/465734
[2]: https://xahteiwi.eu/resources/hints-and-kinks/lxc-sound/

Edit: corrected systemctl unmask to systemctl mask
 
Last edited:
Hi,

Okay, so apparently, aplay on the host doesn't use PulseAudio ...


... but aplay in the container tries to use PulseAudio, which is (apparently?) installed within the container. The "Connection refused" error seems to be more of a PulseAudio permissions issue, see e.g. [1].

I guess there are some more things you could try (possibly even more):
  • In the container, uninstall or mask (as the audio group member, run systemctl --user unmask pulseaudio.service and restart the container) PulseAudio and see whether aplay in the container works then. However, even if this works, there might be applications inside the container which depend on PulseAudio and break?
  • Keep PulseAudio inside the container, try to fix the PulseAudio "Connection refused" issue (e.g. [1]) and check whether it recognizes the sound card(s), and/or install PulseAudio on the host and let PulseAudio in the container connect to PulseAudio on the host using [2].
Hope this helps!

[1]: https://unix.stackexchange.com/a/465734
[2]: https://xahteiwi.eu/resources/hints-and-kinks/lxc-sound/
Thanks for sticking with me. Yeah, Pulseaudio comes preinstalled with Rocky Linux 9.1 (RHEL 9 variant) set up as a Workstation.

When I try to ruy systemctl as userland user (that is in the audio group) in the container, I get this:
Bash:
[userland@container root]$ systemctl --user mask pulseaudio.service
Failed to connect to bus: Permission denied
[userland@container root]$ sudo systemctl --user mask pulseaudio.service
Failed to connect to bus: No medium found
[userland@container root]$ sudo systemctl --user mask pulseaudio
Failed to connect to bus: No medium found
[userland@container root]$ pulseaudio --start
E: [autospawn] core-util.c: XDG_RUNTIME_DIR (/run/user/0) is not owned by us (uid 1000), but by uid 0! (This could e.g. happen if you try to connect to a non-root PulseAudio as a root user, over the native protocol. Don't do that.)
W: [autospawn] lock-autospawn.c: Cannot access autospawn lock.
E: [pulseaudio] main.c: Failed to acquire autospawn lock

Bash:
[userland@container root]$ sudo yum list pulse*
Last metadata expiration check: 3:07:03 ago on Fri 28 Apr 2023 10:38:56 AM EDT.
Installed Packages
pulseaudio.x86_64                                                           15.0-2.el9                                           @appstream
pulseaudio-libs.x86_64                                                      15.0-2.el9                                           @appstream
pulseaudio-libs-devel.x86_64                                                15.0-2.el9                                           @appstream
pulseaudio-libs-glib2.x86_64                                                15.0-2.el9                                           @appstream
pulseaudio-module-bluetooth.x86_64                                          15.0-2.el9                                           @appstream
pulseaudio-utils.x86_64                                                     15.0-2.el9                                           @appstream

[userland@container root]$ sudo yum list alsa*
Last metadata expiration check: 3:07:10 ago on Fri 28 Apr 2023 10:38:56 AM EDT.
Installed Packages
alsa-firmware.noarch                                                     1.2.4-6.el9                                             @appstream
alsa-lib.x86_64                                                          1.2.7.2-1.el9                                           @appstream
alsa-lib-devel.x86_64                                                    1.2.7.2-1.el9                                           @appstream
alsa-plugins-arcamav.x86_64                                              1.2.7.1-1.el9                                           @appstream
alsa-plugins-maemo.x86_64                                                1.2.7.1-1.el9                                           @appstream
alsa-plugins-oss.x86_64                                                  1.2.7.1-1.el9                                           @appstream
alsa-plugins-pulseaudio.x86_64                                           1.2.7.1-1.el9                                           @appstream
alsa-plugins-samplerate.x86_64                                           1.2.7.1-1.el9                                           @appstream
alsa-plugins-speex.x86_64                                                1.2.7.1-1.el9                                           @appstream
alsa-plugins-upmix.x86_64                                                1.2.7.1-1.el9                                           @appstream
alsa-plugins-usbstream.x86_64                                            1.2.7.1-1.el9                                           @appstream
alsa-plugins-vdownmix.x86_64                                             1.2.7.1-1.el9                                           @appstream
alsa-sof-firmware.noarch                                                 2.1.1-1.el9                                             @appstream
alsa-tools-firmware.x86_64                                               1.2.2-6.el9                                             @appstream
alsa-ucm.noarch                                                          1.2.7.2-1.el9                                           @appstream
alsa-utils.x86_64                                                        1.2.7-1.el9                                             @appstream

[userland@container root]$ sudo yum list pipewire*
Last metadata expiration check: 3:07:15 ago on Fri 28 Apr 2023 10:38:56 AM EDT.
Installed Packages
pipewire.x86_64                                                                   0.3.47-2.el9                                   @appstream
pipewire-alsa.x86_64                                                              0.3.47-2.el9                                   @appstream
pipewire-gstreamer.x86_64                                                         0.3.47-2.el9                                   @appstream
pipewire-jack-audio-connection-kit.x86_64                                         0.3.47-2.el9                                   @appstream
pipewire-libs.x86_64                                                              0.3.47-2.el9                                   @appstream
pipewire-utils.x86_64                                                             0.3.47-2.el9                                   @appstream

I actually tried removing all of pulseaudio by duplicating the container and running the commands. Due to dependencies and stuff, it completely removes the GNOME environment. After reinstalling GNOME, some of the packages end up getting reinstalled. It seems that it needs to be there, but I am not sure if it necessarily needs to be used.

I did have problems initially getting this working on another NUC even without Proxmox. Sound took forever to get working, lots of trial and error, and ultimately, I couldn't get it working over xrdp. Thankfully, the nuc is close enough that I can hear it come through the local speakers, which I was looking to replicate in the Proxmox LXC container.

I haven't had the chance to try the second link yet, but will plan on doing that later today!
 
@fweber I made an interesting discovery without making any further changes on the container.

If I try to play this WAV file using the following command, it does play properly in the container:
Bash:
aplay --device=sysdefault:CARD=G1 /usr/share/sounds/alsa/Front_Left.wav

However, in Gnome sound settings, this is the only audio device that shows up: Dummy Output

Looking at available Pulseaudio sinks, the sound card does not show up:
Code:
[userland@container pacmd list-sinks
1 sink(s) available.
  * index: 0
    name: <auto_null>
    driver: <module-null-sink.c>
    flags: DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
    state: IDLE
    suspend cause: (none)
    priority: 1000
    volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    base volume: 65536 / 100% / 0.00 dB
    volume steps: 65537
    muted: no
    current latency: 1488.86 ms
    max request: 344 KiB
    max rewind: 344 KiB
    monitor source: 0
    sample spec: s16le 2ch 44100Hz
    channel map: front-left,front-right
                 Stereo
    used by: 0
    linked by: 0
    configured latency: 2000.00 ms; range is 0.50 .. 2000.00 ms
    module: 2
    properties:
        device.description = "Dummy Output"
        device.class = "abstract"
        device.icon_name = "audio-card"

I'm not exactly how to solve this or proceed further, but it seems that whatever config is being passed into the container is working to play the WAV file with aplay, but I have to specifically pass the device name for it to play correctly!
 
Pulseaudio has lots of options and settings. It can run per user session or as one service for all users or as a normal application (or connect to a remote pulseaudio). It does a lot of things when it detects a USB audio device, but that does not work in a container (no hotplug, no module loading). Maybe you can find some helpful settings in the Arch Wiki?
 
  • Like
Reactions: fweber
Hi,
@fweber I made an interesting discovery without making any further changes on the container.

If I try to play this WAV file using the following command, it does play properly in the container:
Bash:
aplay --device=sysdefault:CARD=G1 /usr/share/sounds/alsa/Front_Left.wav
Well, that's good news :) I think --device sysdefault:CARD=G1 tells aplay to not use the default PulseAudio device, but talk to the card directly via /dev/snd.

Looking at available Pulseaudio sinks, the sound card does not show up:
So it seems it is not that easy to uninstall/mask PulseAudio inside the container, and PulseAudio doesn't recognize the sound card. The GNOME sound settings are probably also using PulseAudio under the hood.

I did find a thread [1] that describes a similar problem, and there it was possible to manually load the respective PulseAudio server module using
Code:
pactl load-module module-alsa-card device_id=1
(the device ID may differ in your case, though).

You could try this and check whether pacmd list-sinks lists the outputs afterwards. If it does, the only remaining thing to fix would be the Connection refused error from aplay, which apparently prevents aplay from connecting to the PulseAudio server. You could also try if maybe paplay works.

[1]: https://bbs.archlinux.org/viewtopic.php?pid=1642543#p1642543