FFmpeg 多媒体处理教程 / 容器格式
容器格式
概述
容器格式(Container Format)是用于存储音频、视频、字幕等多媒体数据的文件格式。容器本身不决定数据的编码方式,而是定义了如何组织和同步这些数据流。本章详细介绍常见容器格式及其使用方法。
容器与编解码器的区别
基本概念
| 概念 |
说明 |
示例 |
| 容器格式 |
存储多媒体数据的文件格式 |
MP4、MKV、AVI |
| 编解码器 |
压缩/解压缩数据的算法 |
H.264、AAC、VP9 |
| 流(Stream) |
容器中的独立数据轨道 |
视频流、音频流、字幕流 |
┌─────────────────────────────────────────────┐
│ 容器文件 (Container) │
│ ┌─────────────────────────────────────────┐│
│ │ 视频流 (Video Stream) ││
│ │ 编解码器: H.264/H.265/VP9 ││
│ └─────────────────────────────────────────┘│
│ ┌─────────────────────────────────────────┐│
│ │ 音频流 (Audio Stream) ││
│ │ 编解码器: AAC/MP3/Opus ││
│ └─────────────────────────────────────────┘│
│ ┌─────────────────────────────────────────┐│
│ │ 字幕流 (Subtitle Stream) ││
│ │ 格式: SRT/ASS/VobSub ││
│ └─────────────────────────────────────────┘│
│ ┌─────────────────────────────────────────┐│
│ │ 元数据 (Metadata) ││
│ │ 标题、作者、创建时间等 ││
│ └─────────────────────────────────────────┘│
│ ┌─────────────────────────────────────────┐│
│ │ 章节信息 (Chapter Info) ││
│ │ 章节标记、时间戳 ││
│ └─────────────────────────────────────────┘│
└─────────────────────────────────────────────┘
常见容器格式对比
综合对比表
| 格式 |
扩展名 |
视频编解码器 |
音频编解码器 |
字幕支持 |
流媒体 |
兼容性 |
说明 |
| MP4 |
.mp4 |
H.264/H.265/VP9/AV1 |
AAC/MP3/Opus |
TTXT/VobSub |
HLS |
极好 |
最通用格式 |
| MKV |
.mkv |
几乎所有 |
几乎所有 |
ASS/SRT/SSA/VobSub |
有限 |
好 |
开放格式 |
| AVI |
.avi |
几乎所有 |
几乎所有 |
无 |
否 |
好 |
传统格式 |
| MOV |
.mov |
H.264/H.265/ProRes |
AAC/PCM |
TTXT |
有限 |
好 |
Apple 格式 |
| FLV |
.flv |
H.264/VP6 |
AAC/MP3 |
无 |
RTMP |
中 |
Flash 格式 |
| WebM |
.webm |
VP8/VP9/AV1 |
Vorbis/Opus |
WebVTT |
DASH |
好 |
Web 格式 |
| MPEG-TS |
.ts |
H.264/H.265 |
AAC/MP3 |
DVB |
HLS/DVB |
好 |
流媒体格式 |
| OGG |
.ogg |
Theora |
Vorbis/Opus |
无 |
有限 |
中 |
开源格式 |
| WMV |
.wmv |
WMV |
WMA |
无 |
有限 |
中 |
Microsoft 格式 |
格式选择建议
| 使用场景 |
推荐格式 |
原因 |
| Web 视频 |
MP4 |
兼容性最好,支持 HLS |
| 高清电影 |
MKV |
支持多音轨、多字幕 |
| 流媒体直播 |
FLV/MPEG-TS |
低延迟,支持推流 |
| Apple 设备 |
MOV/MP4 |
原生支持 |
| 开源项目 |
WebM/OGG |
免版税 |
| 存档备份 |
MKV |
支持所有编解码器 |
| 移动设备 |
MP4 |
通用兼容 |
MP4 格式详解
MP4 特性
| 特性 |
支持 |
说明 |
| 多音轨 |
✅ |
支持多个音频流 |
| 多字幕 |
✅ |
TTXT、VobSub 格式 |
| 章节 |
✅ |
通过元数据支持 |
| 流媒体 |
✅ |
支持 HLS、DASH |
| 元数据 |
✅ |
丰富的元数据支持 |
| 快速启动 |
✅ |
faststart 选项 |
| 分片 |
✅ |
支持分片 MP4 |
MP4 封装选项
# 基本 MP4 封装
ffmpeg -i input.mkv -c:v libx264 -c:a aac output.mp4
# 快速启动(Web 播放优化)
ffmpeg -i input.mkv -c:v libx264 -c:a aac -movflags +faststart output.mp4
# 分片 MP4(DASH/HLS)
ffmpeg -i input.mkv -c:v libx264 -c:a aac \
-movflags +frag_keyframe+empty_moov+default_base_moof output.mp4
# 碎片化 MP4
ffmpeg -i input.mkv -c:v libx264 -c:a aac \
-movflags +frag_keyframe+separate_moof+omit_tfhd_offset output.mp4
MP4 常用参数
| 参数 |
说明 |
示例 |
+faststart |
将 moov 原子移到文件开头 |
-movflags +faststart |
+frag_keyframe |
在关键帧处分片 |
-movflags +frag_keyframe |
+empty_moov |
创建空的 moov 原子 |
-movflags +empty_moov |
+default_base_moof |
默认基地址 |
-movflags +default_base_moof |
+separate_moof |
独立的 moof 原子 |
-movflags +separate_moof |
+omit_tfhd_offset |
省略 tfhd 偏移 |
-movflags +omit_tfhd_offset |
+dash |
DASH 兼容 |
-movflags +dash |
MP4 元数据编辑
# 添加元数据
ffmpeg -i input.mp4 \
-metadata title="视频标题" \
-metadata artist="作者" \
-metadata date="2024" \
-metadata comment="备注" \
-c copy output.mp4
# 删除元数据
ffmpeg -i input.mp4 -map_metadata -1 -c copy output.mp4
# 从文件读取元数据
ffmpeg -i input.mp4 -map_metadata 1 -i metadata.txt -c copy output.mp4
MKV 格式详解
MKV 特性
| 特性 |
支持 |
说明 |
| 多音轨 |
✅ |
无限制 |
| 多字幕 |
✅ |
ASS/SRT/SSA/VobSub/PGS |
| 章节 |
✅ |
XML 章节格式 |
| 元数据 |
✅ |
标签系统 |
| 附件 |
✅ |
字体、图片等 |
| 菜单 |
✅ |
简单菜单支持 |
| 流媒体 |
⚠️ |
有限支持 |
MKV 封装选项
# 基本 MKV 封装
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mkv
# 保留所有流
ffmpeg -i input.mp4 -map 0 -c copy output.mkv
# 添加多音轨
ffmpeg -i video.mp4 -i audio1.mp3 -i audio2.aac \
-map 0:v -map 0:a -map 1:a -map 2:a \
-c:v copy -c:a copy \
-metadata:s:a:0 language=chi \
-metadata:s:a:1 language=eng \
output.mkv
# 添加字幕
ffmpeg -i input.mp4 -i subtitle.srt -i subtitle.ass \
-map 0 -map 1 -map 2 \
-c:v copy -c:a copy -c:s srt \
output.mkv
MKV 章节编辑
# 创建章节文件 chapters.xml
cat > chapters.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<Chapters>
<EditionEntry>
<ChapterAtom>
<ChapterTimeStart>00:00:00.000</ChapterTimeStart>
<ChapterTimeEnd>00:05:00.000</ChapterTimeEnd>
<ChapterDisplay>
<ChapterString>第一章</ChapterString>
</ChapterDisplay>
</ChapterAtom>
<ChapterAtom>
<ChapterTimeStart>00:05:00.000</ChapterTimeStart>
<ChapterTimeEnd>00:10:00.000</ChapterTimeEnd>
<ChapterDisplay>
<ChapterString>第二章</ChapterString>
</ChapterDisplay>
</ChapterAtom>
</EditionEntry>
</Chapters>
EOF
# 应用章节
ffmpeg -i input.mkv -i chapters.xml -map_metadata 1 -c copy output.mkv
MKV 流语言设置
# 设置音频流语言
ffmpeg -i input.mkv \
-metadata:s:a:0 language=chi \
-metadata:s:a:1 language=eng \
-c copy output.mkv
# 设置字幕流语言
ffmpeg -i input.mkv \
-metadata:s:s:0 language=chi \
-metadata:s:s:1 language=eng \
-c copy output.mkv
# 设置默认流
ffmpeg -i input.mkv \
-disposition:a:0 default \
-disposition:a:1 0 \
-c copy output.mkv
FLV 格式详解
FLV 特性
| 特性 |
支持 |
说明 |
| 多音轨 |
❌ |
仅支持单音轨 |
| 字幕 |
❌ |
不支持 |
| 章节 |
❌ |
不支持 |
| 流媒体 |
✅ |
RTMP 推流 |
| 元数据 |
✅ |
基本元数据 |
| 低延迟 |
✅ |
适合直播 |
FLV 封装选项
# 基本 FLV 封装
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -f flv output.flv
# RTMP 推流
ffmpeg -re -i input.mp4 \
-c:v libx264 -preset ultrafast -tune zerolatency \
-c:a aac -b:a 128k \
-f flv rtmp://server/live/stream
# 带元数据的 FLV
ffmpeg -i input.mp4 \
-c:v libx264 -c:a aac \
-metadata title="直播标题" \
-f flv output.flv
MPEG-TS 格式详解
MPEG-TS 特性
| 特性 |
支持 |
说明 |
| 多音轨 |
✅ |
PID 标识 |
| 字幕 |
✅ |
DVB 字幕 |
| 章节 |
❌ |
不支持 |
| 流媒体 |
✅ |
HLS/DVB |
| 错误恢复 |
✅ |
包级错误恢复 |
| 低延迟 |
⚠️ |
取决于配置 |
MPEG-TS 封装选项
# 基本 MPEG-TS 封装
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -f mpegts output.ts
# HLS 分片
ffmpeg -i input.mp4 -c:v libx264 -c:a aac \
-f hls -hls_time 4 -hls_list_size 0 \
-hls_segment_filename "segment_%03d.ts" \
playlist.m3u8
# 低延迟 MPEG-TS
ffmpeg -i input.mp4 -c:v libx264 -c:a aac \
-mpegts_flags +resend_headers \
-f mpegts output.ts
MPEG-TS 流标识
# 设置流类型
ffmpeg -i input.mp4 -c:v libx264 -c:a aac \
-streamid 0:256 -streamid 1:257 \
-f mpegts output.ts
# 查看流信息
ffprobe -show_streams output.ts
WebM 格式详解
WebM 特性
| 特性 |
支持 |
说明 |
| 多音轨 |
⚠️ |
有限支持 |
| 字幕 |
✅ |
WebVTT 格式 |
| 章节 |
❌ |
不支持 |
| 流媒体 |
✅ |
DASH |
| 元数据 |
✅ |
基本元数据 |
| 免版税 |
✅ |
VP8/VP9/AV1 + Vorbis/Opus |
WebM 封装选项
# VP9 + Opus
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus output.webm
# VP8 + Vorbis
ffmpeg -i input.mp4 -c:v libvpx -b:v 2M -c:a libvorbis output.webm
# AV1 + Opus
ffmpeg -i input.mp4 -c:v libaom-av1 -crf 30 -b:v 0 -c:a libopus output.webm
# 分片 WebM (DASH)
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus \
-dash 1 output.webm
格式转换
常见格式转换
# AVI 转 MP4
ffmpeg -i input.avi -c:v libx264 -c:a aac output.mp4
# MKV 转 MP4
ffmpeg -i input.mkv -c:v copy -c:a copy output.mp4
# FLV 转 MP4
ffmpeg -i input.flv -c:v copy -c:a copy output.mp4
# MOV 转 MP4
ffmpeg -i input.mov -c:v copy -c:a copy output.mp4
# MP4 转 WebM
ffmpeg -i input.mp4 -c:v libvpx-vp9 -c:a libopus output.webm
# MP4 转 MKV
ffmpeg -i input.mp4 -c copy output.mkv
无损转换
# 直接复制流(无损,最快)
ffmpeg -i input.avi -c copy output.mp4
# 仅复制特定流
ffmpeg -i input.mkv -map 0:v -map 0:a:0 -c copy output.mp4
带滤镜的格式转换
# 转换并缩放
ffmpeg -i input.avi -vf scale=1280:720 -c:v libx264 -c:a aac output.mp4
# 转换并裁剪
ffmpeg -i input.mkv -vf crop=1280:720:0:0 -c:v libx264 -c:a aac output.mp4
# 转换并添加水印
ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" -c:v libx264 -c:a copy output.mkv
多流处理
多音轨处理
# 提取特定音轨
ffmpeg -i input.mkv -map 0:v -map 0:a:1 -c copy output.mp4
# 合并多音轨
ffmpeg -i video.mp4 -i audio_en.mp3 -i audio_cn.mp3 \
-map 0:v -map 1:a -map 2:a \
-c:v copy -c:a aac \
-metadata:s:a:0 language=eng \
-metadata:s:a:1 language=chi \
output.mkv
# 混合音轨
ffmpeg -i input.mkv -filter_complex "[0:a:0][0:a:1]amix=inputs=2:duration=longest[a]" \
-map 0:v -map "[a]" -c:v copy -c:a aac output.mp4
多字幕处理
# 添加外部字幕
ffmpeg -i input.mp4 -i subtitle.srt \
-map 0 -map 1 \
-c:v copy -c:a copy -c:s mov_text \
output.mp4
# 提取字幕
ffmpeg -i input.mkv -map 0:s:0 output.srt
# 转换字幕格式
ffmpeg -i input.mkv -map 0:v -map 0:a -map 0:s:0 \
-c:v copy -c:a copy -c:s srt \
output.mkv
流映射策略
# 选择所有流
ffmpeg -i input.mkv -map 0 -c copy output.mkv
# 选择特定类型的第一个流
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -c copy output.mp4
# 排除特定流
ffmpeg -i input.mkv -map 0 -map -0:s -c copy output.mp4
# 从多个输入选择流
ffmpeg -i video.mp4 -i audio.mp3 -i subtitle.srt \
-map 0:v -map 1:a -map 2:s \
-c copy output.mkv
容器格式检测
使用 ffprobe 检测
# 基本信息
ffprobe input.mp4
# JSON 格式输出
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
# 仅显示格式信息
ffprobe -v quiet -show_format input.mp4
# 仅显示流信息
ffprobe -v quiet -show_streams input.mp4
# 选择特定流信息
ffprobe -v quiet -select_streams v:0 -show_entries stream=codec_name,width,height input.mp4
格式检测脚本
#!/bin/bash
# detect_format.sh
FILE=$1
echo "=== 文件信息 ==="
echo "格式: $(ffprobe -v quiet -show_entries format=format_name -of csv=p=0 "$FILE")"
echo "时长: $(ffprobe -v quiet -show_entries format=duration -of csv=p=0 "$FILE") 秒"
echo "大小: $(ls -lh "$FILE" | awk '{print $5}')"
echo -e "\n=== 流信息 ==="
ffprobe -v quiet -show_entries stream=index,codec_type,codec_name,width,height,r_frame_rate,sample_rate,channels -of csv=p=0 "$FILE"
echo -e "\n=== 视频流 ==="
ffprobe -v quiet -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate,pix_fmt -of csv=p=0 "$FILE"
echo -e "\n=== 音频流 ==="
ffprobe -v quiet -select_streams a:0 -show_entries stream=codec_name,sample_rate,channels,channel_layout -of csv=p=0 "$FILE"
容器格式最佳实践
场景 1:Web 发布
# MP4 + faststart(推荐)
ffmpeg -i input.mkv \
-c:v libx264 -preset slow -crf 23 \
-profile:v high -level 4.1 \
-movflags +faststart \
-c:a aac -b:a 128k \
output_web.mp4
场景 2:高质量存档
# MKV + 多音轨 + 字幕
ffmpeg -i input.mp4 \
-map 0 \
-c:v libx265 -preset slow -crf 22 \
-c:a copy \
-c:s copy \
output_archive.mkv
场景 3:流媒体
# HLS 分片
ffmpeg -i input.mp4 \
-c:v libx264 -preset fast -crf 23 \
-c:a aac -b:a 128k \
-f hls -hls_time 4 -hls_list_size 0 \
-hls_segment_filename "segment_%03d.ts" \
playlist.m3u8
场景 4:移动设备
# 兼容性 MP4
ffmpeg -i input.mkv \
-c:v libx264 -profile:v baseline -level 3.0 \
-vf scale=640:480 \
-c:a aac -b:a 96k -ar 44100 -ac 2 \
output_mobile.mp4
注意事项
- 格式兼容性:不同播放器和设备对格式的支持程度不同
- 流选择:使用
-map 明确指定流,避免自动选择问题
- 元数据保留:使用
-map_metadata 保留或删除元数据
- 分片选项:流媒体需要使用分片格式
- 编码器兼容性:某些容器不支持特定编解码器
扩展阅读
- FFmpeg 格式文档
- MP4 格式规范
- Matroska 格式规范
- WebM 格式规范
- HLS 规范
总结
本章介绍了 FFmpeg 支持的各种容器格式,包括:
- 容器格式的概念和分类
- MP4、MKV、FLV、TS、WebM 等格式的特性
- 格式转换方法
- 多流处理技巧
- 容器格式检测
掌握这些知识可以帮助您根据不同的使用场景选择合适的容器格式。