使用音频设备播放 WebRTC C++ 应用程序的 AudioStream

Play AudioStream of WebRTC C++ Application with Audio Device

我用 C++ 编写了两个使用 WebRTC 的命令行应用程序:

基本实现工作:他们交换 SDP-Offer 和 -Answer,使用 ICE 找到他们的外部 IP,创建具有相应约束的 PeerConnection 和 PeerConnectionFactory 等。我在服务器端添加了一个钩子到 RtpReceiverImpl::IncomingRtpPacket 将接收到的有效负载写入文件。该文件包含有效的 PCM 音频。因此,我假设客户端通过网络成功地将数据流式传输到服务器应用程序。

在服务器端,我的回调 PeerConnectionObserver::OnAddStream 被调用并收到 MediaStreamInterface。此外,我可以通过我的音频设备迭代 DeviceManagerInterface::GetAudioOutputDevices。所以基本上,一切都很好。

缺少什么:我需要某种胶水来告诉 WebRTC 在相应的设备上播放我的 AudioStream。我已经看到我可以获得 AudioSink、AudioRenderer 和 AudioTrack 对象。再一次:不幸的是,我没有看到将它们传递给音频设备的接口。有人可以帮我吗?

一个重要提示:我想避免调试真正的硬件。因此,我在构建 WebRTC 模块时添加了 -DWEBRTC_DUMMY_FILE_DEVICES。它应该将音频写入输出文件,但该文件仅包含 0x00。输入文件读取成功,因为正如我前面提到的,音频是通过 RTP 发送的。

最后,我找到了解决方案:首先,我不得不说我的代码使用的是 2017 年的 WebRTC。因此,以下内容可能已更改 and/or 已修复:

在调试我的代码和我看到的 WebRTC 库之后:添加远程流时,播放应该自动开始。开发人员无需在 VoiceEngine 中调用 playout() 或类似的东西。当库识别出远程音频流时,播放暂停,新源添加到混音器,然后恢复播放。唯一控制播放的 API 由 webrtc::MediaStreamInterface 提供,它通过 PeerConnectionObserver::OnAddStream 传递。例如 SetVolume()set_enabled().

那么,我的情况出了什么问题?我使用了 FileAudioDevice class 应该将原始音频数据写入输出文件而不是扬声器。我的实现包含两个错误:

  • FileAudioDevice::Playing() 在任何情况下都返回 true。因此,库添加了远程流,想要恢复播放,调用 FileAudioDevice::Playing() 返回 true 并中止,因为它认为 AudioDevice 已经处于播放模式。
  • FileWrapper class 中似乎存在错误。最终输出通过 _outputFile.Write(_playoutBuffer, kPlayoutBufferSize)FileAudioDevice::PlayThreadProcess() 写入磁盘。但是,这不起作用。幸运的是,一个普通的 C fwrite() 作为 hacky bugfix 确实有效。