第1章 FFmpeg简介
1.1 FFmpeg定义
FFmpeg既是一款音视频编解码工具,同时也是一组音视频编解码开发套件,作为编解码开发套件,它为开发者提供了丰富的音视频处理的调用接口。 FFmpeg提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种色彩格式转换、多种采样率转换、多种码率转换等;FFmpeg框架提供了多种丰富的插件模块,包含封装与解封装的插件、编码与解码的插件等。
FFmpeg中的“FF”指的是“FastForward”(快进),曾经有人写信给FFmpeg的项目负责人,询问“FF”是不是代表“FastFreec”或者“FastFourier”的意思。FFmpeg中的“mpeg则是人们通常理解的Moving Picture Experts Group(动态图像专家组),FFmpeg是一个很全面的图像处理套件。其实从2000年发展至今,FFmpeg中的“FF”已经可以用各种组合进行理解,因为FFmpeg的强大足以支撑这些意义。
1.2 FFmpeg的基本组成
(1)FFmpeg的封装模块AVFormat
AVFormat中实现了目前多媒体领域中的绝大多数媒体封装格式,包括封装和解封装 FFmpeg基本组成模块MP4、FLV、KV、TS等文件封装格式,RTMP、RTSP、MMS、HLS等网络协议封装格式。 FFmpeg是否支持某种媒体封装格式,取决于编译时是否包含了该格式的封装库。根据实际需求,可进行煤体封装格式的扩展,增加自己定制的封装格式,即在AVFormat中增加自己的封装处理模块。
(2)FFmpeg的编解码模块AVCodec
AVCodec中实现了目前多媒体领域绝大多数常用的编解码格式,既支持编码,也支持解码。AVCodec除了支持MPEG4、AAC、MJPEG等自带的媒体编解码格式之外,还支持第三方的编解码器,如H.264(AVC)编码,需要使用x264编码器;H.265(HEVC)编码,需要使用x265编码器:MP3(mp3lame)编码,需要使用libmp3lame编码器。如果
(3)FFmpeg的滤镜模块AVFilter
AVFilter库提供了一个通用的音频、视频、字幕等滤镜处理框架。在AVFilter中,滤镜框架可以有多个输入和多个输出。
- 相同的Filter线性链之间用逗号分隔
- 不同的Filter线性链之间用分号分隔
(4)FFmpeg的视频图像转换计算模块swscale
swscale模块提供了高级别的图像转换API,例如它允许进行图像缩放和像素格式转换,常见于将图像从1080p转换成720p或者480p等的缩放,或者将图像数据从YUV420P转换成YUYV,或者YUV转RGB等图像格式转换。
(5)FFmpeg的音频转换计算模块swresample
swresample模块提供了高级别的音频重采样API。例如它允许操作音频采样、音频通道布局转换与布局调整。
1.3FFmpeg的编解码工具ffmpeg
fmpeg是FFmpeg源代码编译后生成的一个可执行程序,其可以作为命令行工具使用。
fmpeg的主要工作流程相对比较简单,具体如下。
1)解封装(Demuxing)。 2)解码(Decoding)。 3)编码(Encoding)。 4)封装(Muxing)。 其中需要经过6个步骤,具体如下。 1)读取输人源。 2)进行音视频的解封装。
3)解码每一帧音视频数据
4)编码每一帧音视频数据。
5)进行音视频的重新封装。
6)输出到目标。
1.5 FFmpeg的播放器fplay
FFmpeg不但可以提供转码、转封装等功能,同时还提供了播放器相关功能,使用FFmpeg的avformat与avcodec,可以播放各种媒体文件或者流。如果想要使用fplay,那么系统首先需要有SDL来进行fplay的基础支撑。 fplay是FFmpeg源代码编译后生成的另一个可执行程序,与fmpeg在FFmpeg项目中充当的角色基本相同,可以作为测试工具进行使用,fplay提供了音视频显示和播放相关的图像信息、音频的波形信息等。
注意: 有时通过源代码编译生成fplay不一定能够成功,因为mplay在旧版本时依赖于SDL-1.2,而fplay在新版本时依赖于SDL-2.0,需要安装对应的SDL才能生成flaya
1.6 FFmpeg的多媒体分析器ffprobe
ffprobe也是FFmpeg源码编译后生成的一个可执行程序。ffprobe是一个非常强大的多媒体分析工具,可以从媒体文件或者媒体流中获得你想要了解的媒体信息,比如音频的参数、视频的参数、媒体容器的参数信息等。 例如它可以帮助分析某个媒体容器中的音频是什么编码格式、视频是什么编码格式,同时还可以得到媒体文件中媒体的总时长、复合码率等信息。 使用fprobe可以分析媒体文件中每个包的长度、包的类型、顿的信息等
1.7 FFmpeg编译
FFmpeg在官方网站中提供了已经编译好的可执行文件。因为FFmpeg是开源的,所以也可以根据自己的需要进行手动编译。FFmpeg官方建议用户自行编译使用FFmpeg的最新版本,因为对于一些操作系统,比如Linux系统(无论是Ubuntu还是RedHat),如果使用系统提供的软件库安装fimpeg时会发现其版本相对比较老旧,比如使用apt-getinstall fmpeg或者yuminstallfmpeg安装fmpeg,那么默认支持的版本都很老,有些新的功能并不支持,如一些新的封装格式或者通信协议。
1.8FFmpeg编码支持与定制
FFmpeg本身支持一些音视频编码格式、文件封装格式与流媒体传输协议,但是支持的数量依然有限,FFmpeg所做的只是提供一套基础的框架,所有的编码格式、文件封装格式与流媒体协议均可以作为FFmpeg的一个模块挂载在FFmpeg框架中。这些模块以第三方的外部库的方式提供支持,可以通过FFmpeg源码的configure命令查看FFmpeg所支持的音视频编码格式、文件封装格式与流媒体传输协议,对于FFmpeg不支持的格式,可以通过configure--help查看所需要的第三方外部库,然后通过增加对应的编译参数选项进行支持。
代码语言:javascript复制configure--help
二.FFmpeg工具使用基础
FFmpeg中常用的工具主要是fimpeg、fprobe、ffplay,它们分别用作多媒体的编解码工具、内容分析工具和播放器。
- fpeg主要用于音视频编解码
- ffprobe主要用于音视频内容分析
- fplay主要用于音视频播放、可视化分析
2.1 fmpeg常用命令
fmpeg在做音视频编解码时非常方便,所以在很多场景下转码使用的是fmpeg,通过ffmpeg--help可以看到fmpeg常见的命令大概分为6个部分,具体如下。
- ffmpeg信息查询部分
- 公共操作参数部分
- 文件主要操作参数部分
- 视频操作参数部分
- 音频操作参数部分
- 字幕操作参数部分
代码语言:javascript复制通过ffmpeg--help查看到的help信息是fmpeg命令的基础信息,如果想获得高级参数部分,那么可以通过使用ffmpeg --help long参数来查看,如果希望获得全部的帮助信息,那么可以通过使用ffmpegg --help full参数来获得。 看fmpeg的版本,包括子模块的详细版本信息,如libavformat、libavcodec、libavutil、libavfilter、libswscale、libswresample的版本。
ffmpeg --help long
ffmpegg --help ful
2.2ffprobe常用命令
在FFmpeg套件中,除了fmpeg作为多媒体处理工具之外,还有ffprobe多媒体信息查看工具,ffprobe主要用来查看多媒体文件的信息. fprobe常用的参数比较多,可以通过fprobe--help来查看详细的帮助信息。
代码语言:javascript复制fprobe--help
使用fprobe-showpacketsinput.flv查看多媒体数据包信息:
通过showpackets查看的多媒体数据包信息使用PACKET标签括起来,其中包含的信息主要如表
字段 | 说明 |
---|---|
.codec_type | 多媒体类型,如视频包、音频包等 |
Stream index | 多媒体的stream索引 |
PIS | 多媒体的显示时间值 |
pIs_time | 根据不同格式计算过后的多媒体的显示时间 |
dts | 多媒体解码时间值 |
dts time | 根据不同格式计算过后的多媒体解码时间 |
duration | 多媒体包占用的时间值 |
duration timc | 根据不同格式计算过后的多媒体包所占用的时间值 |
size | 多媒体包的大小 |
pos | 多媒体包所在的文件偏移位置 |
flags | 多媒体包标记,如关键包与非关键包的标记 |
除了packets与data之外,ffprobe还可以分析多媒体的封装格式,通过ffprobe-show_formatoutput.mp4命令可以查看多媒体的封装格式,其使用FORMAT标签括起来显示:
下面对输出信息关键字段进行说明,具体见表
字段 | 说明 |
---|---|
filename | 文件名 |
nb streams | 媒体中包含的流的个数 |
nbprograms | 节目数(相关的概念在2.3节中会有详细的介绍) |
format name | 使用的封装模块的名称 |
format long name | 封装的完整名称 |
start time | 媒体文件的起始时间 |
duration | 媒体文件的总时间长度 |
size | 媒体文件的大小 |
bit rate | 媒体文件的码率 |
通过ffprobe-show_framesinput.dv命令可以查看视频文件中的赖信息,输出的顺信息将使用FRAME标签括起来
代码语言:javascript复制[FRAME]
media_type=video
stream index=0
key_frame=l
pkt pts=80
pkt_pts_time=0.080000
pkt dts=80
pkt dts_time=0.080000
begt effort timegtamp=80
best effort timestamp_time=0.080000
pkt_duration=N/A
pkt duration time=N/A
pkt_pog=344
pkt_size=8341
width=1280
height=714
pix fmt=yuv420p
6ample_aspect_ratio=1:1
pict_type=T
coded picture number=0
display picture number=0
interlaced frame=0
top_field first=o
repeat pict=0
[/FRAME]
通过-show_frames参数可以查看每一帧的信息,下面就来介绍一下其中重要的信息,具体见表
属性 | 说明 | 值 |
---|---|---|
media type | 的类型(视频、音频,字幕等) | video |
stream index | 帧所在的索引区域 | 0 |
key_frame | 是否为关键顿 | 1 |
pktpts | Frame包的pts | 0 |
pkt pis time | Frame包的ps的时间显示 | 0.08 |
pkt dts | Frame包的dts | 80 |
pkt dis time | Frame包的dts的时间显示 | 0.08 |
pkt duration | Frame包的时长 | NIA |
pkt duration time | Frame包的时长时间显示 | NIA |
pkt pos | Frame包所在文件的偏移位置 | 344 |
width | 显示的宽度 | 1280 |
height | 显示的高度 | 714 |
pix fimt | 倾的图像色彩格式 | yuv420p |
piet type | 侦类型 | I |
通过-show streams参数可以查看到多媒体文件中的流信息,流的信息将使用STREAM标签括起来:
1eve1=31如以上输出内容所示,从中可以看到流的信息,具体属性及说明见表
属性 | 说明 | 值 |
---|---|---|
index | 流所在的索引区域 | 0 |
codecnamc | 编码名 | h264 |
codee long name | 编码全名 | MPEG-4 part 10 |
profile | 编码的profile | High |
属性 | 说明 | 值 |
level | 编码的level | 31 |
has b frames | 包含B赖信息 | 2 |
codec type | 编码类型 | video |
codec timebase | 编码的时间截计算基础单位 | 1750 |
pix fmt | 图像显示的色彩格式 | yuv420p |
codedwidth | 图像的宽度 | 1280 |
coded height | 图像的高度 | 714 |
codec tag string | 编码的标签数据 | [0][0][0][0] |
Tframe rateavg frame rate | 实际硕率平均帧率 | 25/125/ |
time base | 时间基数(用来进行timestamp计算) | 1/1000 |
bit rate | 码率 | 200000 |
xbit ratemax | 最大码率 | N/A |
nb_frames | 帧数 | N/A |
2.3 ffplay常用命令
在编译旧版本FFmpeg源代码时,如果系统中包含了SDL-1.2版本,就会默认将ffplay编译生成出来,如果不包含SDL-1.2或者版本不是SDL-l.2时,将无法生成ffplay文件,所以,如果想使用flay进行流媒体播放测试,则需要安装SDL-1.2.而在新版本的FFmpeg源代码中,需要SDL-2.0之后的版本才能有效生成ffplay.。 在FFmpeg中通常使用ffplay作为播放器,其实ffplay同样也可以作为很多音视频数据的图形化分析工具,通过ffplay可以看到视频图像的运动估计方向、音频数据的波形等.
下表是ffplay的基础参数
参数 | 说明 |
---|---|
x | 强制设置视频显示窗口的宽度 |
y | 强制设置视频显示窗口的高度 |
s | 设置视频显示的宽高 |
fs | 强制全屏显示 |
an | 屏蔽音频 |
vn | 屏蔽视频 |
sn | 屏蔽字幕 |
ss | 根据设置的秒进行定位拖动 |
t | 设置播放视频/音频的长度 |
bytes | 设置定位拖动的策略,0为不可拖动,1为可拖动,-1为自动 |
nodisp | 关闭图形化显示窗口 |
f | 强制使用设置的格式进行解析 |
window title | 设置显示窗口的标题 |
af | 设置音频的滤镜 |
codec | 强制使用设置的codec进行解码 |
autorotate | 自动旋转视频 |
下面这个表是ffplay高级参数
参数 | 说明 |
---|---|
ast | 设置将要播放的音额流 |
vst | 设置将要播放的视频流 |
sst | 设置将要播放的字幕流 |
stats | 输出多媒体播放状态 |
fast | 非标准化规范的多媒体兼容优化 |
sync | 音视频同步设置可根据音频时间、视频时间或者外部扩展时间进行参考 |
autoexit | 多媒体播放完毕之后自动退出fplay,fplay默认播放完毕之后不退出播放器 |
cxitonkeydown | 当有按键按下事件产生时退出ffplay |
exitonmousedown | 当有鼠标按键事件产生时退出fplay |
loop | 设置多媒体文件循环播放的次数 |
framedrop | 当CPU资源占用过高时,自动丢顿 |
infbuf | 设置无极限的播放器buffer,这个选项常见于实时流媒体播放场景 |
vf | 视频滤镜设置 |
acodec | 强制使用设置的音频解码器 |
vcodec | 强制使用设置的视频解码器 |
scodec | 强制使用设置的字幕解码器 |
第3章 FFmpeg转封装
(累了orz,下次更,有人看可以关注回复我下,更有动力)
3.1.1MP4格式标准介绍
MP4格式标准为IS0-14496Part12、IS0-14496Part14,标准内容并不是特别多,下面就来着重介绍一些重要的信息。
如果要了解MP4的格式信息,首先要清楚几个概念,具体如下。
MP4文件由许多个Box与FullBox组成
每个Box由Header和Data两部分组成
FullBox是Box的扩展,其在Box结构的基础上,在Header中增加8位version标志和24位的f1ags标志
Header包含了整个Box的长度的大小(size)和类型(type),当size等于O时,代表这个Box是文件的最后一个Box。当siz等于1时,说明Box长度需要更多的位来描述,在后面会定义一个64位的largesize用来描述Box的长度。当Type为uuid时,说明这个Box中的数据是用户自定义扩展类型
Data为Box的实际数据,可以是纯数据,也可以是更多的子Box
当一个Box中Data是一系列的子Box时,这个Box又可以称为Container(容器)
Box MP4文件中Box的组成可以用表3-1所示的列表进行排列,表3-1中标记“V”的Box为必要Box,否则为可选Box。
第4章FFmpeg转码
4.1.2H.264编码举例
3.H.264的proffle与level设置
这里的profile(档次)与level(等级)的设置与H.264标准文档ISO-14496-Part10中描述的profile、level的信息基本相同,×264编码器支持Baseline、Extented、Main、High、High10、High422、High444共7种profile参数设置,根据profile的不同,编码出来的视频的很多参数也有所不同,具体的情况可以参考表。
4.4FFmpeg输出AAC
在音视频流中,无论直播与点播,AAC都是目前最常用的一种音频编码格式,例如RTMP直播、HLS直播、RTSP直播、FLV直播、FLV点播、MP4点播等文件中都是常见的AAC音视频。
与MP3相比,AAC是一种编码效率更高、编码音质更好的音频编码格式,常见的使用AAC编码后的文件存储格式为m4a,如在iPhone或者iPad中即为m4a.FFmpeg可以支持AAC的三种编码器具体如下。
aac:FFmpeg本身的AAC编码实现
libfaac:第三方的AAC编码器
·libfdk_aac:第三方的AAC编码器
后两种编码器为非GPL协议,所以使用起来需要注意,在预编译时需要注意采用nonfree的支持。
4.4.4AAC音频质量对比
AAC-LC的音频编码可以采用libfaac、libfdk aac、FFmpeg内置AAC三种,其质量顺序排列如下。
libfdk aac音频编码质量最优
FFmpeg内置AAC编码次于libfdk aac但优于libfaac
libfaac在FFmpeg内置AAC编码为实验品时是除了libfdk_aac之外的唯一选择
第5章 FFmpeg流媒体
AAC-LC的音频编码可以采用libfaac、libfdk_aac、FFmpeg内置AAC三种,其质量顺序排列如下
libfdkaac音频编码质量最优
FFmpeg内置AAC编码次于libfdkaac但优于libfaac
libfaac在FFmpeg内置AAC编码为实验品时是除了Iibfdkaac之外的唯一选择。
随着互联网、移动互联网的发展,人们获取信息的方式开始从纸质媒体转向互联网文字媒体,又从文字媒体转向音视频流媒体。音视频流媒体又称为“流媒体”,而用于处理流媒体的压缩、录制、编辑操作,开源并强大的工具屈指可数,FFmpeg就是常见的流媒体处理工具。
3.解析trak子容器
trak容器中定义了媒体文件中的一个track的信息,一个媒体文件中可以包含多个trak,每个trak都是独立的,具有自己的时间和空间占用的信息,每个trak容器都有与它关联的media容器描述信息。trak容器的主要使用目的具体如下。
包含媒体数据的引用和描述(media track)
包含modifier track信息
流媒体协议的打包信息(hint track),hint track可以引用或者复制对应的媒体采样数据
hint track和modifier track必须保证完整性,同时要与至少一个media track一起存在。
一个trak容器中要求必须要有一个Track Header Atom(tkhd)、一个Media Atom(mdia),其他的Atom都是可选的,例如如下的atom选项。
Track剪辑容器:Track Clipping Atom(clip)
Track画板容器:Track Matte Atom(matt)
Edit容器:Edit Atom(cdts)
Track参考容器:Track Reference Atom(tref)
Track配置加载容器:Track Load Settings Atom(load)
Track输出映射容器:Track Input Map Atom(imap)
用户数据容器:User Data Atom(udta)