无声卡Docker容器中Puppeteer录屏无音频问题求助
问题:Docker容器中会议录屏应用无音频,pactl连接拒绝
我开发了一款可录制带音频会议的应用,在有声卡的本地系统上可正常运行,甚至支持多会议录制。但将其部署到无声卡服务器的Docker容器后,录屏内容没有音频。尝试配置PulseAudio及sinks,但执行pactl命令时始终提示连接拒绝,查阅资料后仍未解决。
现有代码
Dockerfile
FROM ultrafunk/undetected-chromedriver RUN mkdir /app /app/recordings /app/screenshots # Set the working directory inside the container WORKDIR /app # Install necessary dependencies RUN apt-get update && \ apt-get install -y \ python3 \ python3-pip \ pulseaudio \ pavucontrol \ curl \ sudo \ pulseaudio \ xvfb \ libnss3-tools \ ffmpeg \ xdotool \ unzip \ x11vnc \ libfontconfig \ libfreetype6 \ xfonts-cyrillic \ xfonts-scalable \ fonts-liberation \ fonts-ipafont-gothic \ fonts-wqy-zenhei \ xterm \ vim RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \ && echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \ && apt-get update \ && apt-get install -y google-chrome-stable \ && rm -rf /var/lib/apt/lists/* RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ apt-get install -y nodejs # Install PM2 globally RUN npm install -g pm2 RUN usermod -aG audio root RUN adduser root pulse-access ENV key=value DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket ENV XDG_RUNTIME_DIR=/run/user/0 RUN mkdir -p /run/dbus RUN chmod 755 /run/dbus RUN rm -rf /var/run/pulse /var/lib/pulse /root/.config/pulse RUN dbus-daemon --system --fork RUN wget http://files.portaudio.com/archives/pa_stable_v190700_20210406.tgz RUN tar -xvf pa_stable_v190700_20210406.tgz RUN mv portaudio /usr/src/ WORKDIR /usr/src/portaudio RUN ./configure && \ make && \ make install && \ ldconfig RUN echo 'user ALL=(ALL:ALL) NOPASSWD:ALL' >> /etc/sudoers RUN adduser root pulse-access RUN mkdir -p /var/run/dbus RUN dbus-uuidgen > /var/lib/dbus/machine-id #RUN dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address WORKDIR /app #COPY chromedriver /usr/bin/chromedriver # Copy your application code to the container COPY . /app # Set any environment variables if required ENV X_SERVER_NUM=1 ENV SCREEN_WIDTH=1280 ENV SCREEN_HEIGHT=1024 ENV SCREEN_RESOLUTION=1280x1024 ENV COLOR_DEPTH=24 ENV DISPLAY=:${X_SERVER_NUM}.0 RUN touch /root/.Xauthority RUN chmod 600 /root/.Xauthority RUN rm /run/dbus/pid RUN mv pulseaudio.conf /etc/dbus-1/system.d/pulseaudio.conf RUN npm install # Start the application with Node.js CMD ["pm2-runtime", "src/script.js"]
启动浏览器前创建sinks的代码
const commands = [ "sudo rm -rf /var/run/pulse /var/lib/pulse /root/.config/pulse", "sudo pulseaudio -D --verbose --exit-idle-time=-1 --system --disallow-exit >> /dev/null 2>&1", 'sudo pactl load-module module-null-sink sink_name=DummyOutput sink_properties=device.description="Virtual_Dummy_Output"', 'sudo pactl load-module module-null-sink sink_name=MicOutput sink_properties=device.description="Virtual_Microphone_Output"', "sudo pactl set-default-source MicOutput.monitor", "sudo pactl set-default-sink MicOutput", "sudo pactl load-module module-virtual-source source_name=VirtualMic" ]; commands.forEach(command => { exec(command, (error, stdout, stderr) => { if (error) { console.error(`Error executing command \"${command}\":`, error); return; } if (stderr) { console.error(`stderr: ${stderr}`); return; } console.log(`stdout: ${stdout}`); }); }); const browser = await puppeteer.launch({ headless: true, args: [ '--use-fake-ui-for-media-stream', '--allow-file-access-from-files', '--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu','--disable-extensions', '--disable-application-cache','--disable-dev-shm-usage' ], executablePath: '/usr/bin/google-chrome-stable' });
解决方案
1. 修复Dockerfile中的关键问题
- 移除Build阶段无效的服务启动命令:
dbus-daemon --system --fork在镜像构建阶段执行后不会保留到容器运行时,需放到运行时启动脚本中。 - 清理重复配置:删除重复的
adduser root pulse-access和pulseaudio安装命令,保留一次即可。 - 预配置PulseAudio虚拟设备:创建
/etc/pulse/default.pa文件,预加载虚拟音频设备,避免动态加载出错:
在Dockerfile中添加复制命令:load-module module-null-sink sink_name=DummyOutput sink_properties=device.description="Virtual_Dummy_Output" load-module module-null-sink sink_name=MicOutput sink_properties=device.description="Virtual_Microphone_Output" load-module module-virtual-source source_name=VirtualMic master=MicOutput.monitor set-default-source MicOutput.monitor set-default-sink MicOutputCOPY default.pa /etc/pulse/default.pa - 改用entrypoint脚本管理运行时服务:创建
entrypoint.sh脚本,统一启动dbus、pulseaudio和应用:
在Dockerfile中替换原CMD:#!/bin/bash # 启动dbus服务 dbus-daemon --system --fork # 启动pulseaudio服务 pulseaudio -D --verbose --exit-idle-time=-1 --system --disallow-exit # 启动应用 pm2-runtime src/script.jsCOPY entrypoint.sh /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh CMD ["/app/entrypoint.sh"]
2. 修正启动脚本中的命令
- 移除sudo前缀:容器以root用户运行,无需sudo,避免权限冲突。
- 添加服务就绪等待:pulseaudio启动为异步操作,直接执行pactl会连接失败,需添加延时:
const execSync = require('child_process').execSync; // 清理旧的pulse数据 execSync("rm -rf /var/run/pulse /var/lib/pulse /root/.config/pulse"); setTimeout(async () => { // 验证虚拟设备是否加载成功 try { const sinks = execSync("pactl list sinks").toString(); console.log("Available sinks:", sinks); } catch (err) { console.error("Failed to list sinks:", err); } // 启动浏览器,补充音频设备参数 const browser = await puppeteer.launch({ headless: true, args: [ '--use-fake-ui-for-media-stream', '--use-fake-device-for-media-stream', // 强制使用虚拟媒体设备 '--allow-file-access-from-files', '--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu','--disable-extensions', '--disable-application-cache','--disable-dev-shm-usage', '--alsa-device=VirtualMic', // 指定虚拟麦克风 '--audio-output-device=MicOutput' // 指定虚拟输出设备 ], executablePath: '/usr/bin/google-chrome-stable' }); }, 2000); // 等待2秒确保pulseaudio启动完成
3. 容器运行时参数补充
启动容器时,需添加权限和环境变量配置:
docker run -d --name recorder-app \ --privileged \ -e PULSE_SERVER=unix:/run/user/0/pulse/native \ your-image-name
4. 验证服务状态
进入容器执行以下命令,确认PulseAudio运行正常:
# 检查pulseaudio进程 ps aux | grep pulseaudio # 检查虚拟设备是否存在 pactl list sinks
内容的提问来源于stack exchange,提问作者Rohan Sharma
相关产品推荐
相关产品推荐

