You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无声卡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文件,预加载虚拟音频设备,避免动态加载出错:
    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 MicOutput
    
    在Dockerfile中添加复制命令:
    COPY default.pa /etc/pulse/default.pa
    
  • 改用entrypoint脚本管理运行时服务:创建entrypoint.sh脚本,统一启动dbus、pulseaudio和应用:
    #!/bin/bash
    # 启动dbus服务
    dbus-daemon --system --fork
    # 启动pulseaudio服务
    pulseaudio -D --verbose --exit-idle-time=-1 --system --disallow-exit
    # 启动应用
    pm2-runtime src/script.js
    
    在Dockerfile中替换原CMD:
    COPY 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 20:59:53