返回文章列表

第一章|数字音视频基础:面向前端工程师的音视频入门心智模型

从采样率、位深、声道、PCM、帧率、分辨率、像素格式、码率、编码和容器开始,建立前端工程师理解音视频的第一层心智模型。

第一章|数字音视频基础

面向前端工程师的音视频入门心智模型

这一章先不钻算法,也不要求你马上看懂 H.264、AAC、MP4 Box。我们先建立一个最重要的底层直觉:

音视频文件,本质上是在记录“声音随时间变化”和“画面随时间变化”。 原始数据非常巨大,所以要压缩;压缩后的数据还要和时间戳、字幕、封面、轨道信息放在一起,所以需要容器。

你后面学 WebCodecs、Web Audio、MP4 解析、音视频合成时,都会反复用到这一章的概念。


1. 本章学习目标

学完本章,你应该能讲清楚这些问题:

  1. 音频是什么? 采样率、位深、声道、PCM 分别是什么意思。

  2. 视频是什么? 帧、分辨率、帧率、像素格式分别是什么意思。

  3. 原始音视频为什么巨大? 能手算一个 1080p 视频和一段 PCM 音频的原始体积。

  4. 为什么需要编码压缩? 明白编码器是在尽量保留感知质量的前提下减少数据量。

  5. 为什么需要容器格式? 明白 MP4 不是视频编码,而是把视频、音频、字幕、元数据装起来的“盒子”。

  6. 播放器播放一个 MP4 大概做了什么? 能从“读取文件 → 解封装 → 解码 → 渲染/播放”讲完整流程。


本章速览

先把本章看成一条从现实信号到浏览器播放的链路:

数字音视频基础:面向前端工程师的音视频入门心智模型 flow 1

读图时抓住三个总结:

  • 音频和视频的原始形态都是“随时间变化的数字样本”,只是音频记录振幅,视频记录连续画面。
  • 原始 PCM、RGB、YUV 数据通常太大,编码器负责在可接受质量下把它们压缩成更小的码流。
  • 容器不负责压缩画面或声音,它负责把编码后的音频、视频、字幕、时间戳和元数据组织成一个可播放文件。

2. 音频是什么?

2.1 声音的本质:空气振动

现实世界里的声音,是空气压力随时间变化形成的波。

你可以把声音想象成一条不断起伏的曲线:

空气压力
  ^
  |        /\        /\          /\
  |       /  \      /  \        /  \
  |______/    \____/    \______/    \____> 时间

但计算机不能直接存“连续曲线”。计算机只能存数字,所以要把连续的声音切成一个个时间点来记录。

这个过程叫:

采样,Sampling


2.2 采样率:每秒记录多少次声音

采样率,Sample Rate,表示每秒钟采集多少个声音样本。

常见采样率:

采样率含义常见场景
8000 Hz每秒 8000 个样本电话语音
16000 Hz每秒 16000 个样本语音识别、会议录音
44100 Hz每秒 44100 个样本CD、音乐
48000 Hz每秒 48000 个样本视频、直播、影视制作

44.1kHz 的意思是:

每秒记录 44100 次声音的瞬时状态

类比一下:

拍视频是每秒拍很多张照片; 录音频是每秒记录很多次声音的高度。

采样率越高,能记录的声音细节越多,尤其是高频声音。但采样率越高,数据也越大。


2.3 位深:每个声音样本有多精细

位深,Bit Depth,表示每个采样点用多少 bit 来表示。

常见位深:

位深每个样本大小可表示范围常见场景
8 bit1 byte256 个等级很老的音频
16 bit2 bytes65536 个等级CD、常见 PCM
24 bit3 bytes约 1677 万等级专业录音
32-bit float4 bytes浮点数Web Audio 内部常见格式

可以把位深理解成“声音振幅的刻度精度”。

低位深:刻度少,声音变化不够细腻
高位深:刻度多,声音变化更细腻

类比图片:

图片里每个像素的颜色可以有 256 级、65536 级……
音频里每个采样点的音量也可以有不同精度。

2.4 声道:有几路声音

声道,Channel,表示同时记录几路声音。

常见声道:

声道英文含义
1mono单声道
2stereo双声道,左声道 + 右声道
65.1 surround环绕声

双声道音频可以理解为:

时间点 1:左耳一个值,右耳一个值
时间点 2:左耳一个值,右耳一个值
时间点 3:左耳一个值,右耳一个值
...

所以声道越多,数据量也越大。


2.5 PCM:最朴素的原始音频数据

PCM,Pulse Code Modulation,脉冲编码调制,可以先理解成:

没有经过 MP3、AAC 这类有损压缩的原始数字音频样本。

例如一段音频是:

44.1kHz / 16bit / stereo

意思是:

每秒 44100 个采样点
每个采样点 16 bit,也就是 2 bytes
左右两个声道

那么它每秒的数据量是:

44100 × 2 bytes × 2 channels
= 176400 bytes/s
≈ 172.27 KiB/s

换成码率:

44100 × 16 bit × 2
= 1411200 bit/s
= 1411.2 kbps

这就是为什么 CD 音质 PCM 的码率常说是 1411.2 kbps。


3. 视频是什么?

3.1 视频的本质:连续播放的图片

视频可以先粗暴理解成:

很多张图片按照固定速度连续播放。

每一张图片叫一帧:

Frame,帧

例如 30fps 的视频表示:

每秒播放 30 张图片
Frame 1 → Frame 2 → Frame 3 → ... → Frame 30
       一秒钟内连续播放

人眼看到足够快的连续图片,就会感受到运动。


3.2 分辨率:每一帧有多少像素

分辨率,Resolution,表示每一帧画面的宽高。

常见分辨率:

分辨率像素数量常见说法
1280 × 720921,600720p
1920 × 10802,073,6001080p
2560 × 14403,686,4002K / QHD
3840 × 21608,294,4004K UHD

一帧 1080p 图片有:

1920 × 1080 = 2,073,600 个像素

也就是两百多万个小点。


3.3 帧率:每秒多少帧

帧率,Frame Rate / FPS,表示每秒播放多少帧。

常见帧率:

帧率场景
24fps电影
25fps部分电视制式
30fps普通视频、会议、短视频
60fps游戏、运动视频、高流畅度场景
120fps+高刷、慢动作素材

帧率越高,动作越流畅,但数据量也越大。

例如:

1080p 30fps:每秒 30 张 1080p 图片
1080p 60fps:每秒 60 张 1080p 图片

60fps 的原始数据量几乎是 30fps 的两倍。


3.4 像素格式:每个像素怎么存颜色

一张图片由很多像素组成。每个像素要记录颜色。

最容易理解的是 RGB:

一个像素 = R + G + B
R:红色
G:绿色
B:蓝色

如果每个通道 8 bit:

R = 8 bit
G = 8 bit
B = 8 bit

一个像素 = 24 bit = 3 bytes

所以 RGB 24-bit 的一帧 1080p 图片大小是:

1920 × 1080 × 3 bytes
= 6,220,800 bytes
≈ 5.93 MiB

但真实视频编码里经常不是 RGB,而是 YUV。


3.5 RGB 和 YUV 的区别

RGB 更符合屏幕显示:

R 红
G 绿
B 蓝

YUV 更符合视频压缩。

严格说,数字视频里常说的 YUV 通常更接近 YCbCr。可以先这样理解:

Y:亮度 / 明暗信息
U / Cb:蓝色色差,表示这个像素相对亮度“偏蓝多少”
V / Cr:红色色差,表示这个像素相对亮度“偏红多少”

也就是说,U/V 不是两份独立的“颜色”,而是配合 Y 使用的两个色差信号。

为什么视频喜欢 YUV?

因为人眼对亮度更敏感,对颜色细节没那么敏感。

所以视频可以做一种聪明操作:

亮度信息多保留一点,颜色信息少存一点。

常见像素格式:

像素格式大致含义
RGB24每个像素 3 bytes,红绿蓝
RGBA每个像素 4 bytes,多一个透明度 Alpha
YUV420P亮度全量,色度降采样,视频里非常常见
NV12常见硬件解码输出格式之一

对于前端工程师来说,后面你会在这些地方遇到它们:

Canvas:常见是 RGBA
WebCodecs VideoFrame:可能涉及 I420、NV12、RGBA 等格式
编码器:常见输入/输出可能更偏 YUV

4. 原始数据为什么巨大?

我们算两个数,你会瞬间有感觉。


4.1 计算 10 秒 1080p 30fps RGB 视频的原始体积

条件:

分辨率:1920 × 1080
帧率:30fps
时长:10 秒
像素格式:RGB,每个像素 3 bytes

一帧大小:

1920 × 1080 × 3
= 6,220,800 bytes
≈ 5.93 MiB

10 秒总帧数:

30 × 10 = 300 帧

总大小:

6,220,800 × 300
= 1,866,240,000 bytes
≈ 1.87 GB
≈ 1.74 GiB

也就是说:

10 秒 1080p 30fps 的未压缩 RGB 视频,大约 1.87GB。

这还只是 10 秒。 如果是 1 分钟,就是十几 GB。 如果是 4K 60fps,那数据量直接起飞,硬盘和网络会一起哭出声。


4.2 计算 44.1kHz / 16bit / stereo / 3 分钟 PCM 音频体积

条件:

采样率:44100 Hz
位深:16 bit = 2 bytes
声道:2
时长:3 分钟 = 180 秒

每秒大小:

44100 × 2 × 2
= 176400 bytes/s

3 分钟大小:

176400 × 180
= 31,752,000 bytes
≈ 31.75 MB
≈ 30.28 MiB

所以:

3 分钟 CD 质量 PCM 音频,大约 31.75MB。

如果压成 128kbps 的 MP3:

128000 bit/s × 180 秒 ÷ 8
= 2,880,000 bytes
≈ 2.88 MB

从 31.75MB 到 2.88MB,差不多小了 11 倍。


5. 为什么需要编码压缩?

原始音视频数据太大,所以需要压缩。

这个过程叫:

编码,Encoding

编码后的数据播放时需要还原成可以播放/显示的数据,这个过程叫:

解码,Decoding

原始音视频数据 → 编码器压缩 → 编码后的音视频数据
编码后的音视频数据 → 解码器解压 → 可播放/可渲染的数据

5.1 音频压缩在压什么?

音频压缩会利用人耳特性。

例如:

  1. 人耳听不到某些特别高或特别低的频率。
  2. 一个很大的声音附近,小声音可能被掩盖。
  3. 有些重复或相近的信息可以用更少数据表示。

所以 MP3、AAC、Opus 这类编码格式会尽量保留人耳更容易感知的部分,丢掉或简化不太敏感的部分。

这类压缩通常是:

有损压缩,Lossy Compression

也就是压缩后不可能完全还原原始数据,但听起来可以很接近。


5.2 视频压缩在压什么?

视频压缩主要利用两件事:

第一,空间冗余

一帧图片内部,很多像素是相近的。

比如蓝天:

蓝 蓝 蓝 蓝 蓝 蓝 蓝 蓝
蓝 蓝 蓝 蓝 蓝 蓝 蓝 蓝
蓝 蓝 蓝 蓝 蓝 蓝 蓝 蓝

没必要每个像素都完整记录一遍。


第二,时间冗余

连续视频里,相邻帧通常很像。

比如一个人坐着说话:

第 1 帧:人坐在椅子上
第 2 帧:人还坐在椅子上,只是嘴动了一点
第 3 帧:人还坐在椅子上,只是头动了一点

那就没必要每一帧都当成完整图片存下来。

可以这样存:

第 1 帧:完整画面
第 2 帧:相对于第 1 帧变化了什么
第 3 帧:相对于前面帧变化了什么

这就是视频压缩的核心直觉。


6. 码率是什么?

码率,Bitrate,表示单位时间内使用多少 bit 来表示音视频数据。

常见单位:

kbps:kilobits per second,每秒多少千 bit
Mbps:megabits per second,每秒多少百万 bit

注意:

bit 和 byte 不一样
1 byte = 8 bit

比如一个视频码率是 5Mbps,时长 10 秒,那么大致大小是:

5,000,000 bit/s × 10s ÷ 8
= 6,250,000 bytes
≈ 6.25 MB

所以文件大小可以粗略估算:

文件大小 ≈ 码率 × 时长 ÷ 8

如果一个 MP4 里面有视频和音频:

总码率 ≈ 视频码率 + 音频码率 + 少量容器开销

7. 关键帧、GOP 是什么?

7.1 关键帧:可以独立解码的帧

视频里不是每一帧都完整保存。

通常有些帧是完整画面,可以独立解码。它叫:

关键帧,Keyframe

在 H.264 里,你也经常听到:

I 帧,Intra Frame

可以先粗略理解成:

关键帧 ≈ 一张完整图片
非关键帧 ≈ 参考其他帧,只记录变化

7.2 GOP:一组相关的视频帧

GOP,Group of Pictures,表示从一个关键帧开始的一组视频帧。

例如:

I B B P B B P B B P

也可以简化理解成:

关键帧 + 后面一串依赖它的帧

一个 GOP 可能长这样:

I 帧:完整画面
P 帧:参考前面的帧
B 帧:参考前后帧

你现在不需要深入 P 帧、B 帧算法,只要记住:

GOP 会影响压缩率、随机 seek、首帧速度、编辑切割体验。


7.3 为什么关键帧影响拖动进度条?

假设一个视频每 5 秒才有一个关键帧。

你拖到第 23 秒,播放器可能不能直接从第 23 秒开始解码,因为第 23 秒附近的帧依赖前面的关键帧。

播放器可能要:

找到第 20 秒关键帧
从第 20 秒开始解码
一直解到第 23 秒
最后显示第 23 秒画面

所以关键帧间隔太长,可能导致 seek 变慢。


8. 为什么需要容器格式?

现在我们已经有了编码后的音频和视频:

H.264 视频数据
AAC 音频数据

但问题来了:

播放器怎么知道:

  1. 这个文件里有几条轨道?
  2. 哪条是视频,哪条是音频?
  3. 视频宽高是多少?
  4. 音频采样率是多少?
  5. 每一帧的时间戳是多少?
  6. 哪些是关键帧?
  7. 字幕在哪里?
  8. 封面、标题、作者、旋转角度这些元数据在哪里?
  9. 音频和视频怎么同步?

这些信息不能靠裸编码流自己全部解决,所以需要一个“外壳”。

这个外壳就是:

容器格式,Container Format

常见容器格式:

容器常见扩展名可以装什么
MP4.mp4, .m4a, .movH.264、H.265、AAC、字幕、元数据等
WebM.webmVP8、VP9、AV1、Opus、Vorbis 等
MKV.mkv很多种视频、音频、字幕
WAV.wav常见 PCM 音频
FLV.flv直播和旧 Web 视频场景常见

容器就像快递盒:

编码数据 = 货物
容器格式 = 快递盒 + 标签 + 目录 + 时间表

MP4 里面可以装:

视频轨道:H.264 / H.265 / AV1 ...
音频轨道:AAC / MP3 / ALAC ...
字幕轨道:WebVTT / mov_text ...
元数据:时长、旋转角度、封面、标题 ...

所以一定要记住:

MP4 不是 H.264。 MP4 是容器,H.264 是视频编码格式。


9. 编码、解码、封装、解封装

这几个词非常容易混,面试也很爱问。

9.1 编码 Encoding

把原始音视频压缩成编码格式。

原始视频帧 RGB/YUV → H.264 Encoder → H.264 码流
原始音频 PCM → AAC Encoder → AAC 码流

9.2 解码 Decoding

把编码后的数据解压成可播放、可处理的原始数据。

H.264 码流 → H.264 Decoder → 视频帧 YUV/RGBA
AAC 码流 → AAC Decoder → PCM 音频

9.3 封装 Muxing

把编码后的音频、视频、字幕、元数据打包进容器。

H.264 视频 + AAC 音频 + 字幕 + 元数据
        ↓
      MP4 Muxer
        ↓
      output.mp4

9.4 解封装 Demuxing

从容器里拆出音频轨、视频轨、字幕轨和元数据。

input.mp4
   ↓
MP4 Demuxer
   ↓
H.264 视频数据
AAC 音频数据
字幕
元数据

9.5 四个概念放在一张图里

录制 / 生成阶段:

摄像头原始画面       麦克风原始声音
     ↓                  ↓
  视频帧 YUV/RGB       PCM 音频
     ↓                  ↓
  H.264 编码           AAC 编码
     ↓                  ↓
  H.264 码流           AAC 码流
          \            /
           \          /
            MP4 封装
               ↓
            output.mp4


播放阶段:

            input.mp4
               ↓
            MP4 解封装
           /          \
          /            \
  H.264 码流           AAC 码流
     ↓                  ↓
  H.264 解码           AAC 解码
     ↓                  ↓
  视频帧 YUV/RGBA      PCM 音频
     ↓                  ↓
  Canvas/Video 渲染    Audio 输出

10. 音频、视频、字幕、元数据如何组成一个媒体文件?

一个 MP4 文件可以粗略理解成这样:

movie.mp4
├── 文件类型信息
├── 全局元数据
│   ├── 时长
│   ├── 创建时间
│   ├── 兼容品牌
│   └── 封面 / 标题 / 作者等
├── 视频轨道
│   ├── 编码格式:H.264
│   ├── 分辨率:1920 × 1080
│   ├── 帧率:30fps
│   ├── 关键帧位置
│   ├── 每个 sample 的时间戳
│   └── 编码后的视频数据位置
├── 音频轨道
│   ├── 编码格式:AAC
│   ├── 采样率:48000Hz
│   ├── 声道数:2
│   ├── 每个 sample 的时间戳
│   └── 编码后的音频数据位置
├── 字幕轨道,可选
└── 真正的媒体数据

这里有一个重要词:

Track,轨道

一个媒体文件里可以有多个轨道:

视频轨道
音频轨道 1:中文
音频轨道 2:英文
字幕轨道 1:中文字幕
字幕轨道 2:英文字幕

还有一个重要词:

Sample,样本

在 MP4 语境里,sample 可以粗略理解成轨道里的一个媒体单元。

对于视频:

一个 sample 通常对应一帧压缩后的视频数据

对于音频:

一个 sample 通常对应一小段压缩后的音频数据

注意,MP4 里的 sample 和音频采样点 sample 不是一个层面的概念。这个点很容易混。


11. 播放器播放一个 MP4 的完整流程

假设浏览器要播放一个 MP4:

<video src="demo.mp4" controls></video>

表面上你只写了一行 HTML,但底层大概经历了这些步骤。


11.1 第一步:读取文件或网络数据

播放器先获取 MP4 数据:

本地文件
或者
HTTP 请求返回的数据

如果是在线播放,播放器不会总是等整个文件下载完才播放,而是边下边分析。


11.2 第二步:解析容器

播放器需要先看 MP4 容器结构,找到:

文件类型
有哪些轨道
每条轨道是什么 codec
视频宽高
音频采样率
时长
关键帧位置
sample 的 offset 和 size
时间戳信息

这一阶段叫:

Demuxing,解封装

11.3 第三步:取出编码后的音视频数据

从 MP4 里拆出:

H.264 视频 sample
AAC 音频 sample

注意,这时候拆出来的还不能直接显示或播放。

H.264 还是压缩数据。 AAC 也是压缩数据。


11.4 第四步:送入解码器

播放器把压缩数据送给对应解码器:

H.264 Decoder → 输出视频帧
AAC Decoder → 输出 PCM 音频

视频解码后可能是:

YUV 视频帧

音频解码后通常是:

PCM 音频样本

11.5 第五步:音视频同步

视频有视频时间戳,音频有音频时间戳。

播放器要根据时间戳同步播放:

第 10.000 秒应该显示哪一帧?
第 10.000 秒应该播放哪一段音频?

通常音频时钟比较稳定,播放器常常以音频播放进度作为主时钟,让视频帧跟着音频走。


11.6 第六步:渲染画面,播放声音

最后:

视频帧 → GPU / 渲染管线 → 屏幕
PCM 音频 → 音频设备 → 扬声器 / 耳机

你看到画面,听到声音。


11.7 文字版流程图

用户打开 MP4
    ↓
读取文件 / 网络数据
    ↓
解析 MP4 容器
    ↓
获取轨道信息
    ├── 视频轨:codec、宽高、帧率、时间戳、关键帧
    └── 音频轨:codec、采样率、声道、时间戳
    ↓
解封装 Demux
    ├── 拆出 H.264 / H.265 / AV1 等视频码流
    └── 拆出 AAC / MP3 / Opus 等音频码流
    ↓
解码 Decode
    ├── 视频码流 → 原始视频帧 YUV/RGBA
    └── 音频码流 → PCM 音频
    ↓
音视频同步
    ↓
渲染视频帧 + 输出音频
    ↓
用户看到画面,听到声音

12. 必须掌握的术语表

术语英文一句话解释
采样率Sample Rate每秒记录多少个音频采样点
位深Bit Depth每个音频采样点用多少 bit 表示
声道Channel有几路声音,比如 mono、stereo
PCMPulse Code Modulation原始数字音频数据
帧Frame视频中的一张画面
分辨率Resolution每帧画面的宽高像素数
帧率FPS每秒播放多少帧
像素格式Pixel Format像素颜色数据的存储方式,如 RGB、YUV
码率Bitrate每秒使用多少 bit 表示音视频数据
编码Encoding把原始音视频压缩成编码数据
解码Decoding把编码数据还原成可播放数据
容器Container装音频、视频、字幕、元数据的文件格式
封装Muxing把音视频轨道打包进容器
解封装Demuxing从容器里拆出音视频轨道
CodecCodec编码器/解码器,也常指编码格式
KeyframeKeyframe可以独立解码的视频帧
GOPGroup of Pictures从关键帧开始的一组相关视频帧
TrackTrack媒体文件中的一条轨道,如视频轨、音频轨
SampleSample轨道中的一个媒体单元,语境不同含义不同

13. 和真实工程的关系

这些概念不是背诵用的,前端音视频工程里会经常遇到。

13.1 WebCodecs

WebCodecs 直接暴露底层编码/解码能力。

你会接触到:

VideoEncoder
VideoDecoder
AudioEncoder
AudioDecoder
VideoFrame
AudioData
EncodedVideoChunk
EncodedAudioChunk

这时候你必须知道:

VideoFrame 是原始视频帧
AudioData 是原始音频数据
EncodedVideoChunk 是编码后的视频数据
EncodedAudioChunk 是编码后的音频数据

也就是说,WebCodecs 正好对应这一章讲的:

编码 Encoding
解码 Decoding
原始帧
编码帧
时间戳
关键帧
codec

13.2 Web Audio

Web Audio 处理的是音频图和 PCM 数据。

你会遇到:

AudioContext
AudioBuffer
AudioBufferSourceNode
GainNode
AnalyserNode
AudioWorklet

Web Audio 里非常重要的概念是:

采样率
声道
PCM
音频时间
音频节点

比如你要做可视化频谱、音量分析、混音、变速、音效处理,这一章的音频基础都逃不掉。


13.3 Canvas 和视频帧处理

如果你做浏览器端视频处理,比如:

视频截图
滤镜
水印
逐帧处理
视频合成
AI 预处理

你会经常把视频帧画到 Canvas 上:

ctx.drawImage(video, 0, 0);
const imageData = ctx.getImageData(0, 0, width, height);

这时你拿到的通常是 RGBA 像素数据:

R G B A R G B A R G B A ...

所以你得知道:

分辨率决定像素数量
像素格式决定每个像素占多少 bytes
帧率决定每秒处理多少帧

13.4 MP4 解析和封装

后面学 MP4 时,你会看到:

ftyp
moov
mdat
trak
stbl
stts
stsz
stco
stss

这些东西的目的其实就是回答:

文件里有什么轨道?
每个 sample 在哪里?
每个 sample 多大?
每个 sample 应该什么时候播放?
哪些 sample 是关键帧?

所以 MP4 不只是“装数据”,它还要提供播放所需的目录和时间表。


14. 常见误区

误区 1:MP4 就是 H.264

不对。

MP4 是容器格式。
H.264 是视频编码格式。

一个 MP4 里可以装 H.264 视频,也可以装 H.265、AV1 等其他视频编码。只是浏览器和设备不一定都支持。


误区 2:视频文件后缀一样,就一定能播放

不一定。

两个文件都叫 .mp4,里面的编码可能不同:

A.mp4:H.264 + AAC
B.mp4:H.265 + AC-3

浏览器可能能播 A,但播不了 B。

所以判断能不能播放,要看:

容器格式 + codec + profile + level + 浏览器/系统支持

误区 3:帧率越高一定越好

不一定。

60fps 比 30fps 更流畅,但也意味着:

数据更多
编码压力更大
解码压力更大
耗电更多
带宽更高

对于电影、课程、会议、短视频,不同场景有不同取舍。


误区 4:码率越高一定越清晰

大多数情况下,码率高有助于画质,但不是唯一因素。

画质还受这些影响:

编码格式
编码器质量
分辨率
帧率
内容复杂度
GOP 设置
是否多次转码

同样 5Mbps,H.265 或 AV1 可能比 H.264 更清晰,但解码兼容性和性能又是另一个问题。


误区 5:解封装就是解码

不对。

解封装:从容器里拆出压缩数据。
解码:把压缩数据还原成原始音视频。

比如:

MP4 解封装 → 得到 H.264 和 AAC
H.264 解码 → 得到视频帧
AAC 解码 → 得到 PCM

15. 面试可能怎么问

问题 1:音频里的采样率和位深分别是什么意思?

参考回答:

采样率表示每秒采集多少个音频样本,比如 44.1kHz 表示每秒 44100 个采样点。位深表示每个采样点用多少 bit 表示,比如 16bit 表示每个采样点占 2 bytes。采样率影响能记录的频率范围,位深影响振幅精度和动态范围。再乘以声道数和时长,就可以算出 PCM 原始音频大小。


问题 2:为什么原始视频数据很大?

参考回答:

因为视频本质上是连续图片。比如 1080p 一帧有 1920×1080 个像素,如果用 RGB,每个像素 3 bytes,一帧大约 6MB。30fps 每秒 30 帧,10 秒就接近 1.87GB。所以必须通过 H.264、H.265、AV1 这类视频编码压缩。


问题 3:MP4 和 H.264 有什么区别?

参考回答:

MP4 是容器格式,负责把视频、音频、字幕、元数据以及时间戳等信息组织在一个文件里。H.264 是视频编码格式,负责压缩视频画面。一个 MP4 文件里可以装 H.264 视频加 AAC 音频,也可以装其他编码。浏览器能播放 MP4,不代表能播放所有 MP4,还要看里面具体 codec 是否支持。


问题 4:封装和编码有什么区别?

参考回答:

编码是把原始音视频数据压缩成编码数据,比如把 YUV 视频帧编码成 H.264,把 PCM 音频编码成 AAC。封装是把这些编码后的音视频数据,以及时间戳、轨道、字幕、元数据等信息打包进容器,比如 MP4。播放时反过来,先解封装,再解码。


问题 5:关键帧有什么用?

参考回答:

关键帧是可以独立解码的视频帧,通常相当于一张完整画面。非关键帧往往依赖前后帧,只记录变化。关键帧影响随机 seek、首帧速度、剪辑切割和压缩率。关键帧间隔太长,压缩率可能更好,但拖动进度条可能更慢。


16. 实践任务

任务 1:计算 10 秒 1080p 30fps RGB 视频原始体积

条件:

width = 1920
height = 1080
fps = 30
duration = 10
bytesPerPixel = 3

公式:

size = width × height × bytesPerPixel × fps × duration

JavaScript 代码:

const width = 1920;
const height = 1080;
const fps = 30;
const duration = 10;
const bytesPerPixel = 3;

const bytes = width * height * bytesPerPixel * fps * duration;
const mb = bytes / 1000 / 1000;
const gib = bytes / 1024 / 1024 / 1024;

console.log(`bytes: ${bytes}`);
console.log(`MB: ${mb.toFixed(2)} MB`);
console.log(`GiB: ${gib.toFixed(2)} GiB`);

输出大约是:

bytes: 1866240000
MB: 1866.24 MB
GiB: 1.74 GiB

任务 2:计算 44.1kHz / 16bit / stereo / 3 分钟 PCM 音频体积

条件:

sampleRate = 44100
bitDepth = 16
channels = 2
duration = 180

公式:

size = sampleRate × bitDepth/8 × channels × duration

JavaScript 代码:

const sampleRate = 44100;
const bitDepth = 16;
const channels = 2;
const duration = 180;

const bytesPerSample = bitDepth / 8;
const bytes = sampleRate * bytesPerSample * channels * duration;

const mb = bytes / 1000 / 1000;
const mib = bytes / 1024 / 1024;

console.log(`bytes: ${bytes}`);
console.log(`MB: ${mb.toFixed(2)} MB`);
console.log(`MiB: ${mib.toFixed(2)} MiB`);

输出大约是:

bytes: 31752000
MB: 31.75 MB
MiB: 30.28 MiB

任务 3:估算压缩后文件大小

假设一段 3 分钟 MP3 是 128kbps:

const bitrate = 128_000; // bit/s
const duration = 180;

const bytes = bitrate * duration / 8;
const mb = bytes / 1000 / 1000;

console.log(`${mb.toFixed(2)} MB`);

输出:

2.88 MB

对比前面的 PCM:

PCM:约 31.75 MB
MP3 128kbps:约 2.88 MB

压缩后小很多,是因为 MP3 会利用人耳感知特性,丢弃或简化不太容易听出来的信息。


任务 4:用 Canvas 理解一帧视频的像素数据

你可以用 Canvas 读取一张图片或视频帧的 RGBA 数据:

<video id="video" src="demo.mp4" controls></video>
<canvas id="canvas"></canvas>

<script>
const video = document.querySelector('#video');
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');

video.addEventListener('loadeddata', () => {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;

  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

  console.log('width:', imageData.width);
  console.log('height:', imageData.height);
  console.log('data length:', imageData.data.length);
  console.log('bytes per pixel:', imageData.data.length / (imageData.width * imageData.height));
});
</script>

你会看到:

data.length = width × height × 4

因为 Canvas 的 ImageData 通常是 RGBA:

R G B A

每个像素 4 bytes。


任务 5:用 AudioContext 看采样率

<button id="btn">Start AudioContext</button>

<script>
document.querySelector('#btn').addEventListener('click', async () => {
  const audioContext = new AudioContext();

  console.log('sampleRate:', audioContext.sampleRate);
  console.log('currentTime:', audioContext.currentTime);
});
</script>

你可能会看到:

sampleRate: 44100

或者:

sampleRate: 48000

不同设备、浏览器、音频输出环境可能不同。


17. 自测题

题 1:44.1kHz 的音频表示什么?

答案:

表示每秒采集 44100 个音频样本。采样率越高,每秒记录的声音点越多,能表示的声音细节通常越多,但数据量也越大。


题 2:16bit stereo PCM,每秒有多少 bytes?

已知:

sampleRate = 44100
bitDepth = 16bit = 2 bytes
channels = 2

计算:

44100 × 2 × 2 = 176400 bytes/s

答案:

每秒 176400 bytes,约 172.27 KiB/s。


题 3:1080p RGB 一帧大约多大?

已知:

1920 × 1080
RGB = 3 bytes/pixel

计算:

1920 × 1080 × 3
= 6,220,800 bytes
≈ 5.93 MiB

答案:

一帧大约 6.22MB,或者 5.93MiB。


题 4:MP4 和 H.264 是什么关系?

答案:

MP4 是容器格式,H.264 是视频编码格式。MP4 可以装 H.264 视频和 AAC 音频,也可以装其他编码。判断一个 MP4 能不能播放,不能只看 .mp4 后缀,还要看里面的 codec。


题 5:为什么播放器要先解封装再解码?

答案:

因为 MP4 这类容器里面同时包含视频、音频、字幕、元数据和时间戳信息。播放器需要先通过解封装找到各个轨道,拆出压缩后的视频码流和音频码流,然后再分别送给对应的解码器。解封装解决“数据在哪里、什么时候播放”的问题,解码解决“如何把压缩数据还原成画面和声音”的问题。


18. 本章总结

这一章你要带走几个核心模型。

音频模型

声音 → 采样 → PCM

音频大小由这些因素决定:

采样率 × 位深 × 声道数 × 时长

例如:

44.1kHz / 16bit / stereo / 3 分钟 PCM ≈ 31.75MB

视频模型

视频 = 很多帧连续播放

视频大小由这些因素决定:

分辨率 × 每像素字节数 × 帧率 × 时长

例如:

10 秒 1080p 30fps RGB ≈ 1.87GB

压缩模型

原始音频 PCM → 音频编码器 → AAC / MP3 / Opus
原始视频帧 → 视频编码器 → H.264 / H.265 / AV1

编码压缩的目标是:

尽量保持主观质量
尽量减少数据量

容器模型

容器 = 音视频数据 + 字幕 + 元数据 + 时间戳 + 轨道目录

MP4 是容器,不是视频编码。

MP4 里面可以有:
H.264 视频
AAC 音频
字幕
封面
时间戳
轨道信息

播放流程模型

读取 MP4
  ↓
解析容器
  ↓
解封装
  ↓
解码音视频
  ↓
音视频同步
  ↓
渲染画面 + 播放声音

19. 后面学习 WebCodecs / Web Audio 会用到哪些概念?

WebCodecs 会用到

VideoFrame
AudioData
EncodedVideoChunk
EncodedAudioChunk
timestamp
key frame
codec
encoder
decoder
pixel format

你需要知道:

VideoFrame 是原始视频帧
EncodedVideoChunk 是编码后的视频 chunk
AudioData 是原始音频数据
EncodedAudioChunk 是编码后的音频 chunk

Web Audio 会用到

PCM
sampleRate
channel
AudioBuffer
AudioContext
AudioNode
AudioWorklet

你需要知道:

Web Audio 主要处理原始音频数据和音频处理图

MP4 解析会用到

container
track
sample
timestamp
duration
keyframe
demuxing
muxing

你需要知道:

MP4 的核心价值是组织音视频轨道、sample 位置、时间戳和元数据。

20. 下一章衔接

下一章要解决一个前端音视频新人最容易混的问题:

容器格式和编码格式到底有什么区别?

你会系统区分这些词:

MP4
WebM
MKV
MP3
AAC
H.264
H.265
AV1
Opus
PCM

尤其要把这句话真正吃透:

.mp4 不等于 H.264
.mp3 不等于万能音频容器
浏览器支持 MP4 不代表支持所有 MP4 文件

下一章会重点讲:

Container
Codec
Muxer
Demuxer
Encoder
Decoder
MIME type
codec string

学完之后,你就能比较自然地回答面试高频问题:

“MP4 和 H.264 有什么区别?”