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 等格式的特性
- 格式转换方法
- 多流处理技巧
- 容器格式检测
掌握这些知识可以帮助您根据不同的使用场景选择合适的容器格式。