4 FFmpeg从入门到精通-FFmpeg转码

1 FFmpeg从入门到精通-FFmpeg简介
2 FFmpeg从入门到精通-FFmpeg工具使用基础
3 FFmpeg从入门到精通-FFmpeg转封装
4 FFmpeg从入门到精通-FFmpeg转码
5 FFmpeg从入门到精通-FFmpeg流媒体
6 FFmpeg从入门到精通-FFmpeg滤镜使用
7 FFmpeg从入门到精通-FFmpeg中Linux设备操作
8 FFmpeg从入门到精通-FFmpeg接口libavformat的使用
9 FFmpeg从入门到精通-FFmpeg接口libavcodec的使用
10 FFmpeg从入门到精通-FFmpeg接口libavfilter的使用

4.FFmpeg转码

  4.1 FFmpeg软编码H.264与H.265

    支持H.264的封装格式有很多,如FLV、MP4、HLS(M3U8)、MKV、TS等格式;FFmpeg本身并不支持H.264的编码器,而是由FFmpeg的第三方模块对其进行支持,例如x264和OpenH264,二者各有各的优势。由于OpenH264开源比较晚,所以x264还是当前最常用的编码器,这里将重点介绍FFmpeg中x264的使用;使用x264进行H.264编码时,所支持的像素格式主要包含yuv420p、yuvj420p、yuv422p、yuvj422p、yuv444p、yuvj444p、nv12、nv16、nv21。通过ffmpeg -h encoder=libx264可以查看到:

Encoder libx264 [libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10]:
    General capabilities: dr1 delay threads
    Threading capabilities: other
    Supported pixel formats: yuv420p yuvj420p yuv422p yuvj422p yuv444p yuvj444p nv12 nv16 nv21 yuv420p10le yuv422p10le yuv444p10le nv20le gray gray10le

    因为其所支持的像素色彩格式比较多,所以x264支持的范围更广。下面就来详细介绍FFmpeg中x264的参数。

  4.1.1 x264编码参数简介

    x264参数在FFmpeg中可以使用很多参数,同样也可以使用x264本身的参数来控制,具体参数列表见下表。
在这里插入图片描述
    以上为H.264编码时用到的常见的参数,设置参数后编码生成的文件可以通过一些外部协助工具进行查看,如Elecard、Bitrate Viewer、ffprobe等。

  4.1.2 H.264编码举例

    上节中已经给出了FFmpeg中H.264编码器的操作参数,下面就来列举一些实际中常用的例子。

   1.编码器预设参数设置preset

    从FFmpeg的x264参考说明中可以看到,可以使用x264 --full help查看preset设置的详细说明,找到x264帮助信息中的preset参数项之后,可以看到其包含了以下几种预设参数,预设参数的详细设置具体如下。
    ·ultrafast:最快的编码方式
    除了默认设置之外,还增加了如下参数设置:

-no-8x8dct --aq-mode 0 --b-adapt 0 --bframes 0 --no-cabac --no-deblock --no-mbtree --me dia --no-mixed-refs --partitions none --rc-lookahead 0 --ref 1 --scenecut 0 --subme 0 --trellis 0 --no-weightb --weightp 0

    ·superfast:超级快速的编码方式
除了默认设置之外,还增加了如下参数设置:

-no-mbtree --me dia --no-mixed-refs  --partitions i8x8,i4x4 --rc-lookahead 0  --ref 1 --subme 1 --trellis 0 --weightp 1

    ·veryfast:非常快速的编码方式
    除了默认设置之外,还增加了如下参数设置:

-no-mixed-refs --rc-lookahead 10 --ref 1 --subme 2 --trellis 0 --weightp 1

    ·faster:稍微快速的编码方式
    除了默认设置之外,还增加了如下参数设置:

-no-mixed-refs --rc-lookahead 20 --ref 2 --subme 4 --weightp 1

    ·fast:快速的编码方式
    除了默认设置之外,还增加了如下参数设置:

-rc-lookahead 30 --ref 2 --subme 6 --weightp 1

    ·medium:折中的编码方式
    参数全部为默认设置。
    ·slow:慢的编码方式
    除了默认设置之外,还增加了如下参数设置:

-b-adapt 2 --direct auto --me umh --rc-lookahead 50 --ref 5 --subme 8

    ·slower:更慢的编码方式
    除了默认设置之外,还增加了如下参数设置:

-b-adapt 2 --direct auto --me umh --partitions all --rc-lookahead 60 --ref 8 --subme 9 --trellis 2

    ·veryslow:非常慢的编码方式
    除了默认设置之外,还增加了如下参数设置:

-b-adapt 2 --bframes 8 --direct auto --me umh --merange 24 --partitions all --ref 16 --subme 10 --trellis 2 --rc-lookahead 60

    ·placebo:最慢的编码方式
    除了默认设置之外,还增加了如下参数设置:

-bframes 16 --b-adapt 2 --direct auto --slow-firstpass --no-fast-pskip --me tesa --merange 24 --partitions all --rc-lookahead 60 --ref 16 --subme 11 --trellis 2

    随着所设置参数的不同,所编码出来的清晰度也会有所不同,设置相关的预设参数之后,有很多参数也会被设置所影响,因此需要了解相关的参数含义。为了方便操作,通过preset进行设置即可,下面就来看一下相同的机器中,设置ultrafast与设置medium预设参数之后转码效率的对比

ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -b:v 2000k output.mp4

    命令行执行之后,输出内容如下:

Output #0, mp4, to 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.27.100
  Stream #0:0(und): Video: h264 (avc1 / 0x31637661), yuv420p(progressive), 1280x720, q=2-31, 2000 kb/s, 30 fps, 15360 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc59.37.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/2000000 buffer size: 0 vbv_delay: N/A
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc59.37.100 aac
frame= 2114 fps=267 q=-1.0 Lsize=   13331kB time=00:01:10.43 bitrate=1550.5kbits/s dup=1 drop=0 speed= 8.9x    

    从命令行执行后的输出内容中可以看到,转码的预设参数为ultrafast模式,转码的速度为8.9倍速,接下来再看一下设置为medium模式后的速度:

Output #0, mp4, to 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.27.100
  Stream #0:0(und): Video: h264 (avc1 / 0x31637661), yuv420p(progressive), 1280x720, q=2-31, 2000 kb/s, 30 fps, 15360 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc59.37.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/2000000 buffer size: 0 vbv_delay: N/A
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc59.37.100 aac
frame= 2114 fps= 56 q=-1.0 Lsize=   12217kB time=00:01:10.37 bitrate=1422.1kbits/s dup=1 drop=0 speed=1.87x  

    从以上输出内容中可以看到,设置medium模式后,转码速度为1.87倍速,速度虽然降低了,但画质却有了明显的提升,对比效果如图所示。
在这里插入图片描述
    很显然,图中的上图是通过预设参数ultrafast转码之后的效果,下边的图像是通过medium转码之后的效果上下图像相差比较大,上边图像的马赛克多一些,图中草的对比比较明显,主要是因为两个preset中所设置的参数略有不同,详情可以参考前边的参数说明。

   2.H.264编码优化参数tune

    使用tune参数调优H.264编码时,可以包含如下几个场景:==film、animation、grain、stillimage、psnr、ssim、fastdecode、zerolatency;==这几种场景所使用的x264参数也各有不同,具体如下。
    ·film
    除默认参数配置之外,还需要设置如下参数:

-deblock -1:-1 --psy-rd <unset>:0.15
animation

    ·animation
    除默认参数配置之外,还需要设置如下参数:

-bframes {
    
    +2} --deblock 1:1 --psy-rd 0.4:<unset> --aq-strength 0.6 --ref {
    
    Double if >1 else 1}

    ·grain
    除默认参数配置之外,还需要设置如下参数:

-aq-strength 0.5 --no-dct-decimate --deadzone-inter 6 --deadzone-intra 6 --deblock -2:-2 --ipratio 1.1 --pbratio 1.1 --psy-rd <unset>:0.25 --qcomp 0.8

    ·stillimage
    除默认参数配置之外,还需要设置如下参数:

-aq-strength 1.2 --deblock -3:-3 --psy-rd 2.0:0.7

    ·psnr
    除默认参数配置之外,还需要设置如下参数:

-aq-mode 0 --no-psy

    ·ssim
    除默认参数配置之外,还需要设置如下参数:

-aq-mode 2 --no-psy

    ·fastdecode
    除默认参数配置之外,还需要设置如下参数:

-no-cabac --no-deblock --no-weightb --weightp 0

    ·zerolatency
    除默认参数配置之外,还需要设置如下参数:

-bframes 0 --force-cfr --no-mbtree --sync-lookahead 0 --sliced-threads --rc-lookahead 0

    在使用FFmpeg与x264进行H.264直播编码并进行推流时,只用tune参数的zerolatency将会提升效率,因为其降低了因编码导致的延迟

   3.H.264的profile与level设置

    这里的profile(档次)与level(等级)的设置与H.264标准文档ISO-14496-Part10中描述的profile、level的信息基本相同,x264编码器支持Baseline、Extented、Main、High、High10、High422、High444共7种profile参数设置,根据profile的不同,编码出来的视频的很多参数也有所不同,具体的情况可以参考下表。
在这里插入图片描述
    level设置则与标准的ISO-14496-Part10参考中的Annex A中描述的表格完全相同,见表
在这里插入图片描述
    下面使用baseline profile编码一个H.264视频,然后使用high profile编码一个H.264视频,分析两类不同profile编码出来的视频的区别,从表所示的profile参数中可以看到,使用baseline profile编码的H.264视频不会包含B Slice,而使用main profile、high profile编码出来的视频,均可以包含B Slice,下面就来着重查看baseline与high两种不同profile编码出来的视频是否包含B Slice。
    首先使用FFmpeg编码生成baseline与high两种profile的视频:

ffmpeg -i input.mp4 -vcodec libx264 -profile:v baseline -level 3.1 -s 352x288 -an -y -t 10 output_baseline.ts
ffmpeg -i input.mp4 -vcodec libx264 -profile:v high -level 3.1 -s 352x288 -an -y -t 10 output_high.ts

    从以上的输出结果可以看到共执行了两次ffmpeg,分别生成output_baseline.ts与output_high.ts两个文件。前面章节中提到过使用ffprobe可以查看到每一帧具体是I帧、P帧还是B帧,下面使用ffprobe查看这两个文件中包含B帧的情况:

ffprobe -v quiet -show_frames -select_streams v output_baseline.ts |grep "pict_type=B"|wc -1
0
ffprobe -v quiet -show_frames -select_streams v output_high.ts |grep "pict_type=B"|wc -l
194

    从输出的结果中可以看到,baseline profile中包含了0个B帧,而high profile的视频中包含了194个B帧。当进行实时流媒体直播时,采用baseline编码相对main或high的profile会更可靠些;但适当地加入B帧能够有效地降低码率,所以应根据需要与具体的业务场景进行选择。

   4.控制场景切换关键帧插入参数sc_threshold

    在FFmpeg中,通过命令行的-g参数设置以帧数间隔为GOP的长度,但是当遇到场景切换时,例如从一个画面突然变成另外一个画面时,会强行插入一个关键帧,这时GOP的间隔将会重新开始,这样的场景切换在点播视频文件中会频频遇到,如果将点播文件进行M3U8切片,或者将点播文件进行串流虚拟直播时,GOP的间隔也会出现相同的情况,为了避免这种情况的产生,可以通过使用sc_threshold参数进行设定以决定是否在场景切换时插入关键帧
    下面执行ffmpeg命令控制编码时的GOP大小,生成MP4之后使用Elecard StreamEye观察GOP的情况:

ffmpeg -i input.mp4 -c:v libx264 -g 50 -t 60 output.mp4

    根据这条命令可以看出,每50帧被设置为一个GOP间隔,生成60秒的MP4视频,接下来查看一下GOP的情况,如图所示。
在这里插入图片描述
    从图4-2中可以看出,其中有一段GOP的间距比较短,这是因为强行插入了GOP而导致的,这个情形插入的GOP是由于场景切换导致的GOP插入。为了使得GOP的插入更加均匀,使用参数sc_threshold即可,下面来看一下效果:

ffmpeg -i input.mp4 -c:v libx264 -g 50 -sc_threshold 0 -t 60 -y output.mp4

    执行完这条命令行之后,GOP间隔被设置为50帧,并且场景切换时不插入关键帧,执行完之后生成的MP4效果如图所示,GOP非常均匀,均为50帧一个GOP,场景切换时并没有强行插入GOP,这样做有一个好处,那就是可以控制关键帧,在进行视频切片时将会更加方便,如下图所示。
在这里插入图片描述

   5.设置x264内部参数x264opts

    由于FFmpeg设置x264参数时增加的参数比较多,所以FFmpeg开放了x264opts,可以通过这个参数设置x264内部私有参数,如设置I帧、P帧、B帧的顺序及规律等,通过x264opts可以设置x264内部的很多参数。下面举个例子,控制I帧、P帧、B帧的顺序及出现频率,首先分析一下设置的GOP参数,如果视频GOP设置为50帧,那么如果在这50帧中不希望出现B帧,则客户只需要将x264参数bframes设置为0即可:

ffmpeg -i input.mp4 -c:v libx264 -x264opts "bframes=0" -g 50 -sc_threshold 0  output.mp4

    命令行执行完毕后,使用Elecard StreamEye查看帧的信息,结果如图所示。
在这里插入图片描述
    从图中可以看出,output.mp4中H.264的帧排列中并不包含B帧,全部为P帧与I帧
    如果希望控制I帧、P帧、B帧的频率与规律,可以通过控制GOP中B帧的帧数来实现,P帧的频率可以通过x264的参数b-adapt进行设置
    例如设置GOP中,每2个P帧之间存放3个B帧:

ffmpeg -i input.mp4 -c:v libx264 -x264opts "bframes=3:b-adapt=0" -g 50 -sc_threshold 0 output.mp4

    命令行执行完之后,使用Elecard StreamEye查看帧信息,如图所示。
在这里插入图片描述
    视频中的B帧越多,同等码率时的清晰度将会越高,但是B帧越多,编码与解码所带来的复杂度也就越高,所以合理地使用B帧非常重要,尤其是在进行清晰度与码率衡量时。

   6.CBR恒定码率设置参数nal-hrd

    从前面对x264参数的介绍中可以看出,编码能够设置VBR、CBR的编码模式,VBR为可变码率,CBR为恒定码率。但CBR依然存在;下面就来介绍一下CBR码率视频的制作。FFmpeg是通过参数-b:v来指定视频的编码码率的,但是设定的码率是平均码率,并不能够很好地控制最大码率及最小码率的波动,如果需要控制最大码率和最小码率以控制码率的波动,则需要使用FFmpeg的三个参数-b:v、maxrate、minrate

ffmpeg -i input.mp4 -c:v libx264 -x264opts "bframes=10:b-adapt=0" -b:v 1000k -maxrate 1000k -minrate 1000k -bufsize 50k -nal-hrd cbr -g 50 -sc_threshold 0 output.ts

    下面就来分析一下这条命令行,具体如下。
    ·设置B帧的个数,并且是每两个P帧之间包含10个B帧
    ·设置视频码率为1000kbit/s
    ·设置最大码率为1000kbit/s
    ·设置最小码率为1000kbit/s
    ·设置编码的buffer大小为50KB
    ·设置H.264的编码HRD信号形式为CBR
    ·设置每50帧一个GOP
    ·设置场景切换不强行插入关键帧
    根据上述参数设置之后生成的output.ts文件,使用Bitrate Viewer观察其码率波动效果,结果如图所示。

在这里插入图片描述
    从图中可以看到码率波动为最小996kbit/s,最大码率为11551kbit/s,码率得到了控制。
    接下来使用Elecard StreamEye查看一下视频流信息,如图所示。

在这里插入图片描述
    在FFmpeg中进行H.265编码时,可以采用x265进行编码,H.265编码参数与x264的编码参数相差不多,基本可以通用。

  4.2 FFmpeg硬编解码

    当使用FFmpeg进行软编码时,常见的基于CPU进行H.264或H.265编码其相对成本会比较高,会考虑采用硬编码,常见的硬编码包含Nvidia GPU与Intel QSV两种,还有常见的嵌入式平台,如树莓派、瑞芯微等,本节将重点介绍常见的Nvidia与Intel硬编码,以及树莓派的硬编码。

  4.2.1 Nvidia GPU硬编解码

    在计算机的显卡生产厂商里,最常见的就是Nvidia了,Nvidia在图像处理技术方面非常强悍FFmpeg集成Nvidia显卡视频处理模块后,使用FFmpeg能够将Nvidia的视频编解码功能快速使用起来,下面就来了解一下Nvidia在FFmpeg中支持的操作参数。

   1.Nvidia硬编码参数

    使用Nvidia GPU编码之前,首先需要了解在FFmpeg中对于Nvidia的GPU编码均支持哪些参数,可以通过ffmpeg -h encoder=h264_nvenc进行查看。Nvidia硬编码参数见表。
在这里插入图片描述
    从表所示的参数列表中可以看到,编码的参数例如preset参数、profile参数、level参数、场景切换参数等。下面就来针对常用的主要参数进行举例。

   2.Nvidia硬编解码参数使用举例

    在使用Nvidia进行编解码时,可以使用ffmpeg -h encoder=h264_nvenc查看FFmpeg中Nvidia做H.264编码时的参数支持,使用ffmpeg -h decoder=h264_cuvid查看FFmpeg中Nvidia做H.264解码时的参数支持。在做H.264编码时,首先需要确认nvenc支持的像素格式:

Encoder h264_nvenc [NVIDIA NVENC H.264 encoder]:
    General capabilities: dr1 delay hardware
    Threading capabilities: none
    Supported hardware devices: cuda cuda d3d11va d3d11va
    Supported pixel formats: yuv420p nv12 p010le yuv444p p016le yuv444p16le bgr0 bgra rgb0 rgba x2rgb10le x2bgr10le gbrp gbrp16le cuda d3d11

    如h264_nvenc基本信息所示,使用nvenc进行H.264编码时所支持的像素格式为yuv420p、nv12、p010le、yuv444p、yuv444p16le、rgb0、cuda
    而在做H.264解码时,需要查看cuvid所支持的解码像素格式:

Decoder h264_cuvid [Nvidia CUVID H264 decoder]:
    General capabilities: delay avoidprobe hardware
    Threading capabilities: none
    Supported hardware devices: cuda
    Supported pixel formats: cuda nv12 p010le p016le
h264_cuvid AVOptions:

    如h264_cuvid基本信息所示,使用cuvid解码H.264时所支持的像素格式为cuda、nv12。了解清楚了所支持的像素格式之后,接下来列举一个硬编码与硬解码的例子:

ffmpeg -hwaccel cuvid -vcodec h264_cuvid -i input.mp4 -vf scale_npp=1920:1080 -vcodec h264_nvenc -acodec copy -f mp4 -y output.mp4

    命令行执行完毕之后,会将input.mp4的视频像素改变为1920×1080,将码率改变为2000kbit/s,输出为output.mp4。下面就来看一下转码时的效果:

    如上述的输出信息所示,使用的是cuvid硬解码与nvenc硬编码,将视频从4K视频降低为1080p,同时将码率从35Mbit/s降低至2Mbit/s,效率刚刚好能够支撑转码处理。而在普通的PC机中,如果不这样使用硬编解码处理,效率将会极为低下。下面就来看一下使用硬转码时的CPU使用情况,如图4-8所示。
    从图4-8中可以看到,使用硬转码4K视频至1080p视频时,CPU的使用效率可以控制在10%之内,而在使用软转码时,CPU的占用率将远远高于100%。

  4.2.2 Intel QSV硬编码

    硬编解码除了可以使用Nvidia的GPU之外,Intel的QSV也是一种不错的方案,FFmpeg对于Intel的QSV支持相对也比较灵活,如果希望使用FFmpeg的Intel QSV编码,则需要在编译FFmpeg时开启QSV支持:

ffmpeg -hide_banner -codecs|grep h264

    命令行执行后的输出内容如下:

 DEV.LS h264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (encoders: libx264 libx264rgb )

    如上述输出信息所示,FFmpeg通过--enable-libmfx开启对Intel QSV的支持;FFmpeg项目中已经支持了H.264、H.265的硬解码、硬编码,下面就来看一下H.264和H.265的参数相关的支持与操作。

   1.Intel QSV H.264参数说明

    在使用Intel QSV编码之前,首先查看一下FFmpeg支持Intel Media SDK QSV的参数,执行命令行ffmpeg -h encoder=h264_qsv可以得到QSV参数信息,具体见表4-5。
在这里插入图片描述
    从表中可以看出,硬件编码所支持的参数虽然比libx264软编码的参数设置稍微少一些,但是基本上也可以实现常见的功能,下面列举几个硬转码的例子,来对比一下其与软编码的区别。

   2.Intel QSV H.264使用举例

    因为是使用硬件的codec,因此可以考虑解码时使用硬件解码,编码时使用硬件编码,通过ffmpeg -h encoder=h264与ffmpeg -h decoder=h264查看h264_qsv硬件参数信息时可以看到h264_qsv只支持nv12与qsv的像素格式,所以在使用yuv420p时需要将其转换成nv12才可以,FFmpeg已经可以自动进行该操作的转换,下面看一下硬转码的例子:

ffmpeg -i 10M1080P.mp4 -pix_fmt nv12 -vcodec h264_qsv -an -y output.mp4

    命令行执行之后,FFmpeg将会使用h264_qsv进行解码与编码,转码速度如下所示:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.27.100
  Duration: 00:00:35.07, start: 0.000000, bitrate: 2661 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 2493 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 159 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (h264_qsv))
Press [q] to stop, [?] for help
Output #0, mp4, to 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.34.102
  Stream #0:0(und): Video: h264 (avc1 / 0x31637661), nv12(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 1000 kb/s, 30 fps, 15360 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc59.54.100 h264_qsv
    Side data:
      cpb: bitrate max/min/avg: 0/0/1000000 buffer size: 0 vbv_delay: N/A
frame= 1052 fps=141 q=26.0 Lsize=    4190kB time=00:00:35.00 bitrate= 980.8kbits/s speed=4.69x
video:4179kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.277420%

    如上述的输出内容所示,FFmpeg采用的是Intel QSV进行H.264转码,将1080p/2.6M的H.264的视频转换为1080p/1M的视频输出,转码速度4.69倍速,如果只使用libx264做软编码时速度并不会有这么快。h264_qsv编码采用的是Intel的GPU编码,对CPU资源也相对更加节省一些

   3.Intel QSV H.265参数说明

    FFmpeg中的Intel QSV H.265(HEVC)的参数与Intel QSV H.264的参数类似,但是FFmpeg另外还支持指定使用软编码还是硬编码的参数。Intel QSV H.265编码参数见表。
在这里插入图片描述

   4.Intel QSV H.265使用举例

    在使用Intel进行高清编码时,使用AVC编码之后观察码率会比较高,但是使用H.265(HEVC)则能更好地降低同样清晰度的码率,下面举例说明:

ffmpeg -hide_banner -y -hwaccel qsv -i 10M1080P.mp4 -an -c:v hevc_qsv -load_plugin hevc_hw -b:v 5M -maxrate 5M out.mp4

    命令行执行之后,FFmpeg会将1080p的高清视频转换为H.265视频使用CPU进行1080p的H.265编码时速度相对会比较慢,而使用Intel QSV进行编码时,效率则会稍微高一些,效果如下:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'H264_1080P_8M_29.97fps.mp4
        major_brand     : isom
        minor_version   : 512
        compatible_brands: isomiso2avc1mp41
        creation_time   : 1970-01-01T00:00:00.000000Z
        encoder         : Lavf53.6.0
    Duration: 00:01:00.29, start: 0.000000, bitrate: 8044 kb/s

    至此,FFmpeg支持的Intel QSV硬编解码已全部介绍完毕。

  4.2.3 树莓派硬编码

    下面就来看一下硬编码所支持的配置:

ffmpeg version 2022-11-23-git-c8e9cc8d20-full_build-www.gyan.dev Copyright (c) 2000-2022 the FFmpeg developers
    built with gcc 12.1.0 (Rev2, Built by MSYS2 project)
    configuration: —enable-omx-rpi
    libavutil      55. 58.100 / 55. 58.100
    libavcodec     57. 89.100 / 57. 89.100
    libavformat    57. 71.100 / 57. 71.100
    libavdevice    57.  6.100 / 57.  6.100
    libavfilter     6. 82.100 /  6. 82.100
    libswscale      4.  6.100 /  4.  6.100
    libswresample   2.  7.100 /  2.  7.100
V….. h264_omx             OpenMAX IL H.264 video encoder (codec h264)

    在FFmpeg下面支持树莓派的H.264编码采用的是OpenMAX框架,在编译FFmpeg工程之前配置编译时,需要使用--enable-omx-pi支持,下面来看一下具体的参数说明。

   1.h264_omx参数说明

    在树莓派中使用的是h264_omx进行编码,ffmpeg对于树莓派的h264_omx编码参数可以通过ffmpeg -h encoder=h264_omx获得,具体参数见表。
在这里插入图片描述
    从表中可以看出,目前一共有三个参数可用,omx_libname与omx_libprefix均是运行ffmpeg时加载omx所使用的参数,zerocopy则用于提升编码时的性能

  4.3 FFmpeg输出MP3

    使用FFmpeg可以解码MP3,同样FFmpeg也可以支持MP3编码,FFmpeg使用第三方库libmp3lame即可编码MP3格式。不但如此,MP3编码还是低延迟的编码,可以支持的采样率比较多,包含44100、48000、32000、22050、24000、16000、11025、12000、8000多种采样率,采样格式也比较多,包含s32p(signed32bits,planar)、fltp(float,planar)、s16p(signed16bits,planar)多种格式,声道布局方式支持包含mono(单声道模式)、stereo(环绕立体声模式),下面就来详细介绍MP3编码参数。

  4.3.1 MP3编码参数介绍

    查看FFmpeg对于MP3的参数支持,可以通过ffmpeg -h encoder=libmp3lame得到MP3的参数,见表。
在这里插入图片描述
    从表中可以看到,FFmpeg对MP3编码操作相关的参数包含了主要的控制参数,更高级的参数控制,尚未全部从lame中移植到FFmpeg中,还有待开发完善。下面就来介绍FFmpeg中重点支持的这些参数的使用及基本原理。

  4.3.2 MP3的编码质量设置

    在FFmpeg中进行MP3编码采用的是第三方库libmp3lame,所以进行MP3编码时,需要设置编码参数acodec为libmp3lame,命令行如下:

ffmpeg –i INPUT –acodec libmp3lame OUTPUT.mp3

    根据上面的命令行可以得到音频编码为MP3封装文件
    MP3编码的码率得到控制之后,控制质量时需要通过-qscale:a进行控制,也可以使用上表中的q参数进行控制,质量不同码率也不同,详情可以参考表。

在这里插入图片描述
    表可以作为参考,如果遇到将低码率转换为高码率的情况,则并不一定会很符合上述参数,但在大多数情况下是符合的,下面举例说明:

ffmpeg -i input.mp3 -acodec libmp3lame -q:a 8 output.mp3

    执行完上面这条命令行之后,将生成的output.mp3的码率区间设置在70kbit/s至105kbit/s之间,下面将转码前的input.mp3与转码后的output.mp3做一个比较:

Input #0, mp3, from 'input.mp3':
  Duration: 00:03:50.64, start: 0.000000, bitrate: 128 kb/s
  Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 128 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (mp3 (mp3float) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, mp3, to 'output.mp3':
  Metadata:
    TSSE            : Lavf59.34.102
  Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp
    Metadata:
      encoder         : Lavc59.54.100 libmp3lame
size=    2560kB time=00:03:50.61 bitrate=  90.9kbits/s speed=86.4x
video:0kB audio:2560kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.009653%

    从以上代码可以看到,转码前的input.mp3的码率为128kbit/s,转码后的output.mp3的码率为91kbit/s。在转码过程中,从FFmpeg的输出过程信息中可以看到编码时的码率在不断地发生变动:

size=    2560kB time=00:03:50.61 bitrate=  90.9kbits/s speed=86.4x

    以上码率设置方式为VBR码率,常见的MP3编码设置为CBR,通过FFmpeg参数-b即可设置,在FFmpeg编码过程中,码率几乎不会波动:

ffmpeg -i input.mp3 -acodec libmp3lame -b:a 64k output.mp3

    执行完上述命令行之后,结果将会生成编码为MP3的音频。
    对比转码前与转码后的两个MP3文件:

Input #0, mp3, from 'input.mp3':
  Duration: 00:03:50.64, start: 0.000000, bitrate: 128 kb/s
  Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 128 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (mp3 (mp3float) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, mp3, to 'output.mp3':
  Metadata:
    TSSE            : Lavf59.34.102
  Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 64 kb/s
    Metadata:
      encoder         : Lavc59.54.100 libmp3lame
size=    1802kB time=00:03:50.61 bitrate=  64.0kbits/s speed=65.9x
video:0kB audio:1802kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.013711%

    两个文件均为CBR编码方式编码的MP3,并且可以看到编码过程中码率几乎没有波动:

size=    1802kB time=00:03:50.61 bitrate=  64.0kbits/s speed=65.9x

  4.3.3 平均码率编码参数ABR

    ABR是VBR与CBR的混合产物,表示平均码率编码,使用ABR参数之后,编码速度将会比VBR高,但是质量会比VBR的编码稍逊一些,比CBR编码好一些,在FFmpeg中可使用参数-abr来控制MP3编码为ABR编码方式:

ffmpeg -i input.mp3 –acodec libmp3lame -b:a 64k -abr 1 output.mp3

    执行上面这条命令之后,编码之后的输出信息如下:

    原本为64kbit/s码率的CBR编码方式的MP3音频,因为设置abr参数之后,成为ABR编码方式的MP3音频,可以观察编码过程中的输出内容:

Input #0, mp3, from 'input.mp3':
  Duration: 00:03:50.64, start: 0.000000, bitrate: 128 kb/s
  Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 128 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (mp3 (mp3float) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, mp3, to 'output.mp3':
  Metadata:
    TSSE            : Lavf59.34.102
  Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 64 kb/s
    Metadata:
      encoder         : Lavc59.54.100 libmp3lame
size=    1858kB time=00:03:50.61 bitrate=  66.0kbits/s speed=64.6x
video:0kB audio:1858kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.013297%

    看似VBR,其实为ABR。

  4.4 FFmpeg输出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编码器

  4.4.1 FFmpeg中的AAC编码器使用

    下面列举几个使用FFmpeg中的AAC编码器编码的例子:

ffmpeg -i input.mp4 -c:a aac -b:a 160k output.aac

    根据这条命令行可以看出,编码为AAC音频,码率为160kbit/s,编码生成的输出文件为output.aac文件:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.27.100
  Duration: 00:00:35.07, start: 0.000000, bitrate: 2661 kb/s
  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 2493 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
    Metadata:
      handler_name    : VideoHandler
      vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 159 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
Stream mapping:
  Stream #0:1 -> #0:0 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
Output #0, adts, to 'output.aac':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf59.34.102
  Stream #0:0(und): Audio: aac (LC), 48000 Hz, stereo, fltp, 160 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
      vendor_id       : [0][0][0][0]
      encoder         : Lavc59.54.100 aac
size=      21kB time=00:00:34.98 bitrate=   4.9kbits/s speed= 240x

    接下来再列举一个例子:

ffmpeg -i input.wav -c:a aac -q:a 2 output.m4a

    从这条命令行可以看出,在编码AAC时,同样也用到了qscale参数,这个q在这里设置的有效范围为0.1~2之间,其用于设置AAC音频的VBR质量,效果并不可控,可以设置几个参数来看一下效果:

Input #0, wav, from 'input.wav':
    Duration: 00:04:13.10, bitrate: 1411 kb/s
        Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from 'output_0.1.m4a':
    Metadata:
        encoder         : Lavf57.66.102
    Duration: 00:04:13.12, start: 0.000000, bitrate: 23 kb/s
        Stream #1:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 24 kb/s (default)
Input #2, mov,mp4,m4a,3gp,3g2,mj2, from 'output_2.0.m4a':
    Metadata:
        encoder         : Lavf57.66.102
    Duration: 00:04:13.12, start: 0.000000, bitrate: 186 kb/s
        Stream #2:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 186 kb/s (default)

    从以上代码可以看到一共有三个Input文件,具体如下。
    ·Input#0为原始文件,码率为1411kbit/s
    ·Input#1为设置q:a为0.1的文件,码率为24kbit/s
    ·Input#2为设置q:a为2.0的文件,码率为186kbit/s
    可以使用-q:a设置AAC的输出质量,关于AAC的输出控制很简单,这里就介绍这么多。

  4.4.2 FDK AAC第三方的AAC编解码Codec库

    FDK-AAC库是FFmpeg支持的第三方编码库中质量最高的AAC编码库,下面就来介绍一下libfdk_aac的几种编码模式。

   1.恒定码率(CBR)模式

    如果使用libfdk_aac设定一个恒定的码率,改变编码后的大小,并且可以兼容HE-AAC Profile,则可以根据音频设置的经验设置码率,例如如果一个声道使用64kbit/s,那么双声道为128kbit/s,环绕立体声为384kbit/s,这种通常为5.1环绕立体声。可以通过b:a参数进行设置。下面就来举几个例子:

ffmpeg -i input.wav -c:a libfdk_aac -b:a 128k output.m4a

    根据这条命令行可以看出,FFmpeg使用libfdk_aac将input.wav转为恒定码率为128kbit/s、编码为AAC的output.m4a音频文件。

ffmpeg -i input.mp4 -c:v copy -c:a libfdk_aac -b:a 384k output.mp4

    根据这条命令行可以看出,FFmpeg将input.mp4的视频文件按照原有的编码方式进行输出封装,将音频以libfdk_aac进行编码,音频通道为环绕立体声,码率为384kbit/s,封装格式为output.mp4。
    以上两个例子均为使用libfdk_aac进行AAC编码的案例,使用libfdk_aac可以编码AAC的恒定码率(CBR),相关内容至此介绍完毕。

   2.动态码率(VBR)模式

    使用VBR可以有更好的音频质量,使用libfdk_aac进行VBR模式的AAC编码时,可以设置5个级别。
    根据表的内容,第一列为VBR的类型,第二列为每通道编码后的码率,第三列中有三种AAC编码信息,具体如下。
    ·LC:Low Complexity AAC,这种编码相对来说体积比较大,质量稍差
    ·HE:High-Efficiency AAC,这种编码相对来说体积稍小,质量较好
    ·HEv2:High-Efficiency AAC version2,这种编码相对来说体积小,质量优
    下面举个例子,将音频压缩为AAC编码的m4a容器:

ffmpeg -i input.wav -c:a libfdk_aac -vbr 3 output.m4a

    执行完上述命令之后,FFmpeg会将input.wav的音频转为音频编码为libfdk_aac的output.m4a音频文件。

  4.4.3 高质量AAC设置

    根据前面的介绍,AAC音频分为三种LC、HE-AAC、HEv2-AAC,前文已经介绍过LC的编码设置,下面举例介绍HE-AAC与HEv2-AAC的设置。

   1.HE-AAC音频编码设置
ffmpeg -i input.wav -c:a libfdk_aac -profile:a aac_he -b:a 64k output.m4a

    执行完上述命令行之后,编码后输出output.m4a的信息如下:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.m4a':
    Metadata:
        major_brand     : M4A 
        minor_version   : 512
        compatible_brands: isomiso2
        encoder         : Lavf57.71.100
    Duration: 00:04:13.22, start: 0.000000, bitrate: 64 kb/s
        Stream #0:0(und): Audio: aac (HE-AAC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 64 kb/s (default)
    Metadata:
        handler_name    : SoundHandler

    从以上代码可以看出,音频编码为HE-AAC,可见编码参数已通过-profile:a aac_he设置生效。

   2.HEv2-AAC音频编码设置

    执行如下命令:

ffmpeg -i input.wav -c:a libfdk_aac -profile:a aac_he_v2 -b:a 32k output.m4a

    编码后输出output.m4a信息如下:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.m4a':
    Metadata:
        major_brand     : M4A 
        minor_version   : 512
        compatible_brands: isomiso2
        encoder         : Lavf57.71.100
    Duration: 00:04:13.26, start: -0.021814, bitrate: 32 kb/s
        Stream #0:0(und): Audio: aac (HE-AACv2) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 32 kb/s (default)

  4.4.4 AAC音频质量对比

    AAC-LC的音频编码可以采用libfaac、libfdk_aac、FFmpeg内置AAC三种,其质量顺序排列如下。
    ·libfdk_aac音频编码质量最优
    ·FFmpeg内置AAC编码次于libfdk_aac但优于libfaac
    ·libfaac在FFmpeg内置AAC编码为实验品时是除了libfdk_aac之外的唯一选择
    注意:
    在新版本的FFmpeg中,libfaac已经被删除。

  4.5 系统资源使用情况

    音视频转码与音视频转封装的不同之处在于音视频转码会占用大量的计算资源,而转封装则主要是将音频数据或者视频数据取出,然后转而封装(Mux)成另外一种封装格式,转封装主要占用IO资源,而转码主要占用CPU资源,同时转码也会使用更多的内存资源,下面观察一下转码视频时的CPU资源使用情况。
    首先使用FFmpeg进行转码:

ffmpeg -re -i input.mp4 -vcodec libx264 -an output.mp4

    执行完上述命令行之后,使用系统命令top查看FFmpeg的CPU资源使用情况,结果如图所示。
在这里插入图片描述

  4.6 小结

    使用FFmpeg进行编解码(转码)相关的介绍至此已经告一段落,可以根据上述所讲按需使用,由于转码需要占用大量的计算资源,所以可以考虑多种优化手段进行支持。如果转码质量要求极高,那么必然需要大量的计算资源,可以考虑采用GPU进行编码,以节省CPU资源来进行其他工作。

猜你喜欢

转载自blog.csdn.net/migu123/article/details/129313337