基于 RTC 场景下要解决的声音的问题,WebRTC 有一个大体如下图所示的音频处理流水线:

WebRTC 的音频处理流水线,不是一次性建立起来的,而是分阶段分步骤建立的。整体而言,可以认为这个流水线分两个阶段建立,或者可以认为这个流水线分为两部分:一部分可称为静态流水线,另一部分可称为动态流水线,或者也可以称为前端和后端。静态流水线,在某个时间点建立一次,随后在整个 WebRTC 通信过程中基本保持不变;动态流水线则在通信过程中,可能出现较为频繁的变动,如本地打开或禁用录制启动发送或停止发送音频数据,远端发送者加入或退出频道等,都会改变动态流水线。
如此,WebRTC 的音频处理流水线大致如下图所示:

WebRTC 音频的静态流水线,建立之后,其相关节点状态由 AudioState 维护和管理。WebRTC 音频的静态流水线,主要包括 AudioDeviceModule,AudioProcessing,和 AudioMixer 等,其中 AudioDeviceModule 用于采集和播放音频数据,AudioProcessing 主要用于对录制的音频数据做初始处理,如回声消除,降噪等,AudioMixer 主要用于对远端发送过来的音频数据做混音。
WebRTC 音频的静态流水线在 WebRtcVoiceEngine 初始化时建立:
WebRTC 音频静态流水线的几个节点,由外部创建好注入进来,并通过 AudioState 创建的 AudioTransport 连接起来:WebRtcVoiceEngine::Init()
根据需要创建 AudioDeviceModule,然后创建 AudioState,AudioState 用注入的 AudioMixer 和 AudioProcessing 创建 AudioTransport,WebRtcVoiceEngine::Init() 随后将 AudioState 创建的 AudioTransport 作为 AudioCallback 注册给 AudioDeviceModule。WebRTC 音频静态流水线在 WebRtcVoiceEngine::Init() 中建立。动态流水线和静态流水线在 AudioState 和 AudioTransport 处交汇。
AudioTransport
AudioDeviceModule 在录到音频数据时,将音频数据送给 AudioTransport,在播放音频时,也向 AudioTransport 拿要播放的音频数据。AudioTransport 是录制的音频数据和播放的音频数据的交汇点。
AudioTransport 接口的定义 (位于 webrtc/src/modules/audio_device/include/audio_device_defines.h) 如下:
WebRTC 中的 AudioTransport 接口实现 AudioTransportImpl 定义 (位于 webrtc/src/audio/audio_transport_impl.h) 如下:
AudioTransportImpl 实现的 AudioTransport 接口的要求的操作:将录制的音频数据送出去,及获取播放的音频数据。
AudioTransportImpl 对象创建时保存注入的 AudioMixer 和 AudioProcessing 对象指针:
播放
AudioDeviceModule 可以通过 AudioTransportImpl 的 NeedMorePlayData() 和 PullRenderData() 获取用于播放的音频数据:
NeedMorePlayData() 执行如下操作:
- 通过
AudioMixer对远端的音频流做混音。AudioTransportImpl没有直接与AudioReceiveStream建立连接,但AudioMixer的 source 实际上是AudioReceiveStream。 - 把混音后的音频数据送进
AudioProcessing。主要用于回声消除。 - 对混音后的音频数据重采样。如我们前面看到的
AudioMixerImpl的实现,它的混音输出采样率有它自己的决定逻辑,可能与AudioDeviceModule设备需要的不一致,这里需要按照设备的需要,将混音后的数据重采样到设备需要的采样率。 - 返回重采样的数据。
PullRenderData() 的操作与 NeedMorePlayData() 仅有的区别在于,没有上面的第 2 步。如注释中所说,在某些情况下,混音之后的数据无需送进 AudioProcessing。此外,PullRenderData() 要求调用者只能请求单通道的音频数据,NeedMorePlayData() 的调用者则可以请求单通道或立体声的。
重采样和混音的更多细节,这里不再赘述。
录制
AudioDeviceModule 可以通过 AudioTransport 的 RecordedDataIsAvailable() 把录制的数据送出去:
AudioTransportImpl 的 RecordedDataIsAvailable() 拿到录音得到的音频数据,对音频数据执行如下操作:
- 重采样。
AudioDeviceModule送进来的音频数据的采样率是设备采集的原始采样率,这里需要把采集的音频数据转换为适合 WebRTC 的音频处理模块如降噪和回声消除等模块及编码器处理的采样率。 - 对音频数据做回声消除,降噪等处理。
- 把音频数据送出去,给注入的
AudioSendStream。
AudioState
AudioState 既是 WebRTC 音频流水线节点的容器,也可用于对这些节点做一些管理和控制,以及将不同节点粘起来构成流水线。AudioState 接口的定义 (位于 webrtc/src/call/audio_state.h) 如下:
作为音频处理流水线的容器,AudioState 接口主要包含了 AudioMixer、AudioProcessing 和 AudioDeviceModule。AudioState 对象的创建主要通过静态工厂方法完成。
WebRTC 提供了 AudioState 接口的实现,该实现的定义 (位于 webrtc/src/audio/audio_state.h ) 如下:
如上面看到的,AudioState 对象在 WebRtcVoiceEngine::Init() 创建。AudioState 的 Create() 函数定义 (位于 webrtc/src/audio/audio_state.cpp) 如下:
WebRTC 中实际在用的 AudioState 对象为 webrtc::internal::AudioState 的对象。
AudioState 完成的工作主要为:
- 音频流水线的节点的 Getter
- 管理音频静态流水线和动态流水线的连接,也就是添加和移除
AudioSendStream和AudioReceiveStream:把AudioSendStream注入给AudioTransportImpl或从中移除,把AudioReceiveStream添加到AudioMixer或从中移除。这些接口主要由webrtc::Call使用。 - 控制播放和录制的启动和停止。
webrtc::internal::AudioState 的具体实现 (位于 webrtc/src/audio/audio_state.cpp) 如下:
总结一下:
WebRtcVoiceEngine::Init()建立了 WebRTC 音频处理的静态流水线。AudioTransport将音频处理静态流水线的各个节点粘起来。webrtc::Call使用AudioState将音频处理流水线的静态部分和动态部分连接起来。