本篇深入探讨视频在浏览器中是如何从二进制数据变成画面的,涵盖播放链路、同步机制以及核心 API 的使用。
一、 视频播放链路(Pipeline)
一个完整的视频播放过程通常经历以下四个步骤:
- 解封装 (Demuxing) :从容器(如 MP4)中分离出视频压缩流和音频压缩流。
- 解码 (Decoding) :将压缩数据还原为原始的图像帧(YUV/RGB)和音频采样(PCM)。
- 音视频同步 (Synchronization) :通过时间戳(PTS)确保画面和声音对齐。
- 渲染 (Rendering) :将图像画在屏幕上(Canvas/GPU),将音频送入声卡。
浏览器能播放一部分 mp4 文件,是因为浏览器的音视频解码器是内嵌的,只能解压缩几种固定的编码格式, 补充说明:每一帧图像,音频采样本身也有自己的格式,图像会有 YUV,RGB 等格式,音频采样会有 float 等样本格式,但一般这些格式处理过程在音视频处理中是不需要特别关心的,因为编码解码时会自动处理这些。
二、 音视频同步机制
同步的核心是时间戳。
-
PTS (Presentation TimeStamp) :显示时间戳。告诉播放器这一帧应该在什么时间点播放。
-
DTS (Decoding TimeStamp) :解码时间戳。告诉播放器这一帧应该在什么时间点解码。
- 为什么需要两者? 因为存在 B 帧(双向预测),解码顺序可能和显示顺序不一致。
-
时间基 (Timebase) :时间戳的单位。例如时间基是
1/90000,PTS 为180000,则播放时间为180000 * (1/90000) = 2秒。
三、 浏览器播放核心组件
0. HTML5 标签
最基础、原生的播放组件。
-
角色:它是高层级的抽象,封装了底层复杂的 Pipeline。只需给它一个
src,浏览器就会自动完成“解复用 -> 解码 -> 渲染”。 -
直播播放的真相:
- 原生支持:仅在极少数环境下(如 Safari)原生支持 HLS (
.m3u8) 直播协议。 - 局限性:原生不支持 HTTP-FLV、DASH 等复杂直播流,也无法实现动态码率切换。
- 协作模式:在现代 Web 开发中,
<video>通常只充当 “渲染终端” 。开发者利用 MSE 插件(如 hls.js, flv.js)在外部处理复杂的协议逻辑,最后将解析好的数据块喂给<video>进行显示。
- 原生支持:仅在极少数环境下(如 Safari)原生支持 HLS (
1. MediaSource Extensions (MSE)
允许 JS 动态控制视频流。它是 HLS.js、Flv.js 实现的基础。
-
核心逻辑:
- 创建
MediaSource并绑定到<video>.src。 - 添加
SourceBuffer(指定格式,如video/mp4; codecs="avc1.42E01E")。 - 通过
fetch请求视频分片(fMP4),并appendBuffer喂给浏览器。
- 创建
-
优势:可以实现码率自适应切换、防盗链、直播拼接等。
2. WebCodecs API
直接操作解码器。它绕过了 <video> 标签,直接给你 VideoFrame。
-
流程:
- 使用
VideoDecoder或AudioDecoder解码媒体数据; - 解码后的帧以
VideoFrame或AudioData对象形式返回; - 你可以将帧绘制到
<canvas>,或送入WebGL/WebGPU; - 也可以用
VideoEncoder重新压缩输出。
- 使用
-
场景:超低延迟视频(云游戏)、视频剪辑(逐帧处理)、添加实时水印/滤镜。
3. Web Audio API
高性能音频处理框架。
- 节点模型:
AudioContext中通过各种 Node(GainNode, FilterNode)串联。 - 用途:音效增强、多通道混音、音频可视化。
4. WebAssembly (WASM)
WASM 并不是浏览器内置的视频播放 API,而是一个高性能计算环境,它让你能在浏览器中运行 C/C++/Rust 等编译后的代码。
- 用途:在浏览器运行 C++ 编写的
FFmpeg库,用来解码浏览器原生不支持的格式(如 H.265, FLV)。
四、 硬件加速与性能
-
硬件加速 (Hardware Acceleration) :利用 GPU 专有的解码电路(如 NVIDIA 的 NVDEC、Intel 的 QuickSync)代替 CPU 完成解码。
-
优势:极大地降低 CPU 占用,减少发热,是播放 4K/8K 视频的必要条件。
-
谁来控制?
-
浏览器自动管理:默认开启。浏览器会根据显卡驱动的稳定性自动决定。
-
用户设置:用户可以在浏览器设置中手动开关(“使用图形加速模式”)。
-
开发者偏好:在使用 WebCodecs 时,可以通过配置项明确要求使用硬件或软件解码:
decoder.configure({ codec: 'avc1.42E01E', hardwareAcceleration: 'prefer-hardware' // 或 'prefer-software' });
-
-
如何判断?
- 在 Chrome 的 Media 面板 中查看
Decoder Name。 - 如果显示为
VpxVideoDecoder或FFmpegVideoDecoder,通常是软解。 - 如果显示为
D3D11VideoDecoder或VaapiVideoDecoder,则是硬解。
- 在 Chrome 的 Media 面板 中查看
五、 转码过程简述
转码(Transcoding)本质上是:解封装 -> 解码 -> 处理(缩放/滤镜) -> 重新编码 -> 重新封装。
- 纯封转 (Remuxing) :如果不改变编码格式,只是把 MP4 转成 FLV,只需 解封装 -> 重新封装,性能极高且画质无损。这是 Web 端播放 FLV 直播流的核心思路。