暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

探索VMAF(一):简介、安装和使用

AggrxTech 2021-09-17
4547
当今,视频已经成为信息的主要载体在互联网上传播。很多公司或生产、或分发,纷纷都投入到这个领域中来。日益激烈的竞争让大家纷纷开始关注视频本身的质量,比如能否秒开、播放是否清晰、是否流畅等等。本文分享的就是这样一款被业界普遍接受,并纷纷开始使用的视频质量的评价工具。

1. 视频质量评价

视频质量评价最基本的两种方式就是主观和客观评价。前者完全依赖个人体验,后者则依赖各种算法和量化指标。比如此前应用比较多的峰值信噪比(PSNR)、结构相似性指数(SSIM)。VMAF通过机械学习的方式将主客观评价结果结合起来,得到一个相对全面的量化指标。

2. VMAF

2.1. 什么是VMAF

简单带过,VMAF(Video Multimethod Assessment Fusion)是Netflix研发并使用的,用于评价视频压缩前后视频质量的工具。它目前已经开源,并且可以集成到ffmpeg上使用。

2.2. VMAF的作用

评价某个或某两个不相关的视频的质量是没有意义的,我们都知道为了存储和传输视频,我们需要对视频进行编码,而压缩往往是有损的,我们肯定希望压缩后的视频越小,质量越高越好,但是不同的视频,不同的压缩参数,会产生不同的压缩比和损失。VMAF就可以用来量化评价编码前后视频的质量,来帮助人们选择和设置更合理、效果更好的编码格式和参数。

3. VMAF安装

3.1. 仅安装vmaf

当前版本的VMAF(https://github.com/Netflix/vmaf)是需要自己make&install的,网上有很多教程,但我建议参考libvamf的README安装。make的时候可能会遇到很多问题,因为遇到的问题不一定一样这里就不再列举,但提示一下如果实在找不着了,建议看看Meson是不是最高版本,我是升级到0.59.1才能成功。


3.2. FFmpeg上支持vmaf

在FFmpeg上使用vmaf十分方便,直接使用mp4格式的文件,不需要将yuv或y4m抽出来。这里分两种情况:没有安装了ffmpeg的同学和已经安装了的同学。
  • 没有安装ffmpeg
    最新版本的ffmpeg已经支持了vmaf,可以直接安装:

    brew install ffmpeg

    如果一定要自己build,下载ffmpeg代码,进入目录后执行configure时增加--enable-libvmaf参数。

    ./configure --enable-libvmaf ......

  • 已经安装了ffmpeg
    这部分同学我建议删了重装ffmpeg,省时省心省力,步骤如上。

4. VMAF使用

本文主要介绍借助ffmpeg来执行vmaf这种方式。当开启vmaf的ffmpeg安装好后,就可以通过命令行来调用执行。命令支持很多参数,官网上也列举了一部分基本参数,大家可以查看参数说明。

这里,我们结合场景对一些常用参数进行说明,包括一些上面没有列举的参数。


4.1. 基本命令

vmaf是作为过滤器libvmaf被包含在ffmpeg中,我们需要按照过滤器的命令格式输入-->过滤器-->输出来设置命令参数。
  • 输入
    我们的目的是为了评价视频转码前和转码后的质量,所以参数至少需 要两个视频如下:

    • original.mp4: 原视频

    • encoded.mp4: 编码后的视频

  • 输出
    因为我们不需要生成什么视频文件,所以将输出设置为标准输出(-),而标准输出又需要-f参数指定输出格式,这里也不需要什么特定的格式,所以可以设置为根据输入选择(null),这样输出这部分就是-f null -

  • 过滤器
    指定复杂过滤器参数-fileter_complex
    -lavfi
    ,过滤器名称libvmaf。

此时我们拼接了一个最基本的命令:

ffmpeg -i original.mp4 -i encoded.mp4 -lavfi libvmaf -f null -

原视频和编码后的视频先后顺序无所谓,但后面会有一些对视频的处理操作,你必须知道它们哪个是哪个。


4.2. 指定模型

如果你直接运行上面的命令会报错:
libvmaf WARNING could not read model from path: "/usr/local/share/model/vmaf_v0.6.1.pkl"
libvmaf WARNING pkl model files have been deprecated, use json
libvmaf ERROR problem loading model file: /usr/local/share/model/vmaf_v0.6.1.pkl

前文已经提到,vmaf是结合机械学习实现的一下评价体系,提到机械学习,你可能立刻会想到需要大量样本来训练模型,的确vmaf支持自己训练模型,但同时也内置了很多已经训练好的模型,vmaf_v0.6.1就是其默认模型。vmaf的内置模型在/yourpath/vmaf/model中:


回到刚刚的报错上,很显然是找不到默认的模型文件,我们可以在过滤器中指定一下:

ffmpeg -i original.mp4 -i encoded.mp4 -lavfi libvmaf=model_path=../model/vmaf_v0.6.1.json -f null -

此时计算就可以正常执行了。如果是想使用手机端的默认模型,可以指定phone_model:

ffmpeg -i original.mp4 -i encoded.mp4 -lavfi libvmaf=model_path=../model/vmaf_v0.6.1.json:phone_model=1 -f null -


4.3. 指定log文件

如果不指定log文件,你能得到的结果只有一句:
VMAF score: 89.067879

更多的信息需要在过滤器中指定日志文件,通过log_fmt指定日志格式,建议用xml,比较容易观察,通过log_path指定输出路径。如果不需要文件,也可以直接指定到标准输出:

ffmpeg -i original.mp4 -i encoded.mp4 -lavfi libvmaf=model_path=../model/vmaf_v0.6.1.json:log_fmt=xml:log_path=/dev/stdout -f null -

执行此命令,你会发现多了很多输出,这个执行结果我们放到最后说。


4.4. 需要增加处理的场合

vmaf对传入的视频有一定要求,我们编码前后的视频不一定是恰好合适的,下面就列举几种需要处理的情况。
  • 当视频分辨率不一致时
    当我们传入的两个视频分辨率不一致时,会得到报错:

    Width and height of input videos must be same

    如提示所说,vmaf要求传入两个视频分辨率一致。但是,在视频编码的过程中,我们经常会改变视频的分辨率,所以不可以避免的我们需要处理分辨率不一致的情况。很简单,统一分辨率要么把大分辨率的视频变小(下采样),要么把小分辨率的视频变大(上采样)。

    下采样:假设原图分辨率为W * H,缩小S倍,分辨率为W/S * H/S,那么我们需要将原图S * S区域内的像素取均值,成为一个像素;
    上采样:采用内插值算法增补像素,将图像放大。

    回到例子中,原视频(original)分辨率为1280*720,编码后的视频(encoded)分辨率为1024*576,我们分别看看上下采样的命令和执行结果:
    上采样:

    ffmpeg -i original.mp4 -i encoded.mp4 -lavfi "[1:v]scale=1280:720[encoded];[0:v][encoded]libvmaf=model_path=../model/vmaf_v0.6.1.json:log_fmt=xml:log_path=/dev/stdout" -f null -

    解释一下,[x:v]的意思是取传入的第x+1个视频的视频流,然后变换到1280*720,并将此操作后的结果命名为[encoded],然后我们将第一个视频的视频流[0:v]和处理过后的[encoded]一同传入之前设置的过滤器libvmaf。
    这里得到的vmaf值为:83.330639。
    下采样:

    ffmpeg -i original.mp4 -i encoded.mp4 -lavfi "[0:v]scale=1024:576[origin];[origin][1:v]libvmaf=model_path=../model/vmaf_v0.6.1.json:log_fmt=xml:log_path=/dev/stdout" -f null -

    这里得到的vmaf值为:85.817568。我们只能说对于此视频来说差别不大,但建议还是优先采用下采样。

  • 当PTS不一致的时候
    PTS(Presentation Time Stamp)标识某一帧的显示时间,因为有I、P、B帧的存在,我们需要保证某帧不在某帧前显示,所以才有了PTS。当PTS不一致时我们需要将PTS统一,可以直接统一到从0开始计数。

    ffmpeg -i original.mp4 -i encoded.mp4 -lavfi "[0:v]scale=1024:576,setpts=PTS-STARTPTS[origin];[1:v]setpts=PTS-STARTPTS[encoded];[origin][encoded]libvmaf=model_path=../model/vmaf_v0.6.1.json:log_fmt=xml:log_path=/dev/stdout" -f null -

  • 当视频时间不一致时
    如果要测试的两个视频时长不一致,那么我们需要指定以短视频为准,短视频处理完毕,则整个计算结束。需要用到的参数是shortest和repeatlast。

    ffmpeg -i original.mp4 -i encoded.mp4 -lavfi "[0:v]scale=1024:576,setpts=PTS-STARTPTS[origin];[1:v]setpts=PTS-STARTPTS[encoded];[origin][encoded]libvmaf=model_path=../model/vmaf_v0.6.1.json:log_fmt=xml:log_path=/dev/stdout:shortest=1:repeatlast=0" -f null -

    shortest:
    默认值是0,即为当短视频处理结束后,不会停止,这里设置为1;
    repeatlast:
    默认值是1,即直到较长的视频结束前,较短的视频会一直反复处理,这里设置为0。


4.5. VMAF执行结果

vmaf最终结果是一个0~100之间的数字,越大越好。通常情况下,我们认为95分以上基本没有差异,93~95分能感知到差异但可接受,91分以下通常差异比较明显。

你会遇到一种情况就是整体看视频觉得效果还行,但评分却很低。如果你执行的是上面的命令,那么请查看一下log,你会发现里面包含了每一帧计算的结果,比如第0帧:

<frame frameNum="0" integer_adm2="0.992588" integer_adm_scale0="0.974760" integer_adm_scale1="0.985340" integer_adm_scale2="0.994697" integer_adm_scale3="0.998173" integer_motion2="0.000000" integer_motion="0.000000" integer_vif_scale0="0.795167" integer_vif_scale1="0.978604" integer_vif_scale2="0.991164" integer_vif_scale3="0.995545" vmaf="94.955235" />

然后请找一下vmaf值比较低的帧,利用ffmpeg取出编码后视频和原视频的对应帧,再做对比,能发现比较明显的差异。
原视频某帧:

编码后同一帧:

随着人们对视频质量的愈加关注,vmaf的使用也越来越多,并且相较于其他指标,vmaf的结果更加贴近人的真实感受,同时又是标准统一的量化值,有助于发现视频编码过程中的问题并加以改进。本文主要着眼于vmaf工具在ffmpeg上的使用,逐一列举要注意的点,并解释常用参数的含义和配置,希望对正准备使用vmaf的小伙伴有一定帮助。

【参考文献】

  • 《libvmaf》(https://github.com/Netflix/vmaf/blob/master/libvmaf/README.md)

  • 《Using VMAF with FFmpeg》(https://github.com/Netflix/vmaf/blob/master/resource/doc/ffmpeg.md)

  • 《新しい映像の品質評価 LIBVMAF》(https://nico-lab.net/libvmaf_with_ffmpeg/)

  • 《ffmpeg命令详解(转)》(https://www.cnblogs.com/AllenChou/p/7048528.html)

  • 《使用VMAF对视频质量进行分析》(https://roov.org/2020/08/vmaf/)

  • 《VMAF in FFmpeg – Installation and Usage Guide for Ubuntu》(https://ottverse.com/vmaf-ffmpeg-ubuntu-compilation-installation-usage-guide/)


文章转载自AggrxTech,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论