# 音频管线总览 · 比视频更精细的实时

> 音频数据量小，但对延迟和瑕疵更敏感——丢一小段、飘一下都刺耳。这一章画出音频的发送/接收管线：采集→APM 处理→编码→传输→NetEq→解码→播放，介绍 AudioSendStream/ReceiveStream、ACM，以及 WebRTC 音频的两颗明珠 NetEq 和 AEC3。

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

# 音频管线总览 · 比视频更精细的实时

[视频讲完](https://daiw.org/manual/webrtc/video-decode-recovery)，进入音频。别以为音频比视频简单——它数据量小，但**对延迟和瑕疵的敏感度更高**：画面卡一下能忍，声音断一下、飘一下、带回声，立刻刺耳。第 7 部分（`modules/audio_coding/`、`modules/audio_processing/`）拆解音频管线，它藏着 WebRTC 最精妙的两个模块：**NetEq** 和 **AEC3**。

## 两条管线

音频也有**发送**和**接收**两条管线：

```mermaid
flowchart LR
    subgraph SEND["发送侧"]
        MIC["麦克风采集"] --> APM["APM 处理<br/>(回声消除/降噪/增益)"]
        APM --> AENC["编码(Opus)"]
        AENC --> APACK["打包 RTP"]
    end
    APACK -->|"传输(第3-5部分)"| NET["网络"]
    NET --> RECV
    subgraph RECV["接收侧"]
        NEQ["NetEq<br/>抖动缓冲+丢包隐藏"] --> ADEC["解码"]
        ADEC --> SPK["播放"]
    end
```

- **发送**：麦克风采集 → **[APM](https://daiw.org/manual/webrtc/apm-overview)**（音频处理：[回声消除](https://daiw.org/manual/webrtc/aec3-echo-problem)、降噪、增益——让你的声音干净）→ [编码](https://daiw.org/manual/webrtc/audio-codecs)（主用 Opus）→ [打包传输](https://daiw.org/manual/webrtc/rtp-packet)。
- **接收**：[收包](https://daiw.org/manual/webrtc/rtp-demuxer) → **[NetEq](https://daiw.org/manual/webrtc/neteq-overview)**（自适应抖动缓冲 + 丢包隐藏）→ [解码](https://daiw.org/manual/webrtc/audio-codecs) → 播放。

## 核心对象：AudioSendStream / AudioReceiveStream

管线的编排者，是 `audio/` 下的两个 stream 对象：

- **`AudioSendStream`**(`audio/audio_send_stream.cc`)—— 发送侧编排，持有 `ChannelSend`。
- **`AudioReceiveStream`** —— 接收侧编排，持有 `ChannelReceive`。

它们和视频的 [`VideoStreamEncoder`/`VideoReceiveStream2`](https://daiw.org/manual/webrtc/video-pipeline-overview) 平行。中间的**音频编解码**由 **ACM（Audio Coding Module，`modules/audio_coding/`）** 统管——它像[视频的编解码器抽象层](https://daiw.org/manual/webrtc/video-encoder-abstraction)，把 [Opus 等编解码器](https://daiw.org/manual/webrtc/audio-codecs)接进来。

## 音频为什么“另有一套”

音频和视频面对**同一类问题**（[丢包、抖动](https://daiw.org/manual/webrtc/rtp-packet)），但**解法迥异**，值得先点明：

<Callout type="info">
  **音频和视频对“丢包 / 抖动”的应对完全不同，因为两者的“瑕疵”性质不同。**

  - **视频**：丢包 → [花屏 / 冻结](https://daiw.org/manual/webrtc/video-decode-recovery)，靠[重传 / FEC / 关键帧](https://daiw.org/manual/webrtc/nack-rtx)恢复。视频帧大、[有依赖链](https://daiw.org/manual/webrtc/frame-reference-finder)。
  - **音频**：丢包 → **断音 / 卡顿**。音频包小、密（每 20ms 一个）、[帧间依赖弱](https://daiw.org/manual/webrtc/audio-codecs)。这让音频有独特的招数——**[丢包隐藏（PLC）](https://daiw.org/manual/webrtc/neteq-plc)**：丢了一小段，可以**凭前后的声音“编造”出一段以假乱真的填充**（语音有很强的短时可预测性），听感上几乎无缝。视频没法这么“编”（编出来就是花屏）。

  这就是为什么音频接收侧有一个专门的、极其精妙的模块——**[NetEq](https://daiw.org/manual/webrtc/neteq-overview)**，它把“抖动缓冲 + 丢包隐藏 + 时间伸缩”融为一体，是[视频抖动缓冲](https://daiw.org/manual/webrtc/video-jitter-buffer)的音频对应物，但精细得多。而发送侧，音频有一个视频完全没有的难题——**[回声](https://daiw.org/manual/webrtc/aec3-echo-problem)**（扬声器的声音被麦克风录回去），由 **[AEC3](https://daiw.org/manual/webrtc/aec3-internals)** 消除。NetEq 和 AEC3，是本部分的两座高峰。
</Callout>

## 本部分路线

第 7 部分分三段走：

1. **编解码**：[Opus 与编解码器抽象](https://daiw.org/manual/webrtc/audio-codecs) → [ACM](https://daiw.org/manual/webrtc/acm)。
2. **接收侧的 NetEq**：[总览](https://daiw.org/manual/webrtc/neteq-overview) → [缓冲与延迟](https://daiw.org/manual/webrtc/neteq-buffer-delay) → [六种操作](https://daiw.org/manual/webrtc/neteq-operations) → [丢包隐藏](https://daiw.org/manual/webrtc/neteq-plc) → [时间伸缩](https://daiw.org/manual/webrtc/neteq-timestretch)。
3. **发送侧的 APM**：[总览](https://daiw.org/manual/webrtc/apm-overview) → [回声问题](https://daiw.org/manual/webrtc/aec3-echo-problem) → [AEC3 内核](https://daiw.org/manual/webrtc/aec3-internals) → [增益 AGC](https://daiw.org/manual/webrtc/agc) → [降噪与 VAD](https://daiw.org/manual/webrtc/ns-vad) → [设备与混音](https://daiw.org/manual/webrtc/audio-device-mixer)。

## 小结与下一章

音频有**发送**（[采集→APM 处理→编码](https://daiw.org/manual/webrtc/apm-overview)）和**接收**（[NetEq→解码→播放](https://daiw.org/manual/webrtc/neteq-overview)）两条管线，由 **`AudioSendStream`/`AudioReceiveStream`** 编排，**ACM** 统管[编解码](https://daiw.org/manual/webrtc/audio-codecs)。音频对**延迟和瑕疵更敏感**，但因音频包小密、[帧间依赖弱](https://daiw.org/manual/webrtc/audio-codecs)，有独特招数——**[丢包隐藏](https://daiw.org/manual/webrtc/neteq-plc)**（凭上下文编造填充）。两座高峰：接收侧的 **[NetEq](https://daiw.org/manual/webrtc/neteq-overview)**（抖动缓冲 + PLC + 时间伸缩）、发送侧的 **[AEC3](https://daiw.org/manual/webrtc/aec3-internals)**（回声消除）。

先从“声音怎么被压缩”讲起——Opus 与音频编解码器抽象。👉 [音频编解码器](https://daiw.org/manual/webrtc/audio-codecs)。

## 参考资料

- [1] libwebrtc 源码.`audio/audio_send_stream.cc`、`audio_receive_stream.cc`、`channel_send.cc`、`channel_receive.cc`。
- [2] libwebrtc 源码.`modules/audio_coding/`（ACM/NetEq）、`modules/audio_processing/`（APM）。
- [3] libwebrtc 源码.`modules/audio_coding/neteq/g3doc/index.md`。
