目录
1. FFmpeg工具使用基础
FFmpeg常用的工具主要是ffmpeg、ffprobe、ffplay,他们可用作多媒体的编解码、内容分析工具以及播放器。
1.1 ffmpeg常用命令
ffmpeg在做音视频编解码时非常方便,在很多场景下转码可以使用ffmpeg,通过ffmpeg --help可以看到 ffmpeg 常见的命令大概分为 6 个部分,具体如下 :
- ffmpeg 信息查询部分
- 公共操作参数部分
- 文件主要操作参数部分
- 视频操作参数部分
- 音频操作参数部分
- 字幕操作参数部分
ffmpeg 信息查询部分的主要参数具体如下:
通过ffmpeg --help可以查看ffmpeg命令的基础信息,如果想获得高级参数部分,那么可以通过使用ffmpeg --help long参数来查看,若想获得全部帮助信息,可以通过ffmpeg --help full来获取。
使用ffmpeg转码,有时会遇到无法解析的视频文件或无法生成视频文件,报错提示不支持生成对应的视频文件,这时可以通过ffmpeg -formats参数来查看ffmpeg是否对相应的视频格式表示支持:
从上面输出的信息可以发现,输出内容分为三部分,具体如下:
- 第一列是多媒体文件封装格式的 Demuxing 支持与 Muxing 支持
- 第二列是多媒体文件格式
- 第三列是文件格式的详细说明
使用ffmpeg命令时,可能会出现ffmpeg不支持某种编码格式或者某种编码格式错误提示信息,一般出现这类情况的原因是没有把相应的编码器或解码器集成到ffmpeg中。比如,我想查看ffmpeg是否支持H.265编码或者解码,可以通过ffmpeg -codecs来查看所有的编解码信息;若想知道对应的编码器,可通过ffmpeg -encoders查看ffmpeg是否支持;若是解码,则可以用ffmpeg -decoders查看。
输出的信息每列代表的含义:
- 第一列中第一个字段表示编码器是音频、视频还是字母,第二个字段表示帧级别的多线程支持,第三个字段表示分片级别的多线程,第四个字段表示该编码为试验版本,第五个字段表示draw horiz band模式支持,第六个字段表示直接渲染模式支持
- 第二列表示编码格式
- 第三列是编码格式的详细说明
除此之外,ffmpeg还支持查看支持哪些滤镜。可通过ffmpeg -filters来查看
输出信息的内容分为四列,具体如下:
- 第一列总共有 3 个字段,第一个字段是时间轴支持,第二个字段是分片线程处理支持,第三个字段是命令支持
- 第二列是滤镜名
- 第三列是转换方式,如音频转音频,视频转视频,创建音频,创建视频等操作
- 第四列是滤镜作用说明
通过ffmpeg --help full命令,可以查看 ffmpeg 支持的所有封装(demuxer 、 muxer)格式,编解码器( encoders 、decoders )和滤镜处理器(filters)。如果要了解ffmpeg支持的具体某一种demuxer、muxer类型,可以通过ffmpeg -h查看该类型的详细参数,包括encoder、decoder 所支持的操作参数,filter 所支持的参数,例如:
查看H.265解码器的参数支持(ffmpeg -h decoder=h264):
1.1.1 ffmpeg封装转换
ffmpeg的封装转换(转封装)功能包含在AVFomrat模块中,通过libavformat库进行Mux和Demux操作。
下表为AVFormatContext主要参数说明
参数 | 类型 | 说明 |
avioflags | 标记 | format的缓冲设置, 默认为0, 就是有缓冲 |
direct | 无缓冲状态 | |
probesize | 整数 | 在进行媒体数据处理前获得文件内容的大小,可用在预读取文件头时提高速度,也可以设置足够大的值来读取到足够多的音视频数据信息 |
fflags | 标记 | |
flush_packets | 立即将packets数据刷新写人文件中 | |
gen pts | 输出时按照正常规则产生pts | |
no fill in | 不填写可以精确计算缺失的值 | |
ign dts | 忽略dts | |
discard corrupt | 丢弃损坏的帧 | |
sort dts | 尝试以dts的顺序为准输出 | |
keep side | 不合并数据 | |
fast seek | 快速seek(定位) 操作, 但是不够精确 | |
lat m | 设置RTP MP4L_ATM生效 | |
no buffer | 直接读取或写出, 不存人buffer, 用于在直播采集时降低延迟 | |
bit exact | 不写人随机或者不稳定的数据 | |
seek2any | 整数 | 支持随意位置seek, 这个seek不以keyframe为参考 |
analyzeduration | 整数 | 指定解析媒体所需要花销的时间,这里设置的值越高,解析越准确,如果在直播中为了降低延迟,这个值可以设置得低一些 |
codec_whitelist | 列表 | 设置可以解析的codec的白名单 |
format_whitelist | 列表 | 设置可以解析的format的白名单 |
output_ts_offset | 整数 | 设置输出文件的起始时间 |
1.1.2 ffmpeg的转码参数
ffmpeg编解码部分的功能主要通过模块AVCodec来完成,通过libavcodec库进行编码(Encode)和解码(Decode)操作。多媒体编码格式的种类有很多,但还是有很多通用的基本操作参数设置。
通过命令ffmpeg --help full可以看到AVCodecContext参数列表信息,具体可见下表:
参数 | 类型 | 说明 |
b | 整数 | 设置音额与视频码率,可以认为是音视频加起来的码率,默认为200kbit/s 使用这个参数可以根据b:v设置视频码率, b:a设置音频码率 |
ab | 整数 | 设置音频的码率,默认是128kbit/s |
g | 整数 | 设置视频GOP (可以理解为关键帧间隔)大小,默认是12帧一个GOP |
ac | 整数 | 设置音频通道数,默认为 0 |
bf | 整数 | 设置连续编码为B帧的个数,默认为0 |
ar | 整数 | 设置音频采样率,默认为0 |
maxrate | 整数 | 最大码率设置,与bufsize一同使用即可 |
Minrate | 整数 | 最小码率设置,配合 max.rate 与 bufsize 可以设置为 CBR 模式,平时很少使 用,默认为 0 |
bufsize | 整数 | 设置控制码率的buffer的大小,默认为0 |
keyint min | 整数 | 设置关键锁最小间隔,默认为25 |
scthreshold | 整数 | 设置场景切换支持,默认为0 |
me threshold | 整数 | 设置运动估计阀值,默认为0 |
mb threshold | 整数 | 设置宏块阈值,默认为0 |
profile | 整数 | 设置音视频的profile,默认为-99 |
level | 整数 | 设置音视频的level,默认为-99 |
timecode_frame_start | 整数 | 设置GOP帧的开始时间,需要在non-drop |
channel_layout | 整数 | 设置音频通道的布局格式 |
threads | 整数 | 设置编解码工作的线程数 |
1.1.3 ffmpeg的转码原理
ffmpeg的转码主要原理如下:
读取文件→解封装→解码→转换参数→新编码→封装→写入文件
通过AVCodec与AVFormat的操作参数进行封装与编码的改变,比如以下例子
ffmpeg -i test.mp4 -vcodec mpeg4 -b:v 200k -r 15 -an output.mp4
命令行执行后输出的基本信息如下:
可以发现在Stream #0:0 那一行码率从692kbit/s转换为200kbits/s,fps从22.87fps降到了15 fps
1.2 ffprobe常用命令
ffprobe主要用来查看多媒体文件的信息,我们可以通过ffprobe --help来查看详细的帮助信息。
在这里举一个例子,使用ffprobe -show_packets input.mp4来查看视频信息
在这里,我们可以发现查看的多媒体数据包信息用PACKET标签包裹起来了,而在这里面的参数意义可以参照下表:
字段 | 说明 |
codec type | 多媒体类型,如视频包、音频包等 |
stream index | 多媒体的stream索引 |
pts | 多媒体的显示时间值 |
pts time | 根据不同格式计算过后的多媒体的显示时间 |
dts | 多媒体解码时间值 |
dts time | 根据不同格式计算过后的多媒体解码时间 |
duration | 多媒体包占用的时间值 |
duration time | 根据不同格式计算过后的多媒体包所占用的时间值 |
size | 多媒体包的大小 |
pos | 多媒体包所在的文件偏移位置 |
flags | 多媒体包标记,如关键包与非关键包的标记 |
同时也可以用ffprobe -show_data -show_packets input.flv组合参数来进一步查看包中具体数据:
通过ffprobe读取packets来进行对应的数据分析,使用show_packets与show_data配合可以进行更加精确的分析 。
除了packets与data之外,probe还可以分析多媒体的封装格式,通过ffprobe -show_format output.mp4命令可以查看多媒体的封装格式,使用 FORMAT 标签括起来显示
其中关键字段说明如下:
字段 | 说明 |
filename | 文件名 |
nb_streams | 媒体中包含的流的个数 |
nb_programs | 节目数 |
format_name | 使用的封装模块的名称 |
format_long _name | 封装的完整名称 |
start_time | 媒体文件的起始时间 |
duration | 媒体文件的总时间长度 |
size | 媒体文件的大小 |
bit_rate | 媒体文件的码率 |
通过表的对应关系,我们可以知道这个视频文件中包含两个流通道,文件封装格式可能为move,mp4,m4a,3gp,3g2,mj2。为什么会有这么多种可能的格式呢?因为这几种格式在ffmpeg中所识别的标签基本相同,所以才会显示多种。
此外还有-show_frames -show_streams,他们分别用来查看(每一) 帧的信息、查看多媒体文件中的流信息。其对应字段的说明如下:
frame字段说明 | |
属性 | 说明 |
media_type | 顿的类型(视频、音频、字幕等) |
stream_index | 帧所在的索引区域 |
key_frame | 是否为关键树 |
pkt_pts | Frame包的pts |
pkt_pts_time | Frame包的pts的时间显示 |
pkt_dts | Frame包的dts |
pkt_dts_time | Frame包的dts的时间显示 |
pkt duration | Frame包的时长 |
pkt duration time | Frame包的时长时间显示 |
pkt pos | Frame包所在文件的偏移位置 |
width | 帧显示的宽度 |
height | 帧显示的高度 |
pix fmt | 帧的图像色彩格式 |
pict type | 帧类型 |
stream字段说明 | |
属性 | 说明 |
index | 流所在的索引区域 |
codec_name | 编码名 |
codec_long_name | 编码全名 |
profile | 编码的profile |
level | 编码的level |
has_b_frames | 包含B帧信息 |
codec_type | 编码类型 |
codec_time_base | 编码的时间戳计算基础单位 |
pix_imt | 图像显示的色彩格式 |
coded_width | 图像的宽度 |
coded_height | 图像的高度 |
codec_tag_string | 编码的标签数据 |
ffprobe 使用前面的参数可以获得 key-value 格式的显示方式,但是阅读起来因习惯不同,有的人认为不方便;如果要进行格式化的显示,就需要用到 ffprobe -print_format 或者 ffprobe -of 参数来进行相应的格式输出,而-print_format支持多种格式输出,包括 XML、INI、JSON、CSV、FLAT等 。 下面列举几种常见的输出格式指令
- ffprobe -of xml -show_streams input.flv XML 输出格式
- ffprobe -of ini -show_streams input.flv INI 输出格式
- ffprobe -of flat -show_streams input.flv FLAT输出格式
- ffprobe -of json -show _packets input.flv JSON 输出格式
- ffprobe -of csv -show_packets input.flv CSV 输出格式
在开发时可以根据需要,输出符合业务的格式,方便分析处理。