返回学习

学习 2026

啊鸡入坑音视频之《音频格式篇》

从声音如何变成 PCM 出发,拆清 Encode、Decode、Mux、Demux、Codec 与 Container 的边界,并用播放、转码和故障定位串起完整媒体链路。

音频多媒体Codec
本文目录8
  1. 1. 声音如何变成数字音频
  2. 2. Encode 与 Decode 做了什么
  3. 3. Mux 与 Demux 为什么不是编解码
  4. 4. 一条完整的播放链路
  5. 5. Remux 与 Transcode 的区别
  6. 6. Frame、Packet 与时间戳怎样配合
  7. 7. 工程沟通中怎样避免歧义
  8. 8. 用一条链路记住所有概念

音视频基础系列(一):下一篇是啊鸡入坑音视频之《流媒体封装篇》

“这个 SDK 支持 MP4 解码吗?”

这句话在日常沟通里完全听得懂,但如果拿来设计接口或定位故障,问题就来了:MP4 是容器,不是编解码器;打开一个 MP4,通常需要先解封装,再分别解码其中的视频和音频。所谓“MP4 解码”,实际可能同时涉及 MP4 Demux、H.264 / H.265 Decode 和 AAC Decode。

音频开发里,许多混乱都来自把不同层次统称为“格式”或“编解码”。只要先拆开三类对象,整条链路就会清楚很多:

  • Raw Data:尚未压缩的媒体数据,音频常见 PCM,视频常见 YUV 或 RGB;
  • Codec:决定媒体数据如何编码和解码,例如 AAC、Opus、H.264、H.265;
  • Container:决定不同码流、时间戳和元数据如何组织,例如 MP4、MKV、Ogg、WAV。

一句话概括:Codec 负责内容如何压缩,Container 负责内容如何装在一起。

Raw Data、Codec 与 Container 的往返关系

1. 声音如何变成数字音频

现实中的声音是连续变化的模拟信号。麦克风将声波转换为电信号,再通过 ADC(Analog-to-Digital Converter,模数转换器)进行采样,得到数字音频。

text
现实声音
  ↓
麦克风
  ↓
模拟电信号
  ↓ ADC
PCM Samples

PCM(Pulse Code Modulation,脉冲编码调制)是最常见的原始数字音频表示。它本身并不只由一个名称决定,至少还要说明三个参数:

  1. Sample Rate(采样率):每秒采多少次,例如 8 kHz、16 kHz、44.1 kHz、48 kHz;
  2. Sample Format / Bit Depth(采样格式 / 位深):每个采样怎样表示,例如 S16、S16LE、S32、Float;
  3. Channel / Channel Layout(声道 / 声道布局):Mono、Stereo、5.1、7.1 等。

比如 48 kHz / Stereo / S16LE 表示每秒每个声道采样 48,000 次,每次使用 16 位有符号小端整数,并包含左右两个声道。

PCM 的数据量可以直接计算:

text
码率 = 采样率 × 位深 × 声道数

48 kHz / 16 bit / Stereo 为例:

text
48,000 × 16 × 2 = 1,536,000 bit/s

也就是 1536 kbps,约 192 KB/s、11.5 MB/min。这个体积说明了为什么实时传输和长期存储通常不能直接使用原始 PCM,而需要 Codec 压缩。

采样率、位深和声道共同决定 PCM 码率

2. Encode 与 Decode 做了什么

编码(Encode)把 Raw Data 转成编码码流,解码(Decode)再把编码码流恢复为可播放或处理的 Raw Data:

text
PCM
 ↓ Encode
AAC / Opus / MP3
 ↓ Decode
PCM

Codec 是 Coder / Decoder 的合称,通常包含编码和解码所遵循的规则。常见音频 Codec 包括:

Codec类型常见场景
AAC有损视频、录像、流媒体
Opus有损WebRTC、实时语音、视频会议、对讲
G.711有损电话、SIP、IPC、传统对讲设备
MP3有损音乐分发与高兼容性播放
FLAC / ALAC无损音乐存档、编辑与高质量归档

无损编码要求解码后的 PCM 与原始 PCM 一致;有损编码则会借助心理声学模型,舍弃人耳不敏感的信息,以更低码率换取可接受的听感。

同样是 64 kbps,不同 Codec 的听感也可能完全不同。因此,码率只能描述每秒使用多少 bit,不能脱离 Codec、内容类型和编码参数直接比较质量。

3. Mux 与 Demux 为什么不是编解码

编码得到的只是码流。实际文件还需要保存轨道、时间戳、字幕和元数据,这些内容由 Container 组织。

例如,一个 MP4 可以包含:

text
MP4
├── Video Track: H.265
├── Audio Track: AAC
├── Subtitle Track
└── Metadata

把这些内容写入容器叫 Mux(Multiplexing,封装或复用);从容器拆出各条码流叫 Demux(Demultiplexing,解封装或解复用)。

text
H.265 Video + AAC Audio
          ↓ Mux
           MP4
          ↓ Demux
H.265 Video + AAC Audio

因此,严格定义下有两组独立动作:

text
Encode / Decode 处理 Raw Data 与 Codec Bitstream 的转换
Mux / Demux       处理 Codec Bitstream 与 Container 的组织

常见文件扩展名也不能单独证明内部 Codec:

扩展名Container常见 Codec
.mp4MP4H.264 / H.265 + AAC
.m4aMP4AAC / ALAC
.mkvMatroskaH.264 / H.265 / AV1 + AAC / Opus
.webmWebMVP9 / AV1 + Opus
.oggOggVorbis / Opus
.wavRIFF/WAVEPCM 最常见,但并非只能装 PCM

M4A 不等于 AAC,Ogg 不等于 Opus,WAV 也不严格等于 PCM。它们之所以经常被画上等号,只是因为某些组合非常常见。

没有放入 Container 的单一编码流通常称为 Elementary Stream(ES,基本流或裸流),例如裸 AAC、裸 H.264。播放器从容器中 Demux 出来的编码数据块通常称为 Packet;Decoder 消费 Packet 后输出 Frame。音频 Frame 通常是一段连续 Samples,而不是一张“画面”。

4. 一条完整的播放链路

播放媒体文件时,数据会经过下面几层:

text
File / Network
      ↓
   Demuxer
      ↓
Encoded Audio Packet
      ↓
   Decoder
      ↓
     PCM
      ↓
Resample / Convert
      ↓
Audio Buffer
      ↓
Audio Renderer
      ↓
OS Audio API
      ↓
Speaker

音频从文件或网络到扬声器的播放链路

Decoder 输出的 PCM 不一定符合播放设备要求。例如,来源可能是 16 kHz / Mono / S16,设备却要求 48 kHz / Stereo / Float。这时还需要做:

  • Sample Rate Conversion;
  • Sample Format Conversion;
  • Channel Layout Conversion。

FFmpeg 中,这类工作通常由 libswresample 完成。到了系统层,iOS / macOS 常见 Core Audio、AVAudioEngine,Android 常见 AudioTrack、AAudio,Windows 常见 WASAPI。

实时语音链路还可能在编码前加入:

  • AEC(Acoustic Echo Cancellation):减少扬声器声音被麦克风再次录入形成的回声;
  • NS(Noise Suppression):抑制风扇声、环境声等背景噪声;
  • AGC(Automatic Gain Control):自动调整输入增益,让音量保持在更可用的范围。

一个双向对讲上行链路可能是:

text
Microphone → PCM → AEC / NS / AGC
→ Opus / G.711 Encode → Network
→ Decode → PCM → Speaker

这里网络传输层还可能涉及 RTP、RTSP 或私有协议。它们不属于 Codec,却同样决定数据怎样分包、传输和恢复。

5. Remux 与 Transcode 的区别

如果只改变 Container,而不改变内部 Codec,这个过程叫 Remux(重新封装):

text
MKV (H.264 + AAC)
 ↓ Demux
H.264 + AAC
 ↓ Mux
MP4 (H.264 + AAC)

Remux 不需要重新编码,通常速度快、CPU 消耗低,也不会引入有损重编码造成的质量下降。但目标 Container 必须能够承载原来的 Codec 和相关参数。

Transcode(转码)则要从一种 Codec 转换为另一种 Codec:

text
AAC
 ↓ Decode
PCM
 ↓ Encode
Opus

或者:

text
H.264
 ↓ Decode
YUV
 ↓ Encode
H.265

转码需要 Decode 和 Encode,成本更高;如果输入和输出都是有损 Codec,还可能进一步损失质量。

所以,当需求只是“把 MKV 变成 MP4”时,第一步不是立即转码,而是先确认现有码流能否直接 Remux。能不重新编码,就不要重新编码。

Remux 与 Transcode 的处理链路和成本对比

6. Frame、Packet 与时间戳怎样配合

音频和视频并不是一帧对一帧播放。假设视频是 30 fps,每帧约 33.3 ms;AAC 在 48 kHz 下常见每帧 1024 samples,每帧约 21.3 ms。两者天然不等长,只能依靠同一时间轴同步。

这里最重要的两个时间戳是:

  • PTS(Presentation Timestamp):这一帧应该何时播放或显示;
  • DTS(Decoding Timestamp):这一帧应该何时送入 Decoder。

视频存在 B Frame 时,解码顺序和显示顺序可能不同,因此 PTS 与 DTS 可能不同。音频通常简单一些,但仍然需要 PTS、Timeline 和 Clock 与视频同步。

这也解释了为什么 Container 不只是“装东西的文件壳”:它还负责保存轨道、时序和同步所需的信息。只有 Codec 而没有正确的时间戳,播放器依旧可能出现音画不同步、跳帧或缓冲异常。

7. 工程沟通中怎样避免歧义

日常交流中,“编解码模块”泛指完整媒体处理能力很常见,没有必要逐句纠正。但进入技术方案、接口命名、性能分析和故障定位后,应明确使用具体阶段:

text
Demux → Decode → Process → Encode → Mux

例如,“文件打不开”至少还要继续问:

  1. Container 是否受支持?
  2. Demux 是否成功识别轨道和时间戳?
  3. 内部 Codec 是否受支持?
  4. Decoder 是否初始化成功?
  5. Bitstream 是否损坏或缺少必要参数?
  6. 解码后的格式转换和 Renderer 是否正常?

同样,“MP4 解码失败”也可能实际发生在 Demux 阶段;“编码成 MP4”通常包含视频编码、音频编码和 MP4 Mux。把问题定位到正确层次,才能找到正确模块和指标。

8. 用一条链路记住所有概念

最后,把核心关系压缩成一条往返链路:

text
Raw Media
  PCM / YUV
      ↓ Encode
Codec Bitstream
  AAC / Opus / H.264 / H.265
      ↓ Mux
Container
  MP4 / MKV / Ogg / WAV
      ↓ Demux
Codec Bitstream
      ↓ Decode
Raw Media
  PCM / YUV

只需要记住三个边界:

  • PCM / YUV 是原始数据;
  • AAC、Opus、H.264、H.265 是 Codec;
  • MP4、MKV、Ogg、WAV 是 Container。

Encode / Decode 解决“如何压缩与恢复”,Mux / Demux 解决“如何组织与拆分”。口头上可以把它们统称为媒体处理,落到设计和排错时,则应该把每一层写清楚。

返回首页
下一篇啊鸡入坑音视频之《流媒体封装篇》

Discussion

留言与讨论

想法、补充和不同意见都欢迎。