FFmpeg 3-pass视频编码

前言

最开始是在论文《ABR Streaming of VBR-encoded Videos: Characterization, Challenges, and Solutions》(CoNext’18)中看到的“‘three-pass’ encoding procedure”,觉得不解,上网搜索一遍发现并没有特别全面的资料。后来,随着对于FFmpeg、H.264编码的了解,加上阅读了上文引用的Netflix的原文章《A Large-Scale Video Codec Comparison of x264, x265 and libvpx for Practical VOD Applications》,逐渐摸清楚了答案。特记此文,以便需要的人查阅。


什么是3-pass编码?

以H.264的视频编码为例,通常2-pass编码较为常用。比如:

那么,什么是3-pass编码呢?
关于3-pass编码,Netflix在论文中如此描述(为通用起见,稍微改动了一点):

  • In a first step, each clip is encoded using a CRF (x264/x265) or constant QP (libvpx) value
  • In a second step, the output bitrates of step 1 are used to drive the two-pass VBR encode

对于H.264视频而言:

  • 第一步,使用CRF进行编码
  • 第二步,将第一步得到的视频的码率作为目标码率,执行2-pass编码

也就是说,3-pass编码实际上是在2-pass编码前加了一步CRF编码,即:

3-pass = CRF + 2-pass

*关于什么是CRF及其跟QP的区别,可以参见:CRF和QP的区别
*简单来说,CRF能够根据视频内容去调节编码所需要的QP参数,从而使得编码后的视频质量保持稳定
*对于H.264,CRF的默认值是23。此外,Netflix在论文中指定了8个CRF参考值,分别为:15, 19, 23, 27, 31, 35, 39, 43


为什么要用3-pass编码?

解决了3-pass是什么的问题之后,我们不禁会想:为什么要用3-pass编码
继续看Netflix在论文中的描述:

  • To determine the bitrates in a content-adaptive way, the following (`three-pass’) procedure was used…
  • This procedure ensures that we avoid over-allocation of the bitrate for easy clips and under-allocation for complex clips, and still benefit from 2-pass rate control.

其实可以从3-pass编码这两部分进行考虑,用CRF是为了做到内容感知,也就是保证视频质量;用2-pass是为了控制码率,压缩简单场景的码率,提升复杂场景的码率。因此,3-pass编码的目标就是在保证视频质量的同时合理分配码率。


怎么进行3-pass编码?

选择Elephant Dream 1080p作为原视频(详见:DSAH视频系统(服务器&播放器)搭建),3-pass编码步骤如下:

step1:使用CRF对原始视频进行编码(默认值为23)
参考:CRF Guide (Constant Rate Factor in x264, x265 and libvpx)

扫描二维码关注公众号,回复: 15618725 查看本文章
ffmpeg -i elephants_dream_1080p24.y4m -s 1920x1080 -c:v libx264 -crf 23 -an tmp1920x1080.mp4

*注:y4m貌似没有音频,使用这里不对音频进行编码
根据ffmpeg的输出信息,得到的视频码率为:3664.85kbps

step2 & step3:使用step1得到的视频码率,对视频进行2-pass编码
(如果我没理解错的话,应该是对原始视频进行2-pass编码)

ffmpeg -i elephants_dream_1080p24.y4m -s 1920x1080 -c:v libx264 -b:v 3665k -pass 1 -an -f mp4 /dev/null && \
ffmpeg -i elephants_dream_1080p24.y4m -s 1920x1080 -c:v libx264 -b:v 3665k -pass 2 -an out1920x1080.mp4

*注:这是Ubuntu下的写法,Windows下需要把/dev/null改成NUL,把\换为^
这样就完成了3-pass视频编码

*我把tmp1920x1080.mp4和out1920x1080.mp4俩视频同时播放了一下,怎么感觉一次编码得到的视频比3-pass的还要清楚……

猜你喜欢

转载自blog.csdn.net/LvGreat/article/details/103536196