Netflix が使っているエンコードされる前と後の動画の品質評価に使われている VMAF(Video Multimethod Assessment Fusion)スコアを ffmpeg で調べる。以前の記事に異なる解像度でも調べられると書いていたが間違いである。同じ解像度でないと調べられない。対応フォーマットは yuv420p, yuv422p, yuv444p, yuv420p10le, yuv422p10le, yuv444p10le になる。外部ライブラリフィルタなので別途インストールが必要である。しかし現在のところ Windows 環境ではおそらくリンクできていない。–disable-w32threads または –enable-pthreads と、–enable-libvmaf を付けるとリンクできる。

Window 向けには以下のスクリプトでリンクできる。
jb-alvarado/media-autobuild_suite: This Windows Batchscript is for setup a compiler environment for building ffmpeg and other media tools under Windows.

しかし上のスクリプトで libvmaf フィルタを使うとメモリリーク(メモリを大量に消費)することが報告されていたが2018年4月1日に直った。
#6967 (Memory leak in Win64 ffmpeg with vmaf) – FFmpeg
vf_libvmaf: Fix memory leak : git.videolan.org Git – ffmpeg.git/commitdiff

2つの映像の画質評価をする ssim
新しい映像の動きの評価 vmafmotion

VMAF の解説記事

基本コマンド

従来の画質評価をする ssim, psnr フィルタと違って、入力するファイルの順番が異なるのに注意。VMAF スコアを調べるのが最初に入力する動画でなければならない。
ffmpeg -i 調べたい動画 -i オリジナル -filter_complex libvmaf -an -f null -

最終的な品質評価になる VMAF スコアは 100 が最高画質。配信向けには 80 程度を目標とするビットレートになるようにする。ログファイルに書いてある adm2, vif_scalex スコアは VMAF スコアの元となり 0(最低画質)から 1(最高画質)。motion2 は 0(動かない映像)から 20(ものすごく動く映像)。

解像度が同じでオプションを明記する場合
ffmpeg -i encoded.mp4 -i original.mp4 -filter_complex "libvmaf=model_path=vmaf_v0.6.1.pkl:log_path=log.xml:log_fmt=xml:enable_transform=0:phone_model=0:psnr=0:ssim=0:ms_ssim=0:pool=mean" -an -f null -
ffmpeg -i encoded.mp4 -i original.mp4 -filter_complex "libvmaf=vmaf_v0.6.1.pkl:log.xml:xml:0:0:0:0:0:mean" -an -f null -

YUV の動画を比較する場合。動画は .mp4 などの圧縮した形式と、展開した .yuv の形式とでは処理速度に大きな変化は見られなかった。
ffmpeg -video_size 1280x720 -pixel_format yuv420p -framerate 30 -i encoded.yuv -video_size 1280x720 -pixel_format yuv420p -framerate 30 -i original.yuv -filter_complex libvmaf -an -f null -

エンコードが終わるとコンソールの最後に以下のような結果が表示される。ログファイルで出力する場合はフレーム毎に指定オプション内容が出力される。Exec FPS は処理速度。

Exec FPS: 4.940972
VMAF score = 96.147066

解像度が異なる場合

解像度が異なる場合に VMAF スコアを調べるには、調べたい動画をフィルタでオリジナルの解像度にリサイズしてから調べればよい。

リサイズする前が 1920 x 1080、リサイズした後が 1280 x 720 で、リサイズ方法が scale フィルタの場合。
ffmpeg -i original.mp4 -filter_complex scale=1280:720:flags=spline -acodec copy resized-720p.mp4
ffmpeg -i resized-720p.mp4 -i original.mp4 -filter_complex "scale=1920:1080:flags=lanczos,libvmaf" -an -f null -

リサイズアルゴリズムの注意点

-s でのリサイズと、-vfscale フィルタを使い flags を指定しない場合は bicubic が使われるが、-filter_complexscale フィルタを使い flags を指定しない場合は bilinear が使われて、-vf, filter_complex で使われるアルゴリズムが異なるのに注意する。

Windows の ffmpeg で生放送する方法 : scale
Zライブラリを使ったリサイズフィルタ zscale

公式ドキュメント:FFmpeg Filters Documentation : libvmaf

オプション

調べる内容を増やすほど処理速度が遅くなる。

  • model_path[string]
    SVM(Support Vector Machines) で使われるモデルのパス指定。vmaf_v0.6.1.pkl と vmaf_v0.6.1.pkl.model を同じ場所に置いておく
    既定値:”vmaf_v0.6.1.pkl”(インストールされているパス)
  • log_path[string]
    出力されるログファイルのパス指定
    既定値:無指定(指定するとログファイルが出力される)
  • log_fmt[string]
    ログファイルのフォーマット指定。xml, json が指定できる
    既定値:xml
  • enable_transform[boolean]
    VMAF スコアの計算で transform を有効にする
    同一ファイルの VMAF スコアが 100 になる。有効にしないと 100 にならない
    既定値:0
  • phone_model[boolean]
    電話モデルを呼び出してノートPCやTVに適した通常より高い VMAFスコアを計算する。携帯電話などのモバイル端末は画面サイズが大きくなく視聴距離が近いためにビットレートを高くしてもそれほど高画質に見えないからである。詳細は ここを参照
    既定値:0(ノートPC、TV向け)
  • psnr[boolean]
    psnr も一緒にを計算する。60 が最高画質
    既定値:0
  • ssim[boolean]
    ssim も一緒にを計算する。1 が最高画質
    既定値:0
  • ms_ssim[boolean]
    ms_ssim も一緒にを計算する。1 が最高画質
    既定値:0
  • pool[string]
    VMAFスコアの計算方法。mean, min, harmonic_mean(調和平均) が指定できる
    既定値:”mean”

enable_transform の挙動について

ffmpeg -f lavfi -i color=s=32x32:d=1 -filter_complex split,libvmaf=enable_transform=0 -an -f null -
Exec FPS: 694.752857
VMAF score = 97.428043
ffmpeg -f lavfi -i color=s=32x32:d=1 -filter_complex split,libvmaf=enable_transform=1 -an -f null -
Exec FPS: 574.159669
VMAF score = 100.000000

2ファイル入力するフィルタの挙動設定 framesync にも対応している。

追記
コメントで指摘のあった部分を追記修正した。2018年3月13日

6 thoughts on “新しい映像の品質評価 libvmaf

    • admin

      コメント確認しました。スレッドも確認しましたが HEVC の100倍遅いと言われている AV1 ですがそれどころじゃないくらい遅くて今のところ全く実用的ではないですね。

       AV1(libaom-av1)で1920×1080の10フレームだけをエンコードしてみた結果。http://mevius.5ch.net/test/read.cgi/avi/1515759816/378

       他のエンコーダとの速度比較などhttp://mevius.5ch.net/test/read.cgi/avi/1515759816/392

      • Tac

        AV1はまだ最適化もされてませんから遅すぎてテストもままならないですね・・・。
        なおZeranoe版ffmpegではlibaomのビルドミスがあり、
        ffmpeg-20180404-53688b6までは本来よりも更に遅い結果(最大で5.7倍くらい)となります。
        そのため検証するならそれ以降のビルド(このコメントを書いている時点ではまだ未リリース)を使う必要があります。
         https://ffmpeg.zeranoe.com/forum/viewtopic.php?f=5&t=5601#p13513

  • Tac

    メモリリークの情報と更新ありがとうございます。
    メモリリークの件は調べていませんでした。

    ●修正後の記事のリサイズの部分ですが、
      ・「リサイズする場合」というタイトルは「解像度が異なる場合」が良いかも。
      ・VMAF計測時のリサイズアルゴリズムは特に縮小時と同じにする必要はなく
       好きなもの(視聴時に期待できるもの)を選択すればよい。
       (高性能なアルゴリズムにすればスコアも上がる)
      ・エンコードする前の動画(オリジナル)をリサイズするのではなく、
       エンコード後の動画をオリジナルサイズにあわせてリサイズする。
      ・VMAF計測時のコマンドでscaleの引数が1280:720になっているが1920:1080のはず。
       (このままだと解像度違いでエラーになる)
     ということで、以下のような感じが良いかもしれません。
     (splineとlanczosにしているのはなんとなくです)

    ——————————————————————–
    解像度が異なる場合

    解像度が異なる場合に VMAF スコアを調べるには、調べたい動画をフィルタでオリジナルの解像度にリサイズしてから調べればよい。

    オリジナルが 1920 x 1080、エンコード後が 1280 x 720 の場合。

    ffmpeg -i original-1080p.mp4 -filter_complex scale=1280:720:flags=spline -acodec copy resized-720p.mp4

    ffmpeg -i resized-720p.mp4 -i original-1080p.mp4 -filter_complex “scale=1920:1080:flags=lanczos,libvmaf” -an -f null –
    ——————————————————————–

    ●SSIMとは違って [encoded][original] と [original][encoded] の結果が異なるので、
     「順序は必ず “-i 調べたい動画 -i オリジナル” にする必要がある」という注意書きもあると良いかなと思いました。

  • Tac

    色々と参考にさせていただいております。ありがとうございます。
    最近libvmafを試していたので、いくつかコメントします。
    間違いなどあったらすみません。

    ●以下の自動ビルドスクリプトでlibvmafを有効にしたWindows用のffmpegバイナリがビルドできました。
      https://github.com/jb-alvarado/media-autobuild_suite
     VMAFが使いたかっただけなので、”Choose ffmpeg and mpv optional libs: “で
     1(Yes)を選び、ffmpeg_options.txtで–enable-avisynthと–enable-libvmafだけ残し、
     他はdisableにしたり消したりして最低限にしたのですが、
     mpv_options.txtの方も不要なものはここでちゃんと無効にしておかないと、
     mpvのビルドをNoにした場合でもmpv用ライブラリをビルドしにいってしまい
     無駄に時間がかかってしまうので注意。
     ビルドしたのは3/5で、各コミットは以下のとおりです。
      media-autobuild_suite r2654 5f3980c4def9d3a818b94b5cc4eb514ad078f0cb
      ffmpeg 69995a94d8409a704361dce9bc16ede7f88bdf1a
      vmaf r683 7426b6fb090b5754bad0c6c428d7dbc2303d980c

    ●libvmafは現状ではpthread依存のようで、ffmpegに–disable-w32threadsが必要なようですが、
     Zeranoe氏はpthreadだと遅くなるということで避けたいらしく、
     当面はlibvmafはZeranoe版バイナリには入らない模様です。
      https://ffmpeg.zeranoe.com/forum/viewtopic.php?p=13039#p13039

    ●i7-4702MQで1080p/2157framesのSSIMやVMAFを計算させると
     -lavfi ssimなら150fps出るのに、-lavfi libvmafは2.8fpsしか出ませんでした。
     また、ssimでは実行中のメモリ使用量も200MB以下なのですが、
     libvmafでは最大6GBくらいになってかなり重くなりました・・・。
     バグなのか仕様なのかビルドの問題なのか不明ですが
     もうちょっと軽く動くようになると嬉しいですね。

    ●VMAFは基本的にオリジナルソース(=reference)を固定した上で、それを元にして
     リサイズやエンコードした複数の配信用ファイル(=distorted,main)のVMAFスコアを測り、
      「同じビットレートならどれが一番VMAFスコアが高いか」
     を調べて、最適な配信用ファイルを決めるといった形で使うものだと思います。

    ●したがって、リサイズしたもののVMAFスコアを測る場合は、
     リサイズしたものをオリジナル解像度に戻した上で
     VMAFスコアを測るのが一般的ではないかと思います。
     コマンド的には
      ffmpeg -i resized720p_x265_2000kbps.mp4 -i original1080p.mp4 -filter_complex scale=1920:1080:flags=print_info+lanczos,libvmaf=model_path=model/vmaf_v0.6.1.pkl -an -f null –
     といった形の方が順序的にも意味的にもわかりやすいのではないかと思います。

    ●YUVの動画比較のところでoriginal.yuvとreference.yuvという
     表現(どちらもオリジナルを指す)が混在してしまっているので、
      original.yuv → encoded.yuv
      reference.yuv → original.yuv
     といった表現に変えるとわかりやすくなると思います。
     (referenceって一般的にはあまりなじみが無い表現かなーと)

    ●enable_transformは、「transformを計算する」というより
      「VMAFスコアの計算でtransformを有効にする」
     という説明の方がよいかと思います。
     (どういう処理なのかは自分もよくわかってないですが
      同一ファイルのVMAFスコアが100.0になったりするようです。)

    ●poolの harmonic mean の指定は harmonic_mean のようです。

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)