3

I'm trying to emulate microphone input for a headless chrome instance, inside a docker container.

Based on Emulating microphone input to Chrome inside Docker container I have the following setup:

Dockerfile

FROM buildkite/puppeteer:latest

RUN apt-get -qq update && apt-get install -y pulseaudio

COPY entrypoint.sh /opt/bin/entrypoint.sh

RUN useradd -ms /bin/bash bot
USER bot

ENTRYPOINT /opt/bin/entrypoint.sh

entrypoint.sh

# Load pulseaudio virtual audio source
pulseaudio -D --verbose --exit-idle-time=-1

# Create virtual output device (used for audio playback)
pactl load-module module-null-sink sink_name=DummyOutput sink_properties=device.description="Virtual_Dummy_Output"

# Create virtual microphone output, used to play media into the "microphone"
pactl load-module module-null-sink sink_name=MicOutput sink_properties=device.description="Virtual_Microphone_Output"

# Set the default source device (for future sources) to use the monitor of the virtual microphone output
pacmd set-default-source MicOutput.monitor

# Create a virtual audio source linked up to the virtual microphone output
pacmd load-module module-virtual-source source_name=VirtualMic

# Allow pulse audio to be accssed via TCP (from localhost only), to allow other users to access the virtual devices
pacmd load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1

mkdir -p /home/bot/.pulse
echo "default-server = 127.0.0.1" > /home/bot/.pulse/client.conf
chown bot:bot /home/bot/.pulse -R

When running the container, pulseaudio -D --verbose --exit-idle-time=-1 fails with no further details though:

E: [pulseaudio] main.c: Daemon startup failed.

I can rule out that pulseaudio autostarts inside the container, since the subsequent output is as follows:

Connection failure: Connection refused
Connection failure: Connection refused
No PulseAudio daemon running, or not running as session daemon.
No PulseAudio daemon running, or not running as session daemon.
No PulseAudio daemon running, or not running as session daemon.

and trying pulseaudio -k results in E: [pulseaudio] main.c: Failed to kill daemon: No such process

The lack of errors makes it pretty difficult for me to figure out what's wrong, especially because I do not have any experience with pulseaudio whatsoever. Does anyone have an idea what may be wrong or why pulseaudio won't start or give any errors?

Currently testing on a Ubuntu 16.04 Desktop. It should be able to run on a server though.

1 Answer 1

7

First of all thanks a lot for your starting point, as i was looking to do the same by joining a conference as virtual user and playing audio.

I got it working with the following changes to your Dockerfile and entrypoint.sh:

Dockerfile

FROM buildkite/puppeteer:latest

# Install pulse audio
RUN apt-get -qq update && apt-get install -y pulseaudio

# Use custom entrypoint
COPY entrypoint.sh /opt/bin/entrypoint.sh

# add root user to group for pulseaudio access
RUN adduser root pulse-access

# copy over node app and expose port or whatever you'd like to do else here (unrelated to pulseaudio)
# WORKDIR /opt/app
# COPY . /opt/app

ENTRYPOINT /opt/bin/entrypoint.sh

entrypoint.sh

# Cleanup to be "stateless" on startup, otherwise pulseaudio daemon can't start
rm -rf /var/run/pulse /var/lib/pulse /root/.config/pulse

# Start pulseaudio as system wide daemon; for debugging it helps to start in non-daemon mode
pulseaudio -D --verbose --exit-idle-time=-1 --system --disallow-exit

# Create a virtual audio source; fixed by adding source master and format
echo "Creating virtual audio source: ";
pactl load-module module-virtual-source master=auto_null.monitor format=s16le source_name=VirtualMic

# Set VirtualMic as default input source;
echo "Setting default source: ";
pactl set-default-source VirtualMic

# whatever you'd like to do next
# e.g. npm run start

After this the audio rerouting worked fine and the virtual mic was recognised by the browser inside the container as default input.

Further info for the interrested:

First of all a disclaimer, i'm no pulseaudio expert in any way, this was all found out in trial and error mode and may not be the optimal solution.

As for the issue where the pulseaudio daemon won't start after a container start/restart, you have to cleanup all pulseaudio directories to let the daemon start "statelessly". Strangely it started fine every time i built the container, but subsequently it died on every startup. So this was my solution to it as i don't rely on any persisted data from pulseaudio.

After starting the daemon pulseaudio already defaults a null sink auto-null with monitor as source, so i mapped this to the virtual source VirtualMic. The key to get it working was to add the monitor as master of the virtual source, otherwise the puppeteer browser threw a media error when accessing the device. After that it worked fine and the audio played inside the docker was streamed through the browser as virtual mic.

Don't forget to add your container user to the group pulse-access or you will get the same media error again. As i run with the root user inside the container i added RUN adduser root pulse-access to the Dockerfile.

As for the tcp part, i did not need that for my use case.

Things i found out during debugging inside the container:

  • The daemon silently dies if you send an invalid command to it with pactl/pacmd, further commands were quit with your mentioned errors.
  • pacmd did not work in any way inside the container, did not investigate further as pactl worked fine
  • It helps to start pulseaudio in normal mode without -D for debugging purposes then executing pactl commands for informative debugging output

Hope this helps also others who are trying to achieve the same or a similar task.

3
  • 2
    Thank you, you've saved my life. My attempts to get pacmd working have also met failure, and it seems like it's pretty much impossible. Thankfully, just substituting pactl for it worked for the commands I needed.
    – Kazami
    Jul 2, 2020 at 22:05
  • Thank you @thec00n your reply was very useful Oct 31, 2020 at 9:16
  • This is great, thank you! (You are based in Vienna? Please reach out!)
    – slhck
    Mar 20, 2023 at 9:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .