背景
我正在尝试控制在 Chrome 上运行的 WebRTC Web 应用程序的输入,该应用程序由 Docker 容器内的 Selenium 控制。
这是 WebRTC 应用程序自动测试的一部分。
作为测试的一部分,我需要能够检查音频是否在应该接收时在另一端接收。
基本上,我想检查如果一个客户端说话,另一个客户端是否听到,反之亦然,除非客户端处于静音状态。
现在,我可以通过使用命令行参数启动 Chrome,轻松让它模拟麦克风(和摄像头)输入:
--use-fake-ui-for-media-stream
--use-fake-device-for-media-stream
问题是默认样本中有很多静音(更难检测)。我可以通过提供具有更一致音频的自己的音频文件来解决这个问题:
--use-file-for-fake-audio-capture=/opt/media/audio1.wav
但这还有另一个问题 - 如果 Chrome 同时发送和接收音频,则作为 Chrome 回声消除功能的一部分,接收到的音频会受到严重干扰,几乎完全静音。(回声消除是作为 WebRTC 应用程序的一部分设置的,而不是作为 Chrome 本身的一部分设置的,我不想为了方便测试而更改正在测试的代码。)
使用两个不同的样本(每个客户端一个)会略有帮助,但帮助不大。
真正的问题是,两个客户端在运行时都会不停地“交谈”,这会因为前面提到的回声消除而弄乱音频,并且由于人们通常不会不断地互相交谈,所以这不是一个现实的测试场景。
理论上,我可以使用专门创建的样本,其中包含有意包含噪音/静音的部分,但随后在客户端之间以及与测试验证之间对齐这些样本将是一场噩梦。
问题
我真正需要的是能够根据需要开始和停止在客户端播放音频。
似乎没有任何方法可以控制 Chrome 中的虚假媒体流,因此似乎我最好的选择可能是以某种方式在 Docker 容器内创建一个虚假的“麦克风”音频输入设备,然后控制它。
在标准 Linux 上,您可以使用 pulseaudio 将音频输出循环回来作为捕获设备,这看起来很有希望,但我不知道如何在 Docker 容器中使用它。Docker 容器
甚至没有任何音频设备可供使用。
我找到了各种关于如何设置 Docker 以使用主机音频硬件的指南,但这并不是很有用,因为这些容器在 eSXI 服务器上运行并且没有任何声卡可用。Pulseaudio
还支持虚拟设备,但这些设备需要驱动程序/内核模块才能工作。我可能错了,但我认为你不能在 Docker 容器中使用它们。
问题
抱歉,上面的内容有点冗长,但我试图解释这个问题以及我已经研究过的各个方向。
那么,是否有人知道如何控制 Docker 容器内 Chrome 捕获设备的音频输入,无论是使用伪捕获设备,还是通过其他方式?
答案1
我设法找到了解决方案。基本概念相当简单,但有几个问题需要解决。
该解决方案涉及利用 pulseaudio 创建虚拟音频源的能力,以及利用 paplay 工具将媒体播放到该音频设备中。
设置 Docker 容器
我需要基于我已经在使用的 Ubuntu/Chrome/Selenium 镜像来制作自己的 Docker 镜像,以安装 pulseaudio 包、调整入口点以启动它,并添加一些要播放的音频文件。
docker文件:
FROM selenium/standalone-chrome-debug
# Install pulse audio
RUN apt-get -qq update && apt-get install -y pulseaudio
# Copy some media files into place
RUN mkdir -p /opt/media
COPY audio1.wav /opt/media/audio1.wav
COPY audio2.wav /opt/media/audio2.wav
# Use custom entrypoint
COPY entrypoint.sh /opt/bin/entrypoint.sh
ENTRYPOINT /opt/bin/entrypoint.sh
然后,我需要一个自定义入口点来启动 pulseaudio 服务器并配置自定义音频源,然后再启动标准 Selenium 启动入口点。
这里有两个虚拟设备,因此其中一个可用于音频播放,而无需将其传输到虚拟麦克风。
入口点
# Load pulseaudio virtual audio source
pulseaudio -D --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
# Configure the "seluser" user to use the network virtual soundcard
mkdir -p /home/seluser/.pulse
echo "default-server = 127.0.0.1" > /home/seluser/.pulse/client.conf
chown seluser:seluser /home/seluser/.pulse -R
# Start Selenium-Chrome-Standalone
/opt/bin/entry_point.sh
因为我想在以“seluser”用户身份运行的由 Selenium 控制的 Chrome 实例中使用音频设备,所以我需要通过 TCP(仅适用于本地主机连接)公开虚拟声卡,然后配置 seluser 以使用该联网声卡。无需额外设置。虚拟源是 Docker 映像上唯一的音频输入设备,因此 Chrome 会自动使用它。剩下的就是构建和运行 docker 容器。
播放音频
容器运行后,我使用 paplay 将媒体发送到虚拟输出设备,我在上面将其命名为“MicOutput”。这可以通过 exec 命令触发:
docker exec -t -i TestContainerName paplay --device=MicOutput /opt/media/audio2.wav
就是这样。
当然,在配置我的 Selenium WebDriver 时,我还需要在 Chrome 功能中使用“--use-fake-ui-for-media-stream”选项,以让 Selenium 无需询问即可使用该设备,但必须确保不要使用“--use-fake-device-for-media-stream”选项,因为这会用 Chrome 的内置设备替换假输入设备。
感谢 spacepickle 的回答这个问题感谢 Eli Billauer 的帖子,他让我走上了正确的道路关于多用户使用 Pulse 音频