# 编码器抽象与编解码器 · VP8/VP9/AV1/H264/H265

> WebRTC 用统一的 VideoEncoder 接口抽象各种编解码器，底下接 VP8、VP9、AV1、H264、H265。这一章读 video_codecs/video_encoder.h 的 InitEncode/Encode/SetRates，讲清这层抽象、编码器工厂、以及各编解码器的取舍。

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

# 编码器抽象与编解码器 · VP8/VP9/AV1/H264/H265

[准备好的帧](https://daiw.org/manual/webrtc/video-source-encoder)交给编码器压缩。WebRTC 支持一大堆编解码器，但上层不想为每种写一套代码——于是有了统一的 **`VideoEncoder` 抽象**（`api/video_codecs/video_encoder.h`）。这一章看这层抽象和它下面的编解码器们。

## VideoEncoder：统一接口

`VideoEncoder` 是所有视频编码器的**公共接口**，核心就三个方法：

```cpp
// api/video_codecs/video_encoder.h(节选)
class RTC_EXPORT VideoEncoder {
  virtual int InitEncode(const VideoCodec* codec_settings, ...);  // 初始化
  virtual int32_t Encode(const VideoFrame& frame, ...);           // 编码一帧
  virtual void SetRates(const RateControlParameters& parameters); // 设目标码率/帧率
  // 编码结果通过 EncodedImageCallback 异步回调
};
```

<Callout type="info">
  **`VideoEncoder` 把「五花八门的编解码器」收敛成一个统一契约：`InitEncode` 配置、`Encode` 喂一帧、`SetRates` 调码率，编好的压缩帧经 `EncodedImageCallback` 回调出来。** 上层的 [`VideoStreamEncoder`](https://daiw.org/manual/webrtc/video-source-encoder) 只面对这个接口，**完全不关心底下是 VP8 还是 AV1**——换编解码器，对上层透明。这是[依赖倒置](https://daiw.org/manual/webrtc/factory-and-context)的经典应用：上层依赖抽象 `VideoEncoder`，具体编解码器实现它。

  尤其 **`SetRates`** 是[拥塞控制闭环的落点](https://daiw.org/manual/webrtc/rate-control)：[拥塞控制算出的目标码率](https://daiw.org/manual/webrtc/rate-control)，经[分配](https://daiw.org/manual/webrtc/video-bitrate-allocation)后就是通过 `SetRates` 告诉编码器「你现在有这么多码率预算，编到这个大小之内」。编码器据此调整量化等参数，产出符合预算的压缩帧。**「网络能承受多少」到「画质多高」的传导，最终就发生在这个方法调用里。**
</Callout>

编码器由**工厂**创建——`VideoEncoderFactory`（[可在 PeerConnectionFactory 依赖里替换](https://daiw.org/manual/webrtc/factory-and-context)），这让平台能提供**硬件编码器**（手机的专用编码芯片，省电省 CPU）或软件编码器。

## 五种编解码器

WebRTC 支持的主要视频编解码器，各有取舍：

| 编解码器 | 特点 | 典型场景 |
| --- | --- | --- |
| **VP8** | 老牌、兼容性最好、纯软件 | 保底、老设备 |
| **VP9** | 比 VP8 省 ~50% 码率，支持 [SVC](https://daiw.org/manual/webrtc/simulcast-svc) | 带宽敏感 |
| **AV1** | 最新、压缩率最高，但编码最耗 CPU | 低带宽、有算力 |
| **H264** | 硬件支持最广（手机几乎都有硬编） | 移动端、省电 |
| **H265** | H264 的继任，压缩更好，但授权 / 支持受限 | 特定场景 |

<Callout type="info">
  **编解码器的选择，是「压缩率 vs CPU vs 兼容性 vs 授权」的多方权衡。** 压缩率越高（AV1 > VP9 > VP8），同样画质越省带宽，但编码越吃 CPU；硬件支持越广（H264），越省电、越流畅，但可能压缩率不如新编解码器；还有专利授权的现实考量（VP8/VP9/AV1 免版税，H264/H265 有授权问题）。所以 WebRTC **不押注单一编解码器**，而是[全都支持、协商时取双方交集](https://daiw.org/manual/webrtc/media-session)——[还记得 SDP 编解码器协商吗](https://daiw.org/manual/webrtc/media-session)，两端各列支持的，取交集用。这套「抽象接口 + 多实现 + 协商选择」的架构，让 WebRTC 能随编解码器技术演进而演进，不被任何一种绑死。具体实现在 `modules/video_coding/codecs/`（vp8/vp9/av1/h264 等子目录）。
</Callout>

## 编码器输出：EncodedImage

编码器吐出的是 **`EncodedImage`**——一段压缩后的字节 + 元数据（是不是[关键帧](https://daiw.org/manual/webrtc/video-decode-recovery)、[时间戳](https://daiw.org/manual/webrtc/video-timing)、[SVC 层信息](https://daiw.org/manual/webrtc/simulcast-svc)等）。它经 `EncodedImageCallback` 回到 [`VideoStreamEncoder`](https://daiw.org/manual/webrtc/video-source-encoder)，再交给[打包](https://daiw.org/manual/webrtc/video-packetization)成 RTP。**关键帧**标记尤其重要：接收端[丢包恢复](https://daiw.org/manual/webrtc/video-decode-recovery)、新加入者起播，都要从关键帧开始。

## 小结与下一章

**`VideoEncoder`** 是统一的编码器抽象（`InitEncode` 配置、`Encode` 喂帧、**`SetRates` 设码率**——[拥塞控制闭环的落点](https://daiw.org/manual/webrtc/rate-control)），让[上层](https://daiw.org/manual/webrtc/video-source-encoder)不关心具体编解码器。由 `VideoEncoderFactory` 创建（[可换硬件编码器](https://daiw.org/manual/webrtc/factory-and-context)）。五种编解码器 **VP8 / VP9 / AV1 / H264 / H265** 各有「压缩率 vs CPU vs 兼容 vs 授权」的取舍，WebRTC 全支持、[协商取交集](https://daiw.org/manual/webrtc/media-session)。输出 `EncodedImage`（压缩字节 + [关键帧](https://daiw.org/manual/webrtc/video-decode-recovery)等元数据）。

编码器能按 `SetRates` 调码率，但**具体降到多低、是降分辨率还是降帧率**，是一套精细的自适应逻辑。下一章专讲。👉 [视频自适应](https://daiw.org/manual/webrtc/video-adaptation)。

## 参考资料

- [1] libwebrtc 源码.`api/video_codecs/video_encoder.h`（`InitEncode` / `Encode` / `SetRates`）、`video_encoder_factory.h`。
- [2] libwebrtc 源码.`modules/video_coding/codecs/`（vp8/vp9/av1/h264 实现）。
- [3] `api/video_codecs/`（各编解码器的 profile 与能力）。
