视频格式与编解码:从原理到生产选型的完整指南
你的视频为什么在 Safari 上播不了?为什么同样是 1080p,文件大小差了 3 倍?为什么 AI 视频项目的流式播放必须用 fMP4?这些问题的答案,都藏在"容器"与"编解码器"这两个概念里。这篇文章带你从底层原理出发,把视频格式这件事彻底讲清楚。
第一步:先分清两个概念
视频开发中最基础也最容易混淆的概念是容器格式和编解码器,它们是两件完全不同的事情。
容器格式(Container Format)是一个"盒子",负责把视频流、音频流、字幕、元数据打包在一起,并定义它们的组织结构。常见容器:.mp4、.webm、.mkv、.mov。
编解码器(Codec,Coder-Decoder)是压缩和解压视频数据的算法。同一个容器里可以装不同编解码器编码的内容,比如 MP4 容器里可以装 H.264,也可以装 H.265,甚至 AV1。
视频文件 = 容器格式(MP4)
├── 视频轨道:H.264 编码的画面数据
├── 音频轨道:AAC 编码的声音数据
└── 元数据:时长、分辨率、章节信息...
类比:容器是快递箱,编解码器是箱子里货物的包装方式。同样的货物(视频内容),可以用不同的包装方式压缩,装进不同的箱子。
第二部分:容器格式详解
MP4(.mp4)— 兼容性最广的容器
MP4 是基于 MPEG-4 Part 12 标准的容器格式,是目前 Web 视频的事实标准。几乎所有浏览器、设备、播放器都支持它。内部结构由一系列 Box(原子) 组成,其中最关键的是两个:
moovbox:包含视频的所有元数据(时长、编解码信息、每帧的位置索引)mdatbox:包含实际的音视频数据
moov 的位置决定了视频能否"边下边播"。默认情况下,很多编码工具生成的 MP4 文件,moov 在文件末尾。浏览器必须下载整个文件才能找到 moov,然后才能开始播放——这在网络视频场景下是灾难性的。
解决方案是使用 FFmpeg 的 -movflags faststart 参数,将 moov 移到文件头部:
# 将 moov 前置,实现边下边播
ffmpeg -i input.mp4 -movflags faststart -codec copy output.mp4这一步对所有面向 Web 的 MP4 视频都是必做操作,直接影响首帧加载速度。github.com/haochuan9421
WebM(.webm)— Web 原生的开放格式
WebM 是 Google 于 2010 年推出的开放、免专利的视频格式,基于 Matroska 容器,专为 Web 流媒体设计。它只支持特定的编解码器组合:
- 视频:VP8、VP9、AV1
- 音频:Vorbis、Opus
WebM 的优势是完全开放、无专利费,且与 Chrome/Firefox 深度集成。劣势是 Safari 的支持历史上不稳定(Safari 14+ 才较好地支持 VP9 + WebM)。
fMP4(Fragmented MP4)— 流媒体的基石
fMP4 是 MP4 的流式变体,也是 MSE(Media Source Extensions)和 MPEG-DASH 的标准分片格式,理解它对 AI 视频的流式播放至关重要。
普通 MP4 的问题在于它的索引(moov)是一个整体,必须完整加载才能使用。fMP4 将视频数据切分成独立的片段(Fragment),每个片段包含自己的 moof(片段头)+ mdat(片段数据),可以独立解码,不依赖其他片段。
普通 MP4:[moov][mdat(全部数据)]
fMP4: [ftyp][moov][moof+mdat][moof+mdat][moof+mdat]...
↑片段1 ↑片段2 ↑片段3
这种结构使得 fMP4 天然支持:
- 随机访问:直接跳到任意片段,无需从头加载
- 码率切换:HLS 和 DASH 的码率自适应切换依赖于此
- 边生成边播放:AI 视频生成完一个片段就推送一个,实现流式播放
# 用 FFmpeg 生成 fMP4
ffmpeg -i input.mp4 \
-c:v libx264 \
-c:a aac \
-movflags frag_keyframe+empty_moov+default_base_moof \
output.fmp4zhuanlan.zhihu.com lucius0.github.io
第三部分:编解码器深度解析
H.264 / AVC — 最广泛的编解码器
H.264(也叫 AVC,Advanced Video Coding)是 2003 年发布的视频编码标准,至今仍是 Web 视频的绝对主力。它的核心优势是兼容性无与伦比——从 IE9 到最新的 Safari,从 Android 2.3 到 iOS 最新版,几乎所有设备都有 H.264 的硬件解码器。
Profile 与 Level 是 H.264 最重要的两个参数,直接影响兼容性和画质:
Profile 定义了使用的压缩特性子集:
| Profile | 特点 | 适用场景 |
|---|---|---|
| Baseline | 最基础,只支持 I/P 帧,无 B 帧 | 低延迟视频通话、老旧移动设备 |
| Main | 支持 B 帧,质量更好 | 标清/高清广播 |
| High | 最高压缩效率,支持 CABAC 熵编码 | Web 视频首选 |
Level 定义了分辨率、帧率和码率的上限。Web 视频常用 Level 4.1(支持 1080p@30fps)和 Level 5.1(支持 4K@30fps)。
在 <video> 的 type 属性中,codec 字符串的完整写法是:
video/mp4; codecs="avc1.PPCCLL"
↑↑ ↑↑ ↑↑
PP = Profile(42=Baseline, 4D=Main, 64=High)
CC = Constraint flags
LL = Level(1E=3.0, 28=4.0, 29=4.1, 32=5.0)
常用组合:
// High Profile, Level 4.1 — Web 视频最常用
'video/mp4; codecs="avc1.64002A"'
// Baseline Profile, Level 3.1 — 最大兼容性
'video/mp4; codecs="avc1.42E01F"'
// Main Profile, Level 4.0
'video/mp4; codecs="avc1.4D0028"'H.265 / HEVC — 高压缩率的代价是专利费
H.265(HEVC,High Efficiency Video Coding)是 H.264 的继任者,相同画质下码率节省约 50%。但它有一个致命问题:复杂的专利授权体系,导致浏览器厂商的支持极不统一。
- Safari(macOS/iOS):支持(Apple 有自己的专利授权)
- Chrome:不支持(需要付专利费)
- Firefox:不支持
- Edge:部分支持(依赖系统解码器)
这意味着 H.265 在 Web 场景几乎无法作为主力格式,除非你的目标平台是纯 Apple 生态。
VP9 — Google 的开放编解码器
VP9 是 Google 于 2013 年发布的开放编解码器,相同画质下码率比 H.264 节省约 30~50%。YouTube 的大部分视频都在用 VP9。
浏览器支持情况:
| 浏览器 | 支持版本 |
|---|---|
| Chrome | 29+ |
| Firefox | 28+ |
| Edge | 14+ |
| Safari | 14(macOS)/ 15(iOS) |
Safari 对 VP9 的支持直到 2020 年才加入,这是 VP9 长期无法作为 Web 唯一格式的原因。
# FFmpeg 编码 VP9(两遍编码获得最佳质量)
# 第一遍:分析
ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 0 -crf 33 -pass 1 -an -f null /dev/null
# 第二遍:编码
ffmpeg -i input.mp4 \
-c:v libvpx-vp9 \
-b:v 0 -crf 33 \
-pass 2 \
-c:a libopus -b:a 128k \
output.webmAV1 — 下一代的开放标准
AV1 是由 Alliance for Open Media(AOM)于 2018 年发布的开放、免专利编解码器,成员包括 Google、Apple、Microsoft、Netflix、Amazon 等。它代表了当前编解码技术的最高水平:
- 相比 H.264,相同画质码率节省约 43%(1080p)到 63%(4K)
- 相比 VP9,码率节省约 20~30%
- 完全开放,无专利费 news.qq.com developer.aliyun.com
浏览器支持现状(2026):
| 浏览器 | 支持版本 | 备注 |
|---|---|---|
| Chrome | 70+ | 软解;Chrome 113+ 支持硬件编码 |
| Firefox | 67+ | 软解为主 |
| Edge | 18+ | 部分依赖系统解码器 |
| Safari | 16.4+(macOS) | 需要 Apple Silicon 或 A17+ 芯片的硬件解码 |
AV1 目前最大的挑战是编码速度极慢(比 H.264 慢 10~100 倍),以及旧设备缺少硬件解码器导致 CPU 占用高。但随着硬件普及,AV1 正在成为 Web 视频的未来标准。B 站、YouTube 都已大规模部署 AV1。
# FFmpeg 编码 AV1(使用 libaom-av1,速度较慢)
ffmpeg -i input.mp4 \
-c:v libaom-av1 \
-crf 30 \
-b:v 0 \
-cpu-used 4 \ # 0=最慢最优,8=最快最差,4是平衡点
-c:a libopus -b:a 128k \
output_av1.webm
# 更快的 AV1 编码器:SVT-AV1(Netflix 开源,速度快很多)
ffmpeg -i input.mp4 \
-c:v libsvtav1 \
-crf 30 \
-preset 6 \ # 0=最慢,13=最快
-c:a libopus -b:a 128k \
output_svtav1.webm音频编解码器
视频文件里的音频轨道同样需要编解码,Web 场景常用的三种:
| 编解码器 | 容器 | 特点 |
|---|---|---|
| AAC | MP4 | 兼容性最广,128kbps 音质优秀,iOS/Android 硬件支持 |
| Opus | WebM | 开放免费,低延迟,128kbps 效果优于 AAC,WebRTC 标准 |
| MP3 | MP4/WebM | 老格式,仅兼容性需求时使用 |
Web 视频的音频选型很简单:MP4 用 AAC,WebM 用 Opus。
第四部分:浏览器支持矩阵
格式组合 Chrome Firefox Safari Edge iOS Safari
─────────────────────────────────────────────────────────────────────
MP4 + H.264 + AAC ✅ ✅ ✅ ✅ ✅
WebM + VP9 + Opus ✅ ✅ ✅* ✅ ✅*
WebM + AV1 + Opus ✅ ✅ ✅** ✅ ✅**
MP4 + H.265 + AAC ❌ ❌ ✅ △ ✅
* Safari 14+ (macOS), Safari 15+ (iOS)
** Safari 16.4+ (macOS), 需要硬件支持
从这张矩阵可以得出一个清晰的生产策略:必须提供 MP4/H.264 作为兜底,可以叠加 WebM/AV1 给支持的浏览器获得更好的压缩率。
第五部分:格式能力检测
在代码中动态选择最优格式,有三个层次的检测 API,精度依次递增:
层次一:canPlayType()
const video = document.createElement('video');
// 返回 'probably' | 'maybe' | ''
const support = {
h264: video.canPlayType('video/mp4; codecs="avc1.42E01E"'),
vp9: video.canPlayType('video/webm; codecs="vp9, opus"'),
av1: video.canPlayType('video/webm; codecs="av01.0.05M.08"'),
hevc: video.canPlayType('video/mp4; codecs="hev1.1.6.L93.B0"'),
};
console.log(support);
// Chrome: { h264: 'probably', vp9: 'probably', av1: 'probably', hevc: '' }
// Safari: { h264: 'probably', vp9: 'probably', av1: 'probably', hevc: 'probably' }层次二:MediaSource.isTypeSupported()
用于 MSE 场景(HLS.js、Dash.js 等),检测是否支持通过 MSE 播放某种格式:
// 检测 fMP4 格式的 MSE 支持
const mseSupport = {
h264: MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E"'),
vp9: MediaSource.isTypeSupported('video/webm; codecs="vp9"'),
av1: MediaSource.isTypeSupported('video/mp4; codecs="av01.0.05M.08"'),
};isTypeSupported 比 canPlayType 更严格——它不仅检测解码能力,还检测是否支持通过 MSE 追加该格式的分片数据。
层次三:navigator.mediaCapabilities.decodingInfo()
最精准的检测 API,不仅告诉你"能不能播",还告诉你"播得流不流畅"、"有没有硬件加速":
async function checkDecodeCapability(config) {
const result = await navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: {
contentType: 'video/mp4; codecs="avc1.42E01E"',
width: 1920,
height: 1080,
bitrate: 4000000, // 4Mbps
framerate: 30,
},
});
console.log({
supported: result.supported, // 是否支持
smooth: result.smooth, // 是否流畅(不会掉帧)
powerEfficient: result.powerEfficient, // 是否有硬件加速
});
}
checkDecodeCapability();
// { supported: true, smooth: true, powerEfficient: true }powerEfficient: true 意味着有硬件解码器介入,功耗低、性能高;false 表示纯软件解码,在低端设备上可能导致发热和掉帧。zhuanlan.zhihu.com
第六部分:硬件解码 vs 软件解码
这是影响移动端体验的关键因素,但很多开发者没有意识到。
硬件解码:由 GPU 或专用解码芯片处理,CPU 占用极低,功耗小,播放 4K 视频不发热。几乎所有现代设备都有 H.264 的硬件解码器。AV1 的硬件解码器从 2022~2023 年的新设备开始普及。
软件解码:由 CPU 处理,高分辨率视频会导致 CPU 满载、发热、掉帧、耗电。
对 Web 开发者的影响:当你用 canPlayType 检测到浏览器"支持"某种格式时,不代表有硬件加速。在老旧移动设备上用软件解码播放 AV1,体验可能还不如 H.264 硬件解码。这正是 mediaCapabilities.decodingInfo() 的价值所在——它能区分硬件解码和软件解码。
第七部分:Web 视频格式选型决策树
你的视频需要在哪些平台播放?
│
├── 必须支持所有浏览器(含旧版 Safari)
│ └── 主力格式:MP4 + H.264 + AAC
│ 可选叠加:WebM + VP9/AV1 + Opus(给 Chrome/Firefox 更好体验)
│
├── 只需支持现代浏览器(2022年以后)
│ └── 主力:WebM + VP9 + Opus
│ 叠加:WebM + AV1 + Opus(Chrome/Firefox 优先选择)
│ 兜底:MP4 + H.264 + AAC(Safari 兜底)
│
├── 流媒体/直播(需要 MSE)
│ └── 必须使用 fMP4(H.264 或 AV1)或 WebM 分片
│ 配合 HLS.js / Dash.js / Shaka Player
│
└── AI 视频流式播放(边生成边播)
└── fMP4 + MSE 的 appendBuffer 方案
或 HLS 分片推送方案
第八部分:生产环境转码工具链
FFmpeg — 命令行瑞士军刀
FFmpeg 是视频处理的核心工具,以下是针对 Web 视频的常用转码命令:
# ── 生成 Web 最优 MP4(H.264 High Profile + AAC + moov 前置)──
ffmpeg -i input.mp4 \
-c:v libx264 \
-profile:v high \ # High Profile
-level:v 4.1 \ # Level 4.1,支持 1080p@30fps
-preset slow \ # 编码速度/质量平衡(ultrafast/fast/medium/slow/veryslow)
-crf 23 \ # 质量因子,18=高质量,28=低质量,23是默认
-c:a aac \
-b:a 128k \
-movflags faststart \ # moov 前置!
output_h264.mp4
# ── 生成 WebM/VP9(双遍编码)──
ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 0 -crf 33 -pass 1 -an -f null /dev/null && \
ffmpeg -i input.mp4 \
-c:v libvpx-vp9 -b:v 0 -crf 33 -pass 2 \
-c:a libopus -b:a 128k \
output_vp9.webm
# ── 生成 fMP4 分片(用于 MSE/DASH)──
ffmpeg -i input.mp4 \
-c:v libx264 -profile:v high -level:v 4.1 -crf 23 \
-c:a aac -b:a 128k \
-movflags frag_keyframe+empty_moov+default_base_moof \
-g 48 \ # 关键帧间隔(影响分片大小)
output.fmp4
# ── 批量生成多码率版本(用于自适应码率)──
ffmpeg -i input.mp4 \
-map 0:v -map 0:a -c:v libx264 -crf 28 -vf scale=640:-2 -c:a aac -b:a 96k 360p.mp4 \
-map 0:v -map 0:a -c:v libx264 -crf 25 -vf scale=1280:-2 -c:a aac -b:a 128k 720p.mp4 \
-map 0:v -map 0:a -c:v libx264 -crf 23 -vf scale=1920:-2 -c:a aac -b:a 192k 1080p.mp4ffprobe — 视频信息检测
# 查看视频的编解码、分辨率、码率等完整信息
ffprobe -v quiet -print_format json -show_streams input.mp4
# 快速查看关键信息
ffprobe -v error -select_streams v:0 \
-show_entries stream=codec_name,width,height,bit_rate,r_frame_rate \
-of default=noprint_wrappers=1 input.mp4第九部分:生产环境最佳实践模板
把以上知识整合成一个完整的格式选择和 <video> 配置方案:
// 智能格式选择器
async function getBestVideoSource(sources) {
// sources = { av1: 'video_av1.webm', vp9: 'video_vp9.webm', h264: 'video.mp4' }
const checks = [
{
src: sources.av1,
type: 'video/webm; codecs="av01.0.05M.08"',
label: 'AV1',
},
{
src: sources.vp9,
type: 'video/webm; codecs="vp9, opus"',
label: 'VP9',
},
{
src: sources.h264,
type: 'video/mp4; codecs="avc1.64002A"',
label: 'H.264',
},
];
for (const check of checks) {
const supported = MediaSource.isTypeSupported(check.type);
if (!supported) continue;
// 进一步检查是否有硬件加速(可选)
if (navigator.mediaCapabilities) {
const info = await navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: {
contentType: check.type,
width: 1920, height: 1080,
bitrate: 4000000, framerate: 30,
},
});
if (info.supported) {
console.log(`选择格式: , 硬件加速: `);
return check;
}
} else {
return check;
}
}
// 最终兜底
return { src: sources.h264, type: 'video/mp4', label: 'H.264 fallback' };
}
// 使用示例
const best = await getBestVideoSource({
av1: 'https://cdn.example.com/video_av1.webm',
vp9: 'https://cdn.example.com/video_vp9.webm',
h264: 'https://cdn.example.com/video.mp4',
});
const video = document.querySelector('video');
video.src = best.src;对应的 HTML 静态写法(无需 JS 检测,浏览器自动选择):
<video controls preload="metadata" playsinline>
<!-- AV1:最优压缩,现代浏览器优先选择 -->
<source src="video_av1.webm"
type="video/webm; codecs='av01.0.05M.08, opus'" />
<!-- VP9:次优,广泛支持 -->
<source src="video_vp9.webm"
type="video/webm; codecs='vp9, opus'" />
<!-- H.264:最终兜底,100% 兼容 -->
<source src="video.mp4"
type="video/mp4; codecs='avc1.64002A, mp4a.40.2'" />
<p>您的浏览器不支持 HTML5 视频</p>
</video>编解码器速查表
| 编解码器 | 标准组织 | 专利 | 压缩效率 | 编码速度 | 硬件解码普及度 | Web 推荐度 |
|---|---|---|---|---|---|---|
| H.264 | ITU/ISO | 有(MPEG-LA) | 基准 | 快 | 极高(所有设备) | ⭐⭐⭐⭐⭐ 兜底必选 |
| H.265 | ITU/ISO | 有(多个池) | H.264 的 2x | 中 | 高(新设备) | ⭐⭐ 仅 Apple 生态 |
| VP9 | 无 | H.264 的 1.5x | 中 | 中(2018年后设备) | ⭐⭐⭐⭐ 主力之一 | |
| AV1 | AOM | 无 | H.264 的 2x | 极慢 | 低(2022年后设备) | ⭐⭐⭐⭐ 未来主力 |
小结
视频格式的选型本质上是在兼容性、压缩效率、编码成本三者之间寻找平衡。对于今天的 Web 视频项目,最稳健的策略是:H.264 作为必备兜底,VP9 或 AV1 作为现代浏览器的优选格式,fMP4 作为流式播放和 AI 视频场景的基础格式。
下一篇将深入流媒体协议,把 HLS 的 m3u8 结构、DASH 的 MPD 文件、自适应码率的切换算法,以及 MSE 如何把这一切串联起来,完整地讲透。