# 媒体引擎 · WebRtcVoiceEngine 与 WebRtcVideoEngine

> 媒体引擎是「协商出的媒体配置」和「实际编解码 + Call 流」之间的胶水层。这一章读 media/engine 的 WebRtcVoiceEngine/WebRtcVideoEngine：它们怎么创建媒体通道、把编解码器工厂接进来，以及在架构里承上启下的位置。

- 作者：David（道雾轩）
- 专栏：音视频与 WebRTC 详解（https://daiw.org/manual/webrtc.md）
- 最后更新：2026-07-14
- 原文：https://daiw.org/manual/webrtc/media-engine
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 媒体引擎 · WebRtcVoiceEngine 与 WebRtcVideoEngine

[`Call` 管媒体流](https://daiw.org/manual/webrtc/call-object)，[编解码器有统一抽象](https://daiw.org/manual/webrtc/video-encoder-abstraction)，但中间需要一个**胶水层**——把“[SDP 协商出的媒体配置](https://daiw.org/manual/webrtc/media-session)”翻译成“用哪些[编解码器](https://daiw.org/manual/webrtc/audio-codecs)、建哪些 [Call 流](https://daiw.org/manual/webrtc/call-object)”。这就是**媒体引擎**（`media/engine/`）：音频的 `WebRtcVoiceEngine`、视频的 `WebRtcVideoEngine`。

## 两个引擎

媒体引擎按音视频分两个（`media/engine/`）：

```cpp
// media/engine/webrtc_voice_engine.h(节选)
class WebRtcVoiceEngine final : public VoiceEngineInterface {
  std::unique_ptr<VoiceMediaSendChannelInterface> CreateSendChannel(...);
  std::unique_ptr<VoiceMediaReceiveChannelInterface> CreateReceiveChannel(...);
};
// media/engine/webrtc_video_engine.h:WebRtcVideoEngine 对称
```

<Callout type="info">
  **媒体引擎是“媒体能力的提供者 + 媒体通道的工厂”——它知道支持哪些[编解码器](https://daiw.org/manual/webrtc/audio-codecs)（持有[编解码器工厂](https://daiw.org/manual/webrtc/factory-and-context)），并据[协商结果](https://daiw.org/manual/webrtc/media-session)创建**媒体通道**（`CreateSendChannel`/`CreateReceiveChannel`），把编解码器和 [`Call` 的流](https://daiw.org/manual/webrtc/call-object)接起来。**

  - **`WebRtcVoiceEngine`** —— 音频引擎。持有[音频编解码器工厂](https://daiw.org/manual/webrtc/audio-codecs)（[Opus 等](https://daiw.org/manual/webrtc/audio-codecs)）、[ADM](https://daiw.org/manual/webrtc/audio-device-mixer)、[APM](https://daiw.org/manual/webrtc/apm-overview)、[音频混音器](https://daiw.org/manual/webrtc/audio-device-mixer)。它 `CreateSendChannel` 建的音频发送通道，内部会用 [`AudioSendStream`](https://daiw.org/manual/webrtc/audio-pipeline-overview) 干活。
  - **`WebRtcVideoEngine`** —— 视频引擎。持有[视频编解码器工厂](https://daiw.org/manual/webrtc/video-encoder-abstraction)（VP8/VP9/AV1/H264 的[编解码器实现](https://daiw.org/manual/webrtc/video-encoder-abstraction)）。它建的视频通道内部用 [`VideoSendStream`/`VideoReceiveStream2`](https://daiw.org/manual/webrtc/video-pipeline-overview)。

  **媒体引擎是“[SDP 协商](https://daiw.org/manual/webrtc/media-session)”和“[Call 流](https://daiw.org/manual/webrtc/call-object)”之间的翻译官**：协商说“用 Opus、双向”，媒体引擎就据此建一个配好 Opus 的音频通道，通道再让 `Call` 建对应的流。它把[抽象的媒体配置](https://daiw.org/manual/webrtc/media-session)落地成[具体的编解码 + 收发管线](https://daiw.org/manual/webrtc/video-pipeline-overview)。
</Callout>

## 承上启下的位置

媒体引擎在架构里**承上启下**：

```mermaid
flowchart TD
    SDP["SDP 协商(media_session)<br/>「用 Opus/VP8,双向」"] --> CH["媒体通道(channel,第 9 部分)"]
    CH --> ENG["媒体引擎<br/>WebRtcVoiceEngine/VideoEngine"]
    ENG -->|"CreateSendChannel"| MC["MediaSendChannel"]
    ENG -->|"持有编解码器工厂"| CODEC["Opus/VP8/... 编解码器"]
    MC -->|"驱动"| CALL["Call 建流(AudioSendStream 等)"]
    CALL --> PIPE["音视频管线(第 6/7 部分)"]
```

- **上承** [SDP 协商](https://daiw.org/manual/webrtc/media-session)——协商出的编解码器、方向、参数，通过[媒体通道](https://daiw.org/manual/webrtc/media-channels)传给引擎。
- **下启** [Call 流 + 编解码器](https://daiw.org/manual/webrtc/call-object)——引擎据配置建通道、通道让 `Call` 建流、流用引擎提供的编解码器编解码。

它是“[控制面的协商结果](https://daiw.org/manual/webrtc/offer-answer-handler)”最终变成“[媒体面的实际管线](https://daiw.org/manual/webrtc/video-pipeline-overview)”的**转换点**——协商说的话，在这里变成真正跑起来的编解码。

## 引擎的初始化

媒体引擎在 [`PeerConnectionFactory` 初始化时](https://daiw.org/manual/webrtc/factory-and-context)创建，是 [`ConnectionContext` 里的 `media_engine_` 成员](https://daiw.org/manual/webrtc/factory-and-context)（[第 1 部分见过](https://daiw.org/manual/webrtc/factory-and-context)）。创建时，把[工厂依赖里的编解码器工厂、ADM 等](https://daiw.org/manual/webrtc/factory-and-context)注入进来。所以你想[换编解码器 / 音频设备](https://daiw.org/manual/webrtc/factory-and-context)，就是通过[工厂依赖](https://daiw.org/manual/webrtc/factory-and-context)影响媒体引擎——这呼应了[第 1 部分的依赖注入](https://daiw.org/manual/webrtc/factory-and-context)：**媒体引擎是那些可替换部件（编解码器、ADM、APM）的汇聚地**。

## 小结与下一章

**媒体引擎**（`WebRtcVoiceEngine`/`WebRtcVideoEngine`，`media/engine/`）是“[SDP 协商配置](https://daiw.org/manual/webrtc/media-session)”和“[Call 流 + 编解码](https://daiw.org/manual/webrtc/call-object)”之间的**翻译胶水**：持有[编解码器工厂](https://daiw.org/manual/webrtc/video-encoder-abstraction)（[及 ADM/APM/混音器](https://daiw.org/manual/webrtc/audio-device-mixer)），据协商 `CreateSendChannel`/`CreateReceiveChannel` 建[媒体通道](https://daiw.org/manual/webrtc/media-channels)，通道驱动 [`Call` 建流](https://daiw.org/manual/webrtc/call-object)。它**承上**（[协商](https://daiw.org/manual/webrtc/offer-answer-handler)）**启下**（[管线](https://daiw.org/manual/webrtc/video-pipeline-overview)），是[控制面到媒体面](https://daiw.org/manual/webrtc/peer-connection-object)的转换点，也是[可替换部件的汇聚地](https://daiw.org/manual/webrtc/factory-and-context)。

媒体引擎建的“[媒体通道](https://daiw.org/manual/webrtc/media-channels)”，和 [SDP 协商](https://daiw.org/manual/webrtc/offer-answer-handler)对接的那层，是 `channel`。下一章看它。👉 [媒体通道](https://daiw.org/manual/webrtc/media-channels)。

## 参考资料

- [1] libwebrtc 源码.`media/engine/webrtc_voice_engine.h`、`webrtc_video_engine.h`（`CreateSendChannel` 等）。
- [2] 关联[Call](https://daiw.org/manual/webrtc/call-object)、[编解码器抽象](https://daiw.org/manual/webrtc/video-encoder-abstraction)、[工厂依赖注入](https://daiw.org/manual/webrtc/factory-and-context)。
- [3] libwebrtc 源码.`media/base/media_engine.h`（`MediaEngineInterface`）。
