实现目标:视频转码及压缩功能
厂站上支持将flv视频格式转码为MP4等通用视频格式,要求转码后的视频可以进行回放、拖拽。
当前主站方案
切片
ffmpeg -i /sysadm/lvting/ffmpeg/y.flv -ss 300 -t 120 -codec copy qp3.flv
不花时间,不费cpu ,切片时间有几秒的差异
ffmpeg -i /sysadm/lvting/ffmpeg/006.flv -ss 300 -t 120 -codec copy qp4.flv
006.flv 是gop 为2000 的视频。切割后视频只有19s,开始时间也不准确。
date && ffmpeg -hide_banner -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i /sysadm/lvting/ffmpeg/006.flv -ss 300 -t 120 -c:v h264_vaapi -qp 30 -g 2000 qp7.flv && date
切片完全正确,视频时间为2min即120s,4s 283k
date && ffmpeg -hide_banner -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i /sysadm/lvting/ffmpeg/006.flv -ss 300 -t 120 -vf "scale_vaapi,hwmap=mode=read+write+direct,format=nv12,drawtext=fontfile=simhei.ttf: text='jiayou':x=100:y=10:fontsize=28:fontcolor=red@0.8,hwmap" -c:v h264_vaapi -qp 30 -g 2000 qpsy8.flv && date
切片完全正确,视频时间为2min即120s,5s 603k
压缩方式
date && ffmpeg -y -hide_banner -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i /sysadm/lvting/ffmpeg/y.flv -vf 'hwdownload,format=nv12' -c:v libx264 -qp 30 003.flv && date
43M->4.3M 20s cpu 330%
date && ffmpeg -hide_banner -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i /sysadm/lvting/ffmpeg/y.flv -c:v h264_vaapi -qp 30 004.flv && date
43->4.3M 11s cpu 30%
date && ffmpeg -hide_banner -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i /sysadm/lvting/ffmpeg/y.flv -c:v h264_vaapi -qp 30 -g 2000 006.flv && date
43->1.3M 10s cpu 30%
当前主站采用量化参数qp帮助实现视频压缩,对应到厂站使用gstreamer的quant属性。
测试过程
查看插件信息:gst-inspect-1.0 vpuenc_h264
vpuenc_h264的bitrate属性和quant属性分别有什么作用
vpuenc_h264编码器的 bitrate属性和quant属性分别对应视频的恒定码率和恒定质量控制模式。
bitrate属性表示视频的目标码率,单位为kbps,该属性控制视频编码时生成的比特流的平均数据率。在恒定码率模式下,编码器会尽可能地根据目标码率和视频内容来控制视频质量,以保证视频的目标码率不超过所设定的值。如果设置的值过小,则可能会导致视频质量不佳或丢失画面。
quant属性表示视频的目标质量,它是一个无单位的量化参数,用于控制编码器的量化和压缩程度。在恒定质量模式下,编码器会根据该参数和源视频的内容来调整比特流的大小,以保证视频的目标质量和视觉体验。通常,较小的量化参数意味着更好的视频质量,但会带来更大的比特流大小和码率。
对比测试,调参bitrate码率和quant量化参数
把量化参数调最小了,bitrate的影响已经微乎其微了,依旧比较模糊,尤其画面中字比较多而且总是变化时更为明显。
模仿主站写成-qp 30形式,不添加bitrate:
bitrate和quant属性对视频压缩的助力有限,查看插件信息考虑使用GOP属性。
GOP的作用
GOP(Group of Pictures)是视频编码中的一个概念,它表示一组连续的视频帧。在视频传输和存储中,GOP的作用很重要。具体来说,GOP中包含有帧、Р帧和B帧。
- l帧:Intra-coded Picture,即关键帧,是完整的图像帧,不依赖于前面或后面的任何帧进行解码。I帧通常被用于视频序列的关键点,比如场景切换、镜头转换等,因为I帧可以确保解码器正确解码之后的所有帧。在GOP中,I帧出现的位置通常是周期性的。
- P帧:Predictive-coded Picture,即预测帧,是通过参考上一帧I帧或P帧,通过预测来构造的图像帧。P帧一般比帧小,并且帧间冗余较高,压缩效果较好。
- B帧:Bi-directional Predictve-coded Picture,即双向预测帧,是通过参考前后两帧进行预测来构造的图像帧。B帧一般比I帧和P帧都小,并且在帧间冗余方面表现最好,因比对于容量有限的存储介质(比如DVD)来说,应用较多。
在视频中,GOP的出现是为了提高视频的编码效率和压缩比例,同时保证解码器正确地解码视频流。因为在一定时间内,视频中的画面通常是连续的,并且很多画面元素都是相似的。因此,通过将一组相关的帧放在一起进行编码,可以更好地利用这些相似之处来进行数据压缩,从而获得更高的压缩比例。而I帧则定义了视频序列的关键点,确保了解码器正确地解码视频序列,从而使视频播放更加流畅和稳定。
vpuenc_h264的gop-size属性有什么作用
vpuenc_h264编码器元件的gop-size属性用于控制视频的Group of Pictures(GOP)大小,即帧组大小。
gop-size属性表示GOP的大小或长度,以帧数为单位。在编码过程中,编码器会根据该属性设置在GOP内插入多少个P帧和B帧,以及在何时生成关键帧(I帧)。较小的GOP 大小通常意味着更好的视频质量,但会带来更高的编码复杂度和比特流大小,从而影响视频的传输和存储效率。而较大的GOP大小可以提高编码效率和传输效率,但可能会导致视频质量下降,尤其是在快速移动的场景下。
因此,在选择gop-size大小时,应综合考虑视频内容、编码质量、传输带宽和存储需求等因素,以达到最佳的平衡。通常,较小的gop-size大小适用于需要高质量视频的场景,例如实时视频会议或流媒体直播等;而较大的 gop-size大小则适用于网络带宽受限、存储空间有限或不需要很高质量视频的场景,例如普通视频通话或监控录像等。
测试gop-size属性的作用效果
在原有bitrate和quant属性基础上添加gop-size
码率bitrate在这个视频压缩方案中的效果可能不太理想
单独调gop-size
单独调gop-size对压缩的帮助不够
测试gop-size和quant的复合效果
视频压缩结果(右侧单位Size(KB))
软编软解方案对比:ffmpeg去掉vaapi硬件加速的执行情况
ffmpeg -y -hide_banner -i /home/kuangan/Videos/vod/VEVPK8I2TV-10.200.255.34-2023-07-05-13:59:19.flv -c:v h264 -qp 30 -g 2000 /home/kuangan/Videos/vod/VEVPK8I2TV.mp4
对比测试一
不添加硬件加速:将size为23521KB大小的flv→354KB的MP4
size少 可能因为视频中变化很小,所以只需要一些关键帧 执行时间3分钟,cpu占用300%左右
添加硬件加速:
执行时间11秒,cpu占用50%左右
添加关键帧的gop-size:
视频效果看不出来明显差别,从23MB减少到几百KB这么少,可能是因为这个录制的视频变化比较小,基本上没有变化,换一个视频波动大一点的再试一下
对比测试二
未进行硬件加速:cpu占用率达300%,运行时间约8min,size大小60MB→9.7MB
进行硬件加速:cpu占用率26%,运行时间约22s,size大小60MB→17.9MB
硬件加速视频压缩转码方案总结
1. 软编软解方案
-
多媒体支持库选择
选择FFmpeg进行视频转码。FFmpeg 是一个开源的跨平台音视频处理套件,包含了多个用于处理音视频数据的程序和库。FFmpeg 将音视频数据作为流来处理,支持多种音视频格式的编解码和转换,并可以兼容各个操作系统。
-
方案实现
- 检查系统是否已经安装了FFmpeg :ffmpeg -version
- 检查FFmpeg 的安装范围在/aaa/ffmpeg:which ffmpeg
- 使用FFmpeg 指令简单实现视频转码为H.264编码格式的功能:
/aaa/ffmpeg -i /input_location/input_stream_name.flv -c:v h264 /output_location/output_stream_name.mp4
- 修改量化参数和关键帧间隔的大小
/aaa/ffmpeg -y -hide_banner -i /location/input_stream_name.flv -c:v h264 -qp 30 -g 2000 /location/output_stream_name.mp4
-qp表示量化参数,是 H.264 编码器中控制视频质量和压缩比的一个重要参数。量化参数越小,获得的视频质量更高,但文件大小更大。设置量化参数为 30,即以较高的视频质量为主,但也会有一定的压缩效果。
-g表示关键帧间隔,即每隔多少帧生成一个关键帧(I 帧)。关键帧是视频编码时恢复视频帧的起点,能够保证视频数据的完整性和正确性。较大的 GOP size 可以获得更高的视频压缩比,但也会增加视频数据的延迟和丢失风险。
-
运行效果
- 达成目的:对flv格式的视频转码为MP4格式进行保存,转码后的视频可以进行播放、拖拽。由于使用了关键帧参数,对视频进度条进行拖拽后,需要等待几秒的时间才会继续播放视频,并且文件大小的前后变化大致为:60MB→10MB。
- 性能分析:文件大小60MB,cpu占用率达300%,运行时间8分钟,录像较清晰,可进行回放、拖拽。
使用软编软解可以实现方案,但是性能不优,考虑对该过程采用硬件加速。
2. 硬编硬解方案
-
系统及硬件
查看硬件平台 uname -i:aarch64
查看操作系统 cat /etc/os-release:KylinSec OS Linux(IoT Version)
查看GPU信息 lspci | grep VGA:没有GPU信息显示
CPU:i.MX 8MP
结果:没有GPU设备信息,但i.MX 8M类CPU采用了Hantro VPU的加速IP核,VPU提供了在Gstreamer上的硬件加速插件。
-
多媒体支持库选择
选择Gsteamer进行视频转码。
Gstreamer的基本思想:Gstreamer以element的基本形式(也就是plugin(插件))存在。两端的pad负责输入和输出,而由当中的element来完成具体工作。总的来说,Gstreamer内容与FFmpeg相似,但是会以element的形式进行管理,最后用pipeline将这些内容连接在一起,由第一个向最后一个推送数据。
Gstreamer的使用方式:Gstreamer由插件组成。每一次播放,编码或者转码都会以一条pipeline的形式出现,里面所有的元素都以插件的形式存在并相互协作。
与FFmpeg相比,Gstreamer的优势:FFmpeg主要还是用于做编解码,而Gstreamer还包括了2D/3D rendering等视音频功能;Gstreamer只需要简单搭建pipeline,放入正确的插件,插件之间以!符号相连接,即可完成,非常直观。而各个插件的具体参数是自动协商完成的,不需要用户指定大量参数。
Gstreamer官方手册:
-
方案实现
1. 列出插件信息:gst-inspect-1.0 --plugin
2. 查看硬件加速插件信息:gst-inspect-1.0 | grep vpu
vpudec: IMX VPU-based video decoder
vpuenc_h264: IMX VPU-based AVC/H264 video encoder
3. 使用指令实现硬件加速的视频转码功能:
gst-launch-1.0 -e filesrc location=/input_location/input_stream_name.flv ! flvdemux name=demux demux.video ! vpudec ! vpuenc_h264 ! queue ! h264parse ! mp4mux ! filesink location=/output_location/output_stream_name.mp4
Size前后变化为60MB→28MB,消耗时间21.873s,可通过调参优化性能。
4. 对vpuenc_h264的属性进行调参过程
bitrate 属性:表示视频的目标码率,该属性控制视频编码时生成的比特流的平均数据率。
quant属性:表示视频的目标质量,它是一个无单位的量化参数,用于控制编码器的量化和压缩程度。
gop-size 属性:控制了生成关键帧(I 帧)的间隔,用于设置 GOP(Group of Pictures)的大小,即每隔多少帧生成一次关键帧。
bitrate(kbps) | quant | gop-size | 原始文件大小(MB) | 转码后文件大小(MB) | 消耗时间(秒) | 结果 |
1500 | 10 | \ | 78 | 14.9 | 12.996 | 画面很模糊 |
1500 | 5 | \ | 78 | 15.3 | 12.980 | 视频质量略好转,但仍有部分模糊 |
2000 | 1 | \ | 78 | 16.1 | 13.037 | 视频产生变化时,看不清内容,提高码率+提高视频质量的方案的压缩效果不错,但视频质量不佳 |
\ | 35 | \ | 78 | 64 | 13.492 | 画面很清晰,但压缩效果不明显 |
\ | 40 | \ | 78 | 45.4 | 13.271 | 画面较为清晰,但单独调大量化参数的压缩效果不明显 |
2000 | 1 | 15 | 78 | 20 | 13.079 | 画面很模糊 |
2000 | 1 | 10 | 78 | 23.8 | 13.070 | 视频产生变化时,看不清内容 |
\ | \ | 25 | 78 | 67 | 13.596 | 画面很清晰,但压缩效果不明显 |
\ | \ | 30 | 78 | 64 | 13.480 | 画面很清晰,但压缩效果不明显 |
\ | \ | 40 | 78 | 61 | 13.516 | 画面很清晰,单独调大gop-size的作用越来越不明显 |
\ | 40 | 20 | 78 | 49.8 | 13.306 | 画面很清晰,但压缩效果不明显 |
\ | 40 | 25 | 78 | 47.6 | 13.267 | 画面较为清晰,压缩效果不明显 |
\ | 45 | 25 | 78 | 30.3 | 13.145 | 画面看得清,但压缩效果不够 |
5. 最终方案
gst-launch-1.0 -e filesrc location=/input_location/input_stream_name.flv ! flvdemux name=demux demux.video ! vpudec ! vpuenc_h264 quant=30 gop-size=2000 ! queue ! h264parse ! mp4mux ! filesink location=/output_location/output_stream_name.mp4
quant表示量化参数,H.264 编码器通过调整不同的量化参数来达到视频质量和压缩比之间的平衡。
gop-size表示关键帧间隔,即每隔 2000 帧生成一个关键帧(I 帧)。
-
运行效果
- 达成目的:flv格式的视频转码为MP4格式保存,转码后的视频可以进行播放、拖拽。由于使用了关键帧参数,对视频进度条进行拖拽后,同样需要等待几秒的时间才会继续播放视频,与硬件加速前的方案相比等待时间减少。转码后的文件大小减小,前后变化大致为:60MB→18MB。
- 性能分析:原始文件大小60MB,cpu占用率26%,运行时间22秒,录像比较清晰,可进行回放、拖拽。
编解码命令总结
1. 原始压缩命令(软编软解)
/aaa/ffmpeg -y -hide_banner -i /location/input_stream_name.flv -c:v h264 -qp 30 -g 2000 /location/output_stream_name.flv
60MB→10MB,300%cpu,耗时8分钟
2. 原始转码+压缩命令(软编软解)
与原始压缩命令相似,将输出视频文件的后缀名替换即可:
/aaa/ffmpeg -y -hide_banner -i /location/input_stream_name.flv -c:v h264 -qp 30 -g 2000 /location/output_stream_name.mp4
60MB→10MB,300%cpu,耗时8分钟
3. 调用硬件加速插件压缩命令(硬编硬解)
gst-launch-1.0 -e filesrc location=/input_location/input_stream_name.flv ! flvdemux name=demux demux.video ! vpudec ! vpuenc_h264 quant=30 gop-size=2000 ! queue ! h264parse ! flvmux ! filesink location=/output_location/output_stream_name.flv
60MB→17.9MB,26%cpu,耗时22秒
4. 调用硬件加速插件转码+压缩命令(硬编硬解)
调用转码命令时,输出视频文件的后缀名被替换,且解交织的插件需要被替换:
gst-launch-1.0 -e filesrc location=/input_location/input_stream_name.flv ! flvdemux name=demux demux.video ! vpudec ! vpuenc_h264 quant=30 gop-size=2000 ! queue ! h264parse ! mp4mux ! filesink location=/output_location/output_stream_name.mp4
60MB→17.9MB,26%cpu,耗时22秒