强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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

注意事项

  1. 格式兼容性:不同播放器和设备对格式的支持程度不同
  2. 流选择:使用 -map 明确指定流,避免自动选择问题
  3. 元数据保留:使用 -map_metadata 保留或删除元数据
  4. 分片选项:流媒体需要使用分片格式
  5. 编码器兼容性:某些容器不支持特定编解码器

扩展阅读

  1. FFmpeg 格式文档
  2. MP4 格式规范
  3. Matroska 格式规范
  4. WebM 格式规范
  5. HLS 规范

总结

本章介绍了 FFmpeg 支持的各种容器格式,包括:

  • 容器格式的概念和分类
  • MP4、MKV、FLV、TS、WebM 等格式的特性
  • 格式转换方法
  • 多流处理技巧
  • 容器格式检测

掌握这些知识可以帮助您根据不同的使用场景选择合适的容器格式。