Pulseaudio 守护进程无法在 docker 中启动

Pulseaudio 守护进程无法在 docker 中启动

我正在尝试在 Docker 容器内模拟无头 chrome 实例的麦克风输入。

基于在 Docker 容器内模拟 Chrome 的麦克风输入我有以下设置:

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

运行容器时pulseaudio -D --verbose --exit-idle-time=-1失败,但没有进一步的详细信息:

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

我可以排除 pulseaudio 在容器内自动启动,因为后续输出如下:

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.

pulseaudio -k尝试E: [pulseaudio] main.c: Failed to kill daemon: No such process

由于没有错误信息,我很难找出问题所在,尤其是因为我对 pulseaudio 一点经验都没有。有谁知道哪里出了问题,或者为什么 pulseaudio 无法启动或出现任何错误?

目前正在 Ubuntu 16.04 桌面上进行测试。但它应该能够在服务器上运行。

答案1

首先非常感谢您的起点,因为我希望通过以虚拟用户身份加入会议并播放音频来做同样的事情。

Dockerfile我对您的和进行了以下更改,使其正常工作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

此后,音频重新路由工作正常,并且虚拟麦克风被容器内的浏览器识别为默认输入。

感兴趣的朋友可以参见更多信息:

首先声明,我绝不是 pulseaudio 专家,这一切都是在反复试验中发现的,可能不是最佳解决方案。

至于在容器启动/重启后 pulseaudio 守护进程无法启动的问题,您必须清理所有 pulseaudio 目录,让守护进程“无状态”启动。奇怪的是,每次我构建容器时它都能正常启动,但随后每次启动时它都会死机。所以这是我的解决方案,因为我不依赖 pulseaudio 的任何持久数据。

启动守护进程后,pulseaudio 已默认auto-null使用监视器作为源的空接收器,因此我将其映射到虚拟源VirtualMic。使其工作的关键是将监视器添加为虚拟源的主控,否则 puppeteer 浏览器在访问设备时会抛出媒体错误。之后它工作正常,docker 内播放的音频通过浏览器作为虚拟麦克风流式传输。

不要忘记将容器用户添加到组中pulse-access,否则您将再次收到相同的媒体错误。当我使用容器内的 root 用户运行时,我将RUN adduser root pulse-access其添加到Dockerfile

至于 tcp 部分,就我的用例而言,我不需要它。

我在容器内部调试时发现的事情:

  • 如果您使用 pactl/pacmd 向守护进程发送无效命令,则守护进程会悄悄死亡,后续命令会因您提到的错误而退出。
  • pacmd在容器内无法以任何方式工作,没有进一步调查,因为pactl工作正常
  • 它有助于在正常模式下启动 pulseaudio,无需 -D 来进行调试,然后执行pactl命令以获得信息调试输出

希望这也能帮助其他试图完成相同或类似任务的人。

相关内容