阶段性学习总结--ffmpeg

来源:互联网 发布:mysql dba 前景 编辑:程序博客网 时间:2024/05/16 18:13

阶段性学习总结

        .自接触这个新鲜事物FFmpeg以来,前后也有近两个月的时间。那么为什么我会接触到这个软件呢?两个月的时间,我学习到了什么呢?仔细理了一下思绪,大致可以从了解,运用,学习,设标,验证,收获这六个方面来叙述。

1.了解概况

1.1、了解背景

起先接收到的任务是用FFmpeg软件生成一段h264的测试码流和学习FFmpeg的使用。
那么什么是FFmpeg呢?官网上的解释是A complete,cross-platform solution to record, convert and stream audio and video,翻译过来就是一个用于记录、转换和流式传输音频和视频的完整跨平台解决方案。
根据字面的意思,我将它理解为用来记录、转换数字视频、音频,能够将它们转换为流的一套可跨平台使用的工具。
什么是h264码流呢?书上解释为H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准。这个标准通常被称之为H.264/AVC,而明确的说明它两方面的开发者。
我从字面将其理解为h264是在压缩和传输方面具有更高效率的编码器,较其他编码其相比,因这两个有点被广泛应用。

1.2、了解作用

FFmpeg有非常强大的功能,核心功能包括视频采集,视频格式转换,视频抓取图片,添加水印等等。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,源文件中里面的很多文件都是从头开发的。我要学习的主要是H264视频码流的转换和分析。FFmpeg项目是由可执行文件和源文件两部分组成的:
以下部分是可执行文件:
ffmpeg  视频文件转换命令行工具。
ffserver  基于HTTP、RTSP用于实时广播的多媒体服务器,也支持时间平移(PS:没用过)
ffplay   用SDL和FFmpeg库来开发的一个简单的媒体播放器
以下部分是源:
libavcodec  一个包含了所有FFmpeg音视频编解码器的库,为了保证最优性能和高可复用性,大多数编码解码器从头开发的。
libavformat  用于各种音视频封装格式的生成和解析
libavfilter  filter音视频滤波器的开发
libavutil  包含一些公共的工具函数的使用库
libavsample  音视频封装编码格式预设
libswzesample 原始音频格式转码

1.3、了解概念

提到视频编码,那么其中的一些基本概念就不得不提了。
码率,比特率(码率)是一个确定整体视频/音频质量的参数,和视频质量成正比。
帧,就是一副静止的画面。常说的帧数,就是在1秒钟时间里传输的图片的帧数,也可以理解为图形处理器在每秒钟能够刷新几次,通常用fps(Frames Per Second)表示,也就是帧率。
分辨率,指视频宽高的像素数值。通常视频分辨率的数值宽高比要等于画面比例,不然视频文件就会产生黑边。标准1080P的分辨率为1920×1080,帧速率为60fps,也就是真高清。
码率,比特率是指每秒传送的比特(bit)数。比特率越高,传送数据速度越快。
容量,容量 = 码率 * 时间。这里的码率说的是视频码率+音频码率
比如一个文件20.8M,时长1分钟,那么,码率就是:
biterate = 20.8Mbit*8/60s = 20.8*1024*1024*8 bit/60s= 2831Kbps,一般音频的码率只有固定几种,比如是128Kbps,那么,video的就是  video biterate = 2831Kbps -128Kbps = 2703Kbps。
I、B、P帧
I帧,即关键帧。关键帧是,构成一个帧组(GOP,Group of Picture)的第一个帧。
P帧,即未来单项预测帧,只储存与之前一个已解压画面的差值。 
B帧,即双向预测帧,除了参考之前解压过了的画面外,亦会参考后面一帧中的画面信息。
(注意点:参数概念一定要搞清楚,非常重要)

1.4、了解句法

H264的句法比较多,在SPS(Sequence Parameter Set)中常见的如下:
(profile_idc):档次(baseline、main、extend、high)
(cosntraint_set0_flag)(cosntraint_set1_flag)(cosntraint_set2_flag)(cosntraint_set3_flag)四个约束句法,0可以不遵从相关简表规定
(reserved_zero_4bits)预留4个0的位置
(level_idc)级别
(分别是1、1.1、1.2、1.3//2、2.1、2.2//3、3.1、3.2//4、4.1、4.2//5、5.1)
(seq_parameter_set_id)序列参数集ID=0
(chroma_format_idc)色度格式
(bit_depth_luma_minus8)亮度比特=8 bits,亮度量化参数范围偏移
(bit_depth_chroma_minus8)色度比特=8 bits,色度量化参数范围偏移
(qpprime_y_zero_transform_bypass_flag)不使用变换旁路操作
(seq_scaling_matrix_present_flag)默认缩放比例列表
(log2_max_frame_num_minus4):最多帧数=2^4=16
(pic_order_cnt_type)图像顺序类型
(log2_max_pic_order_cnt_lsb_minus4)最大图像顺序数低位=2^4=16
(num_ref_frames)参考帧的最大数
(gaps_in_frame_num_value_allowed_flag)帧数差异标记
(pic_width_in_mbs_minus1)图像宽度
(pic_height_in_map_units_minus1)图像高度
(frame_mbs_only_flag)只是帧宏块,没有场宏块
(direct_8x8_inference_flag)B帧 运动矢量计算时用
(frame_cropping_flag)帧剪切偏移参数
(vui_parameters_present_flag)有VUI信息,默认矩阵系数2
一般情况下在sps中,能经常性用到的句法元素就是这么20句左右,不排除其他会用到的句法,但是都是比较少的。当然还有pps句法,这里就不一一列举了。


2.设计目标

2.1、设计目标

借用ffmpeg能够完成什么呢?从之前叙述的作用来看,ffmpeg可以实现的功能太多太多。那么我根据自己使用情况频率设计了以下两个小目标:
(1)、对视频的格式进行转换;
(2)、对句法元素值进行精确控制;

2.2、设计内容

所有的目标都可以在linux大环境下进行,首先下载该应用软件,搭建软件应用环境;然后通过资料来查看ffmpeg软件的参数有那些;了解参数的作用;参数组合使用,实现相应的功能;检测相应的生成结果,利用工具判断最后结果是否符合预期,若不符合,则说明不符合点,以及原因,若符合,则保存证明数据和结果。

3.学习工具

3.1、学习FFmpeg

之前也说到FFmpeg软件中包含了大量的从头开发的库文件,方便代码的移植。比较麻烦的是操作基于命令行,操作相对比较复杂,这是所有的命令行文件所具有的问题,但也因为是基于命令行所以变化的更加灵活。
下载的该工具的时候我们选择Linux版本,其中只包含了几个个可执行文件(ffmpeg、ffprobe、ffplay、ffserver)。
命令语法如下:
ffmpeg [global_options]{[input_file_options] -i input_file}{[output_file_options] output_file}
ffmpeg[全局选项][输入文件选项] -i [输入文件][输出文件选项][输出文件]
注意:(使用ffmpeg转码时,输入文件、输出文件必需要有,某些输入文件前面必需要添加一些修饰的参数,例如.yuv文件,需要在输入的之前添加分辨率参数。)
常用参数选项说明:因为只需要对视频流进行操作编码,所以只对通用参数和视频类相关参数做出罗列。

3.1.1、通用参数

-f fmt强制格式
-c codec编解码器名称
-codec codec编解码器名称
-pre preset预设名称
-t持续时间记录或转码音频/视频的“持续时间”秒
-to time_stop记录或转码停止时间
-fs limit_size设置限制文件大小(以字节为单位)
-ss time_off设置开始时间偏移量
-seek_timestamp启用/禁用用-ss查询时间戳
-filter filter_graph设置流过滤器

3.1.2、视频参数

-b <bits per second> 设置比特率bit_rate,缺省 200kb/s
-r <int >设置帧频(fps) 缺省默认为25
-s <w*h> 设置分辨率 缺省 160*128.下面的简写也可以直接使用:
Sqcif 128*96  qcif 176*144  cif 352*288  4cif 704*576
-aspect <int> 设置横纵比 4:3 16:9 或 1.3333 1.77773
-crop 设置切除大小 
-pad 补充条大小和颜色
-vn 不做视频记录
-bt <int>设置视频码率容忍度kbit/s
-maxrate <bits> 设置最大视频码率max_rate容忍度,以比特/秒设置GOP最大比特率。 
-minrate <bits> 设置最小视频码率容忍度
-bufsize<bits> 设置码率控制缓冲区buffer_size大小
-vcodec codec 强制使用codec编解码方式。如果用copy表示原始编解码数据必须
被拷贝。
-sameq 使用同样视频质量作为源(VBR)
-pass n 选择处理遍数(1或者2)。两遍编码非常有用。第一遍生成统计信息,第
二遍生成精确的请求的码率

3.1.3、高级选项

-g <frames> 设置图像组gop_sizes大小
-keyint_min <int> 设置IDR帧的最小间隔(和-g、-sc_threshold联合使用可以避免出现gop出现不想要的数值—GOP对齐)
sc_threshold 设置场景阀值 用来设置gop对齐和以上两个参数联合使用最好。在遇到场景切换的情况时,H.264编码器会自动强制插入一个I帧,此时实际的GOP值被缩短了。
-refs<int> 设置参考帧的每个P帧 能使用的参考帧数。范围是0-16
-subq<int> 设置子像素运动估计子量
-intra 仅适用帧内编码
-me_range<int>设置搜索范围
-qmin <int> 最小视频量化标度(VBR)
-qmax <int> 最大视频量化标度(VBR)
-qdiff <int> 量化标度间最大偏差 (VBR)设置max_dqiff
-qblur<float> blur 视频量化标度柔化(VBR)
-qcomp<float> compression 视频量化标度压缩(VBR) qcomp(bias-pct)
-me method < umh epzs full hex dia esa tesa>设置运动估计的方法


在ffmpeg中参数比较的多,大部分参数不会经常性用到,以上参数只是自己在视频编码时可能会用到的部分,并不代表其他内容。
(注意点:参数作用最好是自己去试试看看效果如何,比如说在什么场景下能够应用下什么参数。修改参数会产生什么效果。举例来说:给出一个随机视频文件,如果该文件的视频比较模糊,你可以想到修改什么参数,怎么设置该参数。视频卡顿,又该修改什么参数)

3.1.4、参数查找

ffmpeg编解码时非常的方便。通过 ffmpeg -help操作可以看到ffmpeg中常见的命令。总的来说ffmpeg命令大概可以分为六部分:
(1)ffmpeg信息查询部分
(2)公共操作的参数部分
(3)视频操作部分
(4)音频操作部分
(5)字幕操作部分
(6)文件操作部分(这部分不怎么清楚)
通过ffmpeg --help查到的help信息应该是基础信息,如果想要看到高级的或者说更多的信息,可以通过使用ffmpeg  --help long参数来查看;如果想要看多全部发信息那就使用ffmpeg --help full参数来看到所有的信息。
通过使用-version查看ffmpeg的版本,包含libavformat、libavcodec、libavutil、libavfilter、libswscale、libswresample的版本。
使用ffmpeg转码的时候,发现不能解析视频文件或者无法生成文件,或者不支持生成对应文件时,需要使用ffmpeg -formats来查看ffmpeg是否支持对应的格式。

3.2、学习Elecard

Elecard.Streameye.Tools,一个强大的视频序列或者码流分析软件,YUV分析,264文件分析软件,H.264视频编解码学习必备的东西。Elecard Stream工具套中这两个工具用的比较多,相对的介绍一下,其他几个不常用,就不介绍。

3.2.1、Elecard StreamEye

Elecard StreamEye Suite是一套用于专业视频压缩领域的功能强大的工具 ,能够帮助用户进行有效的对于视频序列的深入分析。感觉STREAM EYE的界面更加亲民,而且它的视频窗口可缩放,比较好操作。编码视频的可视化表现,流结构分析,这些流可以是MPEG-1/2/4 or AVC/H.264 VES(视频基本流)、SS(MPEG1的系统流)、PS(MPEG2的程序流)、TS(mpeg2的传输流)。
 
图3.2.1 StreamEye

3.2.2、Stream Analyzer

用于编码媒体流的语法分析,以及人类可读形式的展示。可以操作MPEG-1 Video/Audio, MPEG-2 Video/Audio, AAC, AC-3 and AVC/H.264 文件。
 

图3.2.2 Stream Analyzer

3.3、学习JM

什么是JM?JM编码程序是H.264的官方测试源码,由德国hhi研究所负责开发。JM实现了H.264所有的特性,几乎所有的学术研究的算法都是在JM基础上实现并和JM进行比较。但其程序结构冗长,只考虑引入各种新特性以提高编码性能,忽视了编码复杂度,其编码复杂度较高。
命令语法如下:
lencod[-h][-d defenc.cfg]{[-f curenc1.cfg] [-f curencN.cfg]}{[-p EncParam1=EncValue1][-p EncParamM=EncValueM]}
-h打印参数用法。
-d使用<defenc.cfg>作为参数初始化的默认文件。如果未使用,则文件默认为本地目录中的“encoder.cfg”。
-f读取<curencM.cfg>以复位所选的编码器参数。可以使用多个文件来设置不同的参数。
-p将参数<EncParamM>设置为<EncValueM>。<EncParamM>的条目不区分大小写。


(说明点:本文主要讲述ffmpeg,JM软件不细说明,不常用,参数比较多,有兴趣可以参考官方文档,以下主要叙述编译环境的搭建。)

3.3.1、编译环境搭建

下载压缩文件并且解压,进入文件夹;找到.sln文件双击打开,根据提示一步步向下走;在之后打开的页面中找到lencod项目,设置其为启动项;设置lencod的属性,修改输出目录和工作目录为bin,保存退出;右击lencod项目,选择仅用于项目中仅生成选项,生成相应的支撑文件;在bin目录下添加输入文件“xxx.yuv”文件,即可编译运行程序。
打开支撑文件encoder.cfg,可以看到几大部分,例如:"Files"、"Encoder Control"、"B slices"等等,输入文件的名字可以在files中看到,修改其名,就可以使得程序运行成功。
运行命令行程序和在Windows环境下运行ffmpeg类似,这里不做过多说明。


4.实现目的

能利用ffmpeg转换的格式比较的多,本章节主要叙述对视频的各类操作。

4.1、转换格式

利用ffmpeg转换视频格式,例如:将1.avi转换为out.mp4的文件。

4.1.1、默认参数

(只有输入输出参数,其他参数又系统默认未指定)
根据上述要求给出命令,例如:
ffmpeg -i 1.avi out.mp4 (1)
在命令行(1)中,ffmpeg表示的是ffmpeg软件中的ffmpeg可执行程序,ffmpeg的作用是视频文件转换命令工具;
-i + 1.avi表示输入,输入文件为1.avi;
out.mp4 表示输出文件名和格式。
(1)命令是ffmpeg中最简单的命令,只包含了输入文件输出文件,在转化过程中其他的内容例如profile、level、s、gop、fps等等全部都由软件默认指定。一般情况下不推荐单独使用该命令,因为其他参数都是未知的,不一定能够符合特殊情况下的特殊要求。

4.1.2、指定参数

1.编码器的指定

-vcodec + codec强制指定输出文件out.mp4使用某个编码器,例如:使用libx264编码器编码,输出文件格式为MP4
ffmpeg -i 1.avi -vcodec libx264 out.mp4 (2)
在命令行(2)中,ffmpeg表示的是ffmpeg软件中的ffmpeg可执行程序,其作用是视频文件转换命令工具;
-i 1.avi表示输入,输入文件为1.avi;
-vcodec libx264 表示的是为输出文件指定视频编码器,视频编码器为libx264。
out.mp4 表示输出文件名和格式。
(2)命令的作用是利用libx264编码器将avi格式的文件转成264流的MP4文件。该参数和其他参数可以使用,并不影响其他参数。

2.档次的指定

-profile:v + profile指定输出文件out.mp4的档次,例如:设置输出文件的档次为baseline,输出文件格式为MP4
ffmpeg -i 1.avi -profile:v baseline out.mp4 (3)
在(3)中ffmpeg是可执行程序;
-i 1.avi表示输入,输入文件为1.avi;
-profile:v baseline 表示的是为输出文件指定基线档(baseline);
-level 3.0表示的是为输出文件指定的级数为3.0;
out.mp4 表示输出文件名和格式。
(3)命令的作用是,指定输出文件out.mp4的档次。该参数和其他参数可以联合使用,互不影响。

3.级数的指定

-level 指定输出文件out.mp4的级数,例如:设置输出文件的级数为3.2,输出文件格式为MP4
ffmpeg -i 1.avi -level 3.0 out.mp4 (4)
在(4)中ffmpeg是可执行程序;
-i 1.avi表示输入,输入文件为1.avi;
-level 3.0表示的是为输出文件指定的级数为3.0;
out.mp4 表示输出文件名和格式。
(4)命令的作用是,指定输出文件out.mp4的级数。该参数和其他参数可以联合使用,互不影响。

4.分辨率的指定

- s 指定文件的分辨率,修饰输出文件out.mp4,例如:1.avi文件作为输入文件,输出文件分辨率大小为cif,输出格式为MP4
ffmpeg -i 1.avi -s qcif out.mp4 (5)
在(4)中ffmpeg是可执行程序;
-i 1.avi 表示输入文件是名为1的avi文件;
-s qcif 表示设置的输出文件的分辨率 qcif(176*144);
out.mp4 表示输出文件名和格式。
(5)命令的作用是,以分辨率为cif的1.avi文件作为输入,设置输出文件的分辨率为qcif。此参数可以和其他参数联合使用,互不影响。

5.图组的指定

-g 指定输出文件out.mp4的GOP大小,例如:指定输出文件的GOP大小为25
ffmpeg -i 1.avi -g 25 out.mp4 (6)
在(5)中ffmpeg是可执行程序;
-i 1.avi 表示输入文件是名为1的avi文件;
-g 25 指定输出文件的大小为25
out.mp4 表示输出文件名和格式。
(5)命令的作用是将1.avi文件转换为GOP大小为25的输出文件out.mp4。此参数的和其他参数互不影响,可以相互使用(除了下面的两个参数以外)。
(注意:参数 -g和参数-keyint_min 和参数-sc_throshold,会互相作用。keyint_min的作用是设置关键帧的间隔大小,-sc_threshold 的作用是设置场景切换阀值。三个参数联合使用可以强制使得GOP对齐,不会因为场景切换而导致GOP大小出现变故,一般情况下keyint_min 值和GOP一致,sc_threshold设置为0表示不切换场景);

6.帧率的指定

-r指定输出文件out.mp4的帧率大小,例如:指定输出文件的帧率为30
ffmpeg -i 1.avi -r 30 out.mp4 (7) 
在(7)中ffmpeg是可执行程序;
-i 1.avi 表示输入文件是名为1的avi文件;
-r 30 指定输出文件的帧数(fps)大小为30;
out.mp4 输出文件是名为out的mp4文件。
(7)命令的作用是将1.avi转换为fps大小为30输出文件out.mp4。该参数和其他参数互不影响,可同时使用。

7.采样率的指定

-b:v 指定输出文件out.mp4的视频采样率大小,例如:指定输出文件的采样率大小为1500k,输出格式为MP4
ffmpeg -i 1.avi -b:v 1500k out.mp4 (8)
在(8)中ffmpeg是可执行程序;
-i 1.avi 表示输入文件是名为1的avi文件;
-b:v 1500k 指定输出文件视频采样率大小为1.5M
out.mp4 输出文件是名为out的mp4文件。
(8)命令的作用是将1.avi文件转换为视频采样大小为1.5M的out.mp4文件。该参数和其他参数互不影响,可以同时使用。
(注意:在使用该参数的时候最好联合参数bufsize一起使用,bufsize的作用是设置视频的缓冲,先将数据读入缓存之后再拿出使用,这样做比较的安全有效,也可单一使用。)

8.编码帧的指定

-vframe 指定输出文件out.mp4文件编码的帧数,例如:编码只有150帧的视频文件,输出格式为MP4
ffmpeg -i 1.avi -vframes 150 out.mp4 (9)
在(9)中ffmpeg是可执行程序;
-i 1.avi 表示输入文件是名为1的avi文件;
-vframes 150 表示的是指定输出文件的帧大小为150帧;
out.mp4 输出文件是名为out的mp4文件。
(9)命令的作用是将输出文件的帧数的大小修改为150帧。该文件和其他参数互不影响,可以同时使用。
(注意:当输入文件帧大小小于150时,输出文件帧数大小等于源文件帧数大小。)

9.纵横比的指定

-aspect 指定输出文件的纵横比大小,例如:输出纵横比大小为16:9,格式为MP4的文件
ffmpeg -i 1.avi -aspect 1.7 out.mp4 (10)
在(9)中ffmpeg是可执行程序;
-i 1.avi 表示输入文件是名为1的avi文件;
-aspect 1.7 表示的是指定输出文件纵横比大小为16:9;
out.mp4 输出文件是名为out的mp4文件。
(10)命令的作用表示的是设置输出文件out.mp4的纵横比大小为16:9,此参数和其他参数互不影响,可以同时使用。

10.过滤器的指定

-filter为输出文件设置过滤器,-vf 表示的是视频过滤器,例如:将输入文件放大到1920*1080
ffmpeg -i 1.avi -vf scale=1920:1080 out.mp4 (11)
在(11)中ffmpeg是可执行程序;
-i 1.avi 表示输入文件是名为1的avi文件;
-vf 表示的是视频过滤器,scale1=1920:1080中scale表示的是缩放功能,缩放大小是1080
out.mp4 输出文件是名为out的mp4文件。
(11)命令的作用是将1.avi输入文件放大到1080p作为输出文件。此参数和其他参数互不影响,可以一同使用。(该过滤器和s功能一致,用一个就好了)

4.1.3、随机参数

根据以上说明情况,每一个参数机会都可以几乎都可以同时使用,不能一起使用的参数需要避开。
比如说给出一个随机要求:以avi文件作为输入,利用x264编码器编码,为输出文件设置档次为main 级数为4.0 分辨率大小为cif 图组大小为25,fps大小为30,视频采样大小为1.5M,忽略音频,输出格式为MP4格式:
ffmpeg -i 1.avi -vcodec libx264 -profile:v baseline -level 3.1 -s cif -g 30 -keyint_min 30 -sc_threshold 0 -r 30 -b:v 1500k -an -f mp4 out.mp4(12)
在命令(12)中,ffmpeg表示的是ffmpeg软件中的ffmpeg可执行程序,ffmpeg的作用是视频文件转换命令工具;
-i 表示输入,后面跟avi格式的输入文件input_file;
-vcodec libx264表示的是指定视频编码器,用x264编码;
-profile:v baseline表示为输出视频文件设置基线档(profile_idc = 66);
-level 3.1 表示为输出文件设计与profile对应的级(level_idc = 31);
-s cif 表示的是为输出文件设置分辨率,cif为352*288(w = 352,h = 288);
-g 30表示的是为输出文件设置GOP组,其大小为30;
-keyint_min 30表示的是为输出文件设置关键帧的最小间隔,大小为30;
-sc_threshold 0 表示的是为输出文件设置场景切换阀值,0表示不切换场景;
(注意:在遇到场景切换的情况时,H.264编码器会自动强制插入一个I帧,此时实际的GOP值会被缩短,所以-g/-sc_threshold/-keyint_min三个参数组合使用可以强行对齐GOP组,但也有缺点,某些时候可能会因此导致画面和音频不匹配)
-r 30 表示为输出文件设置fps 大小为30帧;
-b:v 1500k表示的是设置输出视频的采样频率为1500k;
-an 表示的是输出文件忽略音频部分,不记录音频部分;
-f mp4 指定输出文件格式为MP4格式;
output_file.mp4 表示的是mp4格式的输出文件。
 
图4.1.2 控制输出文件参数值
(12)命令的本质作用都没有变化,目的都是将avi文件转换为MP4格式,不同的是,在(12)中将输出文件的某些关键值通过参数指定了。这样做的好处是,能够满足任何情况下的输出文件的特殊需求,输出文件的关键值都可以由自己指定,极大的方便了后续的对输出文件的利用。
参数搭配使用效果更好,比较的灵活,在添加或者删除或者修改某些参数之后,就可以达到不同用户的不同需求。不足之处就是,可能输入的参数量比较大,稍显繁琐,命令长度因此变长了。
以上为avi格式转换为mp4格式的一个案例,当然其他格式的转换也可以借鉴该命令,需要做的就是将输入、输出文件改成相应的文件,对其中的参数适当的增删,对参数的值做出适当的修改,来符合想要的结果。


4.2、控制句法

一般情况下的编码往往都需设置某些特定的值来满足对生成结果利用的需要。简单举例来说:生成一个档次为main,级数为4.0,参考帧数为5,视频宽度为352 高度为288,不使用b帧,GOP组(关键帧间隔)大小为28,格式为264,名为test的文件。

4.2.1、参数控制法

ffmpeg -i 1.MP4 -vcodec libx264 -profile:v main -level 4.0 -refs 5 -s cif -bf 0 -g 28 -inter -f h264 test.h264(13)
在命令(13)中:
-vcodec libx264 表示的是指定输出文件的编辑器,libx264是编辑器名,用来编写生成h264文件;
-profile:v main 表示的是指定输出文件的档次为main,-profile:v表示的是为视频文件指定档次,还有其他档次的例如:baseline,high等等;
-refs 5 表示的是指定输出文件的参考帧数,大小为5;
-s cif 表示的是指定输出文件的分辨率大小,cif指的是w = 352,h = 288,类似的还有像qcif = 176*144、2cif = 704*288、dcif = 584*384等等;
-bf 0 表示的是指定输出文件的b帧数量为0;
-g 28 表示的是指定输出文件的GOP为28(最好跟上参数keyint_min,用来限制参数的GOP组,强制GOP对齐);
-f h264 表示的是指定输出文件格式为.h264格式;
test.h264 表示的是输出文件名字以及输出格式。
 

图4.2.1 以要求设置参数

根据要求,那么给出命令(13),对输出文件进行参数设置。编码结果显示如上图4.2.1,从中我们可以看到的确实是没有b帧,profile、level、s等给定要求的按照设定在最后结果显示,这个结论是就上图而言,但具体结果还需要后面检验。
其实,从本质上来说只要输入输出不变,其的目的都是一样。但是通过精确控制参数的值,来实现一些特殊的要求,这样生成的文件才能够在特殊环境下加以利用。

4.2.2、配置修改法

对比4.2.1的使用参数的方式来说,需要去修改配置文件的默认值,根据要求设置的参数值,在配置文件中找到该相应的参数,并且修改其值。
/*****************************************************************************/
一般情况下的编码往往都需设置某些特定的值来满足对生成结果利用的需要。简单举例来说:生成一个档次为main,级数为4.0,参考帧数为5,视频宽度为352 高度为288,不使用b帧,GOP组(关键帧间隔)大小为28,格式为264,名为test的文件。
/*****************************************************************************/
打开文件所在位置,找到编码支撑文件encoder.cfg,修改参数:
ProfileIDC            = 77 # Profile IDC (66=baseline, 77=main, 88=extended; FREXT Profiles: 100=High, 110=High 10, 122=High 4:2:2, 244=High 4:4:4, 44=CAVLC 4:4:4 Intra, 118=Multiview High Profile, 128=Stereo High Profile)
LevelIDC              = 40  # Level IDC   (e.g. 20 = level 2.0)
NumberReferenceFrames = 5   # Number of previous frames used for inter motion search (0-16)
SourceWidth           = 352    # Source frame width
SourceHeight          = 288    # Source frame height
NumberBFrames          = 0  # Number of B coded frames inserted (0=not used)
DirectInferenceFlag    = 0  # Direct Inference Flag (0: Disable 1: Enable)
IDRPeriod             = 28   # Period of IDR pictures (0=only first)
OutputFile            = "test.264"           # Bitstream
 
图4.2.1 修改配置之后的编码结果
根据要求,修改配置参数,其结果如上图4.2.2显示从图中观测到的信息有限,但确实是按照给定要求的进行了编码,就上图而言确实是成功的,其结果同上,都需要进行验证
从大方向来说,两个方法都是可以达到控制句法值的目的,可能还是修改配置参数来的更加准确,因为修改配置参数的时候是将这个参数做出了明确的修改,可以保证能够正确编译的前提下,在最后的结果上参数值会变成修改值。但是不足之处也比较的明显,每一次都需要打开配置文件来修改配置参数,相对来说比较麻烦。
综上两种情况所述,推荐使用第一种方式,通过命令行来修改参数相对简便,尽管可能因为需要写入的参数数量比较的大,但这也是其灵活点和优势所在。

5.验证结果

5.1、验证格式

/*****************************************************************************/
ffmpeg -i 1.avi out.mp4 (1)
ffmpeg -i 1.avi -vcodec libx264 out.mp4 (2)
ffmpeg -i 1.avi -profile:v baseline out.mp4 (3)
ffmpeg -i 1.avi -level 3.0 out.mp4 (4)
ffmpeg -i 1.avi -s qcif out.mp4 (5)
ffmpeg -i 1.avi -g 25 out.mp4 (6)
ffmpeg -i 1.avi -r 30 out.mp4 (7) 
ffmpeg -i 1.avi -b:v 1500k out.mp4 (8)
ffmpeg -i 1.avi -vframes 150 out.mp4 (9)
ffmpeg -i 1.avi -aspect 1.7 out.mp4 (10)
ffmpeg -i 1.avi -vf scale=1920:1080 out.mp4 (11)
ffmpeg -i 1.avi -vcodec libx264 -profile:v baseline -level 3.1 -s cif -g 30 -keyint_min 30 -sc_threshold 0 -r 30 -b:v 1500k -an -f mp4 out.mp4(12)
/*****************************************************************************/


 
图5.1.1生成文件夹
根据生成文件的编号来对应相应的命令行,从上图中可以看到生成文件确实都是为MP4格式。其他数据的生成结果需要对照编码界面上的数据来验证。
 
图5.1.2 命令行(1)的编码结果
从图5.1.2中可以看出,只存在输入输出文件时,该输出文件的参数都是由系统默认值来指定的,但是也达到了效果。图中显示Input from '1.avi',output to 'out.mp4',其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.3 命令行(2)的编码结果
从图5.1.3中可以看到,格式转换成功从avi格式,经由libx264编码器编码成功转换为MP4格式的文件,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.4 命令行(3)的编码结果
从图5.1.4中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的档次设置为了baseline,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.5 命令行(4)的编码结果
从图5.1.5中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的级数设置为了4.0,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.6 命令行(5)的编码结果
从图5.1.6中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的分辨率设置为了qcif,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.7 命令行(6)的编码结果
从图5.1.7中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的gop(关键帧间距)设置为了25,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.7 命令行(7)的编码结果
从图5.1.7中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的fps设置为了30,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.8 命令行(8)的编码结果
从图5.1.8中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的fps设置为了30,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.9 命令行(9)的编码结果
从图5.1.9中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的帧数总量设置为了150,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.9 命令行(10)的编码结果
从图5.1.10中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的纵横比设置为16:9,其生成结果满足目的参数设置,命令行设置成功。
 
图5.1.9 命令行(11)的编码结果
从图5.1.11中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的分辨率设置成了1920*1080,其生成结果满足目的参数设置,其本质和-s设置分辨率没有什么区别,命令行设置成功。
ffmpeg -i 1.avi -vcodec libx264 -profile:v baseline -level 3.1 -s cif -g 30 -keyint_min 30 -sc_threshold 0 -r 30 -b:v 1500k -an -f mp4 out.mp4
 
图5.1.9 命令行(12)的编码结果
从图5.1.12中可以看到,成功的将输入格式avi,转换为输出格式MP4,同时也根据参数设置点的要求,将输出文件的视频采样率设置成了1.5M,fps大小设置了30,GOP组(关键帧间隔)大小设置为了30,分辨率设置成了cif,档次和级数分别设置了基线档和3.1,同时编码器也强制指定了使用libx264作为其输出编码器,其生成结果满足目的参数设置,其本质和-s设置分辨率没有什么区别,命令行设置成功。
5.2、 验证句法
/************************************************************************/
ffmpeg -i 1.MP4 -vcodec libx264 -profile:v main -level 4.0 -refs 5 -s cif -bf 0 -g 28 -intra -f h264 test.h264
/************************************************************************/
 
图5.2.1 命令(13)编译结果
从图5.2.1上来看,大部分值对应的都是参数设置值,那么具体值是多少需要我们通过软件来分析。利用Stream Analyzer打开编译结果可以看到
 
图5.2.2 Stream Analyzer分析界面图
从图中可以看到,GOP并不是设置的大小,为什么呢?我猜测应该是场景切换的原因,在遇到场景切换的情况时,H.264编码器会自动强制插入一个I帧,此时实际的GOP值被缩短了。利用参数keyint_min和参数sc_threshold可以解决该问题,因为keyint_min设置关键帧的间距大小,sc_threshold设置了场景切换阀值。设置keyint_min 的大小等于GOP大小,设置sc_threshold值为0(表示场景不切换)。添加参数之后在编译文件,重新打开分析界面可以看到以下结果。
 
图5.2.2 重新编译Stream Analyzer分析界面图
 
图5.2.2 Stream Analyzer SPS分析界面图
从上图可以看到,参数值符合参数设定,说明设置的参数可以控制这么句法的值。

6.总结收获

以上给出的是几个随机例子,从该案例中我们可以大概的了解到一些问题:
(1)、参数数量情况;(2)、对参数的认识;(3)、参数各自的互相关联情况;(4)、必要的参数;(5)、能缩略的参数等等
以YUV测试文件(1.yuv)为输入文件举例,MP4文件已经编码过了,所以有些参数可以不用写入。相比较来说,1.yuv文件就是一个空白文件,对应的参数不能省略。
对1.yuv来说,对输入文件的分辨率描述不能少,少了会提示错误,同一般的文件一致,输入、输出文件同样也不能少:
Picture size 0x0 is invalid
1.yuv: Invalid argument
为什么用编码器编译的时候没有写入相应的次一级参数依旧不会报错误呢?因为在源文件中设置了默认选项,当没有写入必要参数的时候,系统会设置一个默认值,如下所示,白色选中部分就是系统源码设置的默认值,同时也是该部分参数就是header 里的句法元素设置信息。
 
图4.1 系统默认参数设置
输入文件是就类似一个空白文件,输入的参数就如同画画,参数越多,生成的内容就越接近你想要的。这就导致下面两个问题了,对参数的认识是否充足,参数之间的互相影响是否清楚。基础点就是参数的认识,需要好好理解参数。

原创粉丝点击