FFmpeg测试序列
经常需要做测试以及功能验证,每次都要找个视频文件或者线上拉一路流推流。在某些测试场景下,视频文件和线上的流都存在一定的码率波动,对于实际的测试数据有一定的影响。所以需要一路码率、帧率、GOP等参数可调且尽可能标准的测试流,并且使用方式要尽可能的简答,适用大多数的场景。
一般机器都安装FFmpeg
,所以打算用FFmpeg
实现测试流的生成。查阅资料发现FFmpeg
的lavfi
自带简单的测试视频,利用ffmpeg
本身的一堆编码参数便可以得到想要的标准测试流。
FFmpeg安装
FFmpeg
的安装,参考官网的指南足矣。其他的安装指南写得再好,还是没有官方的好,而且附带中文版,集成了几乎平时用到的所有lib。
我在一台VPS上安装X265
库的时候出了个问题:
我通过以下操作解决:
卸载yum
原本的yasm
yum remove yasm
将按照官方指南中安装的高版本的yasm
链接到PATH
ln -s /root/bin/yasm/usr/bin/yasm
安装完毕
测试流生成
视频
利用lavfi生成测试视频,查到以下说明,按图索骥即可生成测试图像。
http://www.bogotobogo.com/FFMpeg/ffmpeg_video_test_patterns_src.php
此处我采用的参数如下,使用testsrc这个图像,很有小时候周二下午的回忆。
-f lavfi -i "testsrc=size=1920x1080:rate=30:duration=5"
参数含义:
参数 | 含义 |
---|---|
testsrc |
使用testsrc 作为测试画面 |
size |
分辨率 |
rate |
帧率 |
duration |
持续时间 |
音频
测试音频采用sine正弦波。可条件频率,采样率等参数。具体参考官网说明
https://lists.ffmpeg.org/pipermail/ffmpeg-cvslog/2013-March/062382.html
此处我采用的参数是:
-f lavfi -i "sine=frequency=440:sample_rate=44100:beep_factor=4:duration=5"
参数含义:
参数 | 含义 |
---|---|
sine |
使用正弦波信号作为输入 |
frequency |
正弦波频率 |
sample_rate |
音频采样率 |
beep_factor |
每秒产生一个蜂鸣,蜂鸣频率为正弦波频率的四倍 |
duration |
持续时间 |
合成测试流
将以上视频和音频作为FFmpeg
的输入,通过ffmpeg自带的一些编码参数和码率控制参数输出。
ffmpeg -f lavfi -i testsrc=duration=5:size=1920x1080:rate=300 \
-f lavfi -i sine=frequency=440:sample_rate=44100:beep_factor=4:duration=5 \
-acodec libfdk_aac \
-vcodec libx264 -bf 0 -b:a 100k -b:v 1900k -bufsize 1000k \
-r 30 -g 30 -sc_threshold 0 \
-profile baseline -pix_fmt yuv420p \
-f flv test.flv
输出画面如下:
观察生成的test.flv
,发生其码率并不是指定的音频100kbps,视频1900kbps,而是只有730kbps。
# ffmpeg -i test.flv
...
Input #0, flv, from 'test.flv':
Metadata:
encoder : Lavf58.3.100
Duration: 00:00:05.08, start: 0.000000, bitrate: 730 kb/s
Stream #0:0: Video: h264 (Constrained Baseline), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 1900 kb/s, 30 fps, 30 tbr, 1k tbn, 60 tbc
Stream #0:1: Audio: aac (LC), 44100 Hz, mono, fltp, 100 kb/s
无论如何修改指定的码率的值,输出码率总是明显小于指定值。
查阅资料后,使用x264
的参数,启用CBR模式,解决问题,码率稳定在2000kbps左右:
ffmpeg -f lavfi -i testsrc=duration=5:size=1920x1080:rate=30 \
-f lavfi -i sine=frequency=440:sample_rate=44100:beep_factor=4:duration=5 \
-acodec libfdk_aac -b:a 100k \
-vcodec libx264 -x264opts bitrate=1900:vbv-maxrate=1900:vbv-bufsize=1000:nal_hrd=cbr \
-r 30 -g 30 -sc_threshold 0 \
-profile baseline -pix_fmt yuv420p \
-f flv test.flv
以上FFmpeg
参数含义:
参数 | 含义 |
---|---|
-acodec libfdk_aac |
指定音频编码为aac 格式 |
-b:a 100k |
指定音频编码输出码率为100kbps |
-vcodec libx264 |
指定视频编码为h264 格式 |
-x264opts |
启用x264 参数 |
-x264opts bitrate=1900 |
x264 参数:指定视频输出码率为1900kbps |
-x264opts vbv-maxrate=1900 |
x264 参数:指定视频输出的最高码率为1900kbps |
-x264opts vbv-bufsize=1000 |
x264 参数:指定视频编码的buffer为1000kb |
-x264opts nal_hrd=cbr |
x264 参数:设置HRD为CBR,严格按照指定码率转码 |
-r 30 |
指定输出帧率为30fps |
-g 30 |
指定输出视频GOP 为30帧 |
-sc_threshold 0 |
视频编码关闭 scenecut 模式,用以不再自动生成I帧 |
-profile baseline |
指定视频编码规则为baseline |
-pix_fmt yuv420p |
指定输出数据格式为yuv420p ,baseline 只支持这种 |
-f flv |
指定输出封装为flv 格式 |
# ffmpeg -i test1.flv
...
Input #0, flv, from 'test1.flv':
Metadata:
encoder : Lavf58.3.100
Duration: 00:00:05.05, start: 0.000000, bitrate: 1975 kb/s
Stream #0:0: Video: h264 (Constrained Baseline), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 1900 kb/s, 30 fps, 30 tbr, 1k tbn, 60 tbc
Stream #0:1: Audio: aac (LC), 44100 Hz, mono, fltp, 100 kb/s
At least one output file must be specified
此处观察FFmpeg
打印的日志发现,两次转码只在x264
的参数上差了一个指标,如下两图,下图指定了nal_hrd=cbr
。
那么这个nal_hrd=cbr
又是什么鬼呢?
HRD?没搞明白
上述两者的唯一区别便是nal_hrd是否有设置成CBR,CBR(Constant Bitrate, 常数比特率 ) ABR(Average Bitrate)
VBR(Variable Bitrate)只是x264按下不表。并没有查到相关资料,没有搞明白这些跟HRD有啥关系。
假想码流调度器(hypothetical reference decoder, HRD),wiki上说在264标准中,HRD已经被VBV代替了,也就是设置的vbv-maxrate
和vbv-bufsize
两个参数。不清楚为什么还需要设置HRD为CBR模式。
关于VBV中vbv-maxrate
和vbv-bufsize
两个参数的关系,这个文章中有所解释:http://www.bretl.com/mpeghtml/VBV.HTM
实际使用
ffmpeg -re -f lavfi -i testsrc=duration=5:size=1920x1080:rate=30 \
-re -f lavfi -i sine=frequency=440:sample_rate=44100:beep_factor=4:duration=5 \
-acodec libfdk_aac -b:a 100k \
-vcodec libx264 -x264opts bitrate=1900:vbv-maxrate=1900:vbv-bufsize=1000:nal_hrd=cbr \
-r 30 -g 30 -sc_threshold 0 \
-profile baseline -pix_fmt yuv420p \
-f flv rtmp://127.0.0.1:1935/xujk.test.com/live/stream