本文主要了解FFmpeg进行音视频编码转换。主要学习如下几个知识点:
支持H.264的封装格式的文件格式有很多,例如FLV,MP4,HLS,TS等。FFmpeg本身不支持H.264的编码器,通过第三方库x264或者OpenH264来支持,但是OpenH264开源较晚,所以多数使用的还是x264,可以通过命令行ffmpeg -h encoder=libx264
来查看x264编码的一些基本信息和参数情况。
通过上面的-h命令查看x264支持的参数真的很多,我们在要用到优化的时候可以仔细了解其参数的含义,下面的几个实例列出了一些参数的使用,简单的了解参数的含义以及使用方法。每一个参数都可以带很多不同的配置,在使用的时候查看文档
这个参数主要调节编码速度和质量的平衡,有ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo这10个选项,从快到慢。
使用H.264转码文件
ffmpeg -i input.mp4 -vcodec libx264 -preset ultrafast -b:v 2000k output.mp4
输出关键速度信息
ffmpeg -i input.mp4 -vcodec libx264 -preset medium -b:v 2000k output.mp4
这个参数配合视频类型和视觉优化的参数。可选项
ffmpeg -i input.mp4 -vcodec libx264 -tune zerolatency -b:v 2000k output.mp4
profile和level的设置和H.264标准文档ISO-14496-Part10描述的profile和level信息基本相同。profile有如下选项:
下面使用baseline profile和high profile编码一个H.264视频,分析两个编码出来的文件的区别。有一个知识我们提取了解一下baseline profile编码出来额视频不会包含B帧,而high profile包含B帧,下面就看它们B帧的差别
ffmpeg -i input.mp4 -vcodec libx264 -profile:v baseline -level 3.1 -s 352x288 -an -y -t 10 ouput_baseline.ts
ffmpeg -i input.mp4 -vcodec libx264 -profile:v high -level 3.1 -s 352x288 -an -y -t 10 ouput_high.ts
生成了两个文件,通过ffprobe来查看包含B帧的信息
ffprobe -v quiet -show_frames -select_streams v output_baseline.ts |grep "pict_type=B"|wc -l
输出0
ffprobe -v quiet -show_frames -select_streams v output_high.ts |grep "pict_type=B"|wc -l
输出161
验证了我们的理论baseline profile包含0个B帧,而high profile包含B帧。在进行实时流媒体直播时,使用包含B帧的编码更可靠些;适当加入B帧可以有效降低码率
FFmpeg可以通过参数-g设置帧数间隔为GOP的长度,但是遇到场景切换的时候,从一个画面突然变为另一个画面时,会强行插入一个关键帧,这时GOP的长度会重新开始。可以通过参数sc_threshold决定是否在场景切换的时候插入关键帧。
执行命令控制编码时GOP的大小。
ffmpeg -i input.mp4 -c:v libx264 -g 50 -t 60 output.mp4
执行完毕后生成的文件每50帧被设置为一个GOP间隔。
通过软件Elecrd StreamEye查看帧信息如下:
看到有些GOP的间距很短,这是因为强行插入了GOP导致的,为了使GOP的插入更加均匀,使用sc_threshold设置一下:
ffmpeg -i input.mp4 -c:v libx264 -g 50 -sc_threshold 0 -t 60 output.mp4
再看GOP的帧信息如下:
由于FFmpeg设置x264参数时增加的参数比较多,FFmpeg开放了x264opts,可以通过这个参数设置x264的内部私有参数,如设置IBP帧的顺序以及规律。下面列举在上面生成的GOP文件数据分析基础上控制生成的文件不出现B帧,只要设置x264内部参数bframes=0即可:
ffmpeg -i input.mp4 -c:v libx264 -x264opts "bframes=0" -g 50 -sc_threshold 0 -t 60 output.mp4
通过StreamEye查看Stream信息没有出现B帧
如果希望控制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 -t 60 output.mp4
看看分析:
编码可以设置VBR,CBR的编码模式,VBR为可变码率,CBR为恒定码率。互联网上VBR居多,但是我们可以使用FFmpeg制作CBR码率视频。
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 -t 60 output.ts
命令执行参数介绍
可以通过工具Bitrate Viewer查看码率波动,我就没试了,通过Elecard StreamEye查看流信息的bitrate type为CBR。
以前都不知道FFmpeg可以硬编解码,以为它就只能软编解码,它真的强大。FFmpeg可以在Nvidia GPU,Intel QSV,树莓派,OS X系统下硬编解码。我使用的是OS X系统,所以下面来实验一个在该系统的硬编解码。
直接看一个硬转码的实例,先把一个视频通过h264_vda硬解码,然后通过h264_videotoolbox硬编码视频文件。
ffmpeg -vcodec h264_vda -i input.mp4 -vcodec h264_videotoolbox -b:v 2000k output.mp4
结果出现错误如下:
编码MP3使用编码器libmp3lame这个库,通过命令ffmpeg -h encoder=libmp3lame
可以查看它的一些参数信息。
先来看最简单的一条命令使用libmp3lame来进行音频文件编码为MP3文件。
ffmpeg -i input -acodec libmp3lame output.mp3
控制码率的参数为-q:a后面带数字
AAC是一种比MP3的编码效率更高,编码音质更好的音频编码格式,常见的使用AAC编码后的文件存储格式为m4a。FFmpeg可以使用如下三种编码器
看下面最简单的例子:
ffmpeg -i input.mp4 -c:a aac -b:a 160k output.aac
同样可以使用-q:a带数值代表的码率信息进行转换