VMAFで画質比較、パラメータ検討

h264_vaapiでハードウェアエンコードしてたんだが、素材に寄ってはブロックノイズが気になることがあり、もう一度、コーデックも含め、パラメータを検討してみることにした。目視では時間がかかるうえ、客観性も劣る。そこで、VMAFという指標を用いて比較することにした。

VMAFはffmpegのフィルタとして実装されており、エンコ前後の動画を食わせると100点満点で値を返してくる。手元のffmpegコンパイルし直すのが面倒だったので、ニコニコで配ってるバイナリを引っ張ってきて使用した。

比較するコーデックはh264, h264_vaapi, hevc、それぞれ固定画質モードでエンコードし、ファクタは17から33までひとつおきとした。素材は4種類。洋ドラ、演芸、動物物、アニメ。こんな感じ。

ffmpeg -loglevel 32 -hide_banner -analyzeduration 30M -probesize 30M -i CUT.ts -map 0:0 -map 0:1 -vcodec $CODEC -flags +ildct+ilme -crf $CRF -acodec copy -f mpegts -mpegts_m2ts_mode 1 -vsync 0 $OUTFILE

  • vaapiは無いな、と。わざわざエンコードする意味がない。HWエンコはやはり配信用だ。
  • hevcとh264、いい勝負なんだが、素材によって得手不得手が有るようだ。
  • アニメはh264がいい仕事している。
  • 動きの少ない演芸番組、洋ドラ、低ビットレートではhevcが勝る。
  • VMAF90点を目標とするなら、hevcでもh264でもqp=27としてエンコードするのがバランスが良いだろう。
  • エンコード時間を考えると、h264だな。
  • 改めてh264の優秀さに脱帽。
#!/usr/bin/R

vmaf <- NULL
vmaf <- data.frame (
  sample=c("endeavour", "endeavour", "endeavour", "endeavour", "endeavour",
           "endeavour", "endeavour", "endeavour", "endeavour",
           "endeavour", "endeavour", "endeavour", "endeavour", "endeavour",
           "endeavour", "endeavour", "endeavour", "endeavour",
           "endeavour", "endeavour", "endeavour", "endeavour", "endeavour",
           "endeavour", "endeavour", "endeavour", "endeavour",

           "engei", "engei", "engei", "engei", "engei",
           "engei", "engei", "engei", "engei",
           "engei", "engei", "engei", "engei", "engei",
           "engei", "engei", "engei", "engei",
           "engei", "engei", "engei", "engei", "engei",
           "engei", "engei", "engei", "engei",

           "neko", "neko", "neko", "neko", "neko", 
           "neko", "neko", "neko", "neko", 
           "neko", "neko", "neko", "neko", "neko", 
           "neko", "neko", "neko", "neko", 
           "neko", "neko", "neko", "neko", "neko", 
           "neko", "neko", "neko", "neko", 

           "baka", "baka", "baka", "baka", "baka", 
           "baka", "baka", "baka", "baka", 
           "baka", "baka", "baka", "baka", "baka", 
           "baka", "baka", "baka", "baka", 
           "baka", "baka", "baka", "baka", "baka", 
           "baka", "baka", "baka", "baka"), 

  codec=c("h264", "h264", "h264", "h264", "h264",
          "h264", "h264", "h264", "h264",
          "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi",
          "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi",
          "hevc", "hevc", "hevc", "hevc", "hevc",
          "hevc", "hevc", "hevc", "hevc",

          "h264", "h264", "h264", "h264", "h264",
          "h264", "h264", "h264", "h264",
          "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi",
          "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi",
          "hevc", "hevc", "hevc", "hevc", "hevc",
          "hevc", "hevc", "hevc", "hevc",

          "h264", "h264", "h264", "h264", "h264",
          "h264", "h264", "h264", "h264",
          "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi",
          "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi",
          "hevc", "hevc", "hevc", "hevc", "hevc",
          "hevc", "hevc", "hevc", "hevc",

          "h264", "h264", "h264", "h264", "h264",
          "h264", "h264", "h264", "h264",
          "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi",
          "h264_vaapi", "h264_vaapi", "h264_vaapi", "h264_vaapi",
          "hevc", "hevc", "hevc", "hevc", "hevc",
          "hevc", "hevc", "hevc", "hevc"),

  q=c(17, 19, 21, 23, 25, 27, 29, 31, 33,
      17, 19, 21, 23, 25, 27, 29, 31, 33,
      17, 19, 21, 23, 25, 27, 29, 31, 33,

      17, 19, 21, 23, 25, 27, 29, 31, 33,
      17, 19, 21, 23, 25, 27, 29, 31, 33,
      17, 19, 21, 23, 25, 27, 29, 31, 33,

      17, 19, 21, 23, 25, 27, 29, 31, 33,
      17, 19, 21, 23, 25, 27, 29, 31, 33,
      17, 19, 21, 23, 25, 27, 29, 31, 33,

      17, 19, 21, 23, 25, 27, 29, 31, 33,
      17, 19, 21, 23, 25, 27, 29, 31, 33,
      17, 19, 21, 23, 25, 27, 29, 31, 33),

  size=c(40233408, 28410816, 19067712, 13342848, 10179840,
         7934592, 6602880, 5611200, 4888128,
         58493376, 42685632, 34079040, 20838912, 17428800,
         12104064, 9887808, 8582208, 7333440,
         30403584, 19525248, 13114752, 9402624, 7192128,
         5808192, 4856448, 4212480, 3741504,

         151035264, 114034176, 82104768, 56709504, 39038208,
         26509056, 18812928, 13984704, 10893888,
         180936576, 129821568, 96960768, 60131904, 45524544,
         31225920, 22638912, 18226368, 14008320,
         84664320, 57035904, 37372224, 24697152, 16933632,
         12134592, 9122304, 7165824, 5833920,

         154437312, 122170176, 92806464, 67483776, 48272256,
         33981696, 25192320, 19374720, 15513600,
         195580608, 144600000, 111267264, 72640704, 56917248,
         40729728, 30924096, 25297920, 19798848,
         96467904, 71329152, 50634048, 34667328, 23605248,
         16603968, 12332160, 9608064, 7767552, 

         49433856, 38120256, 28001280, 20700864, 15813888,
         12406848, 10219392, 8692032, 7590144,
         89130048, 71908608, 61507008, 44960064, 39323328,
         30558528, 25833216, 23206080, 20117568,
         34869312, 26099328, 20038272, 15844416, 12858240,
         10714560, 9045696, 7749888, 6715392), 

  vmaf=c(97.414223, 97.033137, 96.482038, 95.757239, 94.927476,
         93.827896, 92.298622, 90.533203, 88.224027,
         97.030416, 96.358609, 95.820635, 94.789654, 93.996665,
         92.554915, 90.360646, 88.345397, 85.164701,
         96.219444, 95.691093, 95.029160, 94.137422, 92.967064,
         91.447516, 89.471573, 87.011807, 83.784730,

         98.938432, 98.642856, 98.124073, 97.340494, 96.344059,
         94.954042, 93.197262, 91.164133, 88.550417,
         98.414272, 97.745381, 97.169063, 95.961049, 94.971345,
         93.369077, 91.096610, 88.941571, 85.402841,
         96.982160, 96.112228, 95.127002, 94.008808, 92.675871,
         90.938491, 88.704656, 85.810726, 82.135652,

         98.956203, 98.674420, 98.200277, 97.477086, 96.427196,
         94.767823, 92.285201, 89.003958, 84.911819,
         98.546474, 97.897274, 97.294441, 95.725487, 94.356864,
         91.833858, 88.033021, 84.286361, 78.460347,
         97.610464, 96.862611, 95.852296, 94.467861, 92.648679,
         90.275109, 87.202078, 83.337630, 78.449135,

         97.403659, 97.187608, 96.859229, 96.446676, 96.002653,
         95.345043, 94.579849, 93.621566, 92.440076,
         97.229073, 96.942756, 96.600447, 96.138650, 95.621452,
         94.792517, 93.501437, 92.044247, 89.634072,
         96.659194, 96.318148, 95.893010, 95.349360, 94.573302,
         93.521138, 92.015785, 90.099163, 87.699080)
)
vmaf <- data.frame (vmaf, bitrate=vmaf$size / 1000 / 60 * 8)

png ("vmaf.png", width=960, height=540)

xr=c(500, 30000)
lt="x"

# 
  x <- subset (vmaf, sample=="endeavour"); cc=hsv (0, 1, 1);

  plot (x[which(x$codec=="h264"),]$bitrate, x[which(x$codec=="h264"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    xlab="Bitrate (kb/s)", ylab="VMAF Score", type="b", col=cc, pch=0)

  par(new=T)

  plot (x[which(x$codec=="h264_vaapi"),]$bitrate,
    x[which(x$codec=="h264_vaapi"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=1)

  par(new=T)

  plot (x[which(x$codec=="hevc"),]$bitrate, x[which(x$codec=="hevc"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=2)

  par(new=T)

#
  x <- subset (vmaf, sample=="engei"); cc=hsv (0.25, 1, 1)
 
  plot (x[which(x$codec=="h264"),]$bitrate, x[which(x$codec=="h264"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=0)

  par(new=T)

  plot (x[which(x$codec=="h264_vaapi"),]$bitrate,
    x[which(x$codec=="h264_vaapi"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=1)

  par(new=T)

  plot (x[which(x$codec=="hevc"),]$bitrate, x[which(x$codec=="hevc"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=2)

  par(new=T)

#
  x <- subset (vmaf, sample=="neko"); cc=hsv (0.5, 1, 1)

  plot (x[which(x$codec=="h264"),]$bitrate, x[which(x$codec=="h264"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=0)

  par(new=T)

  plot (x[which(x$codec=="h264_vaapi"),]$bitrate,
    x[which(x$codec=="h264_vaapi"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=1)

  par(new=T)

  plot (x[which(x$codec=="hevc"),]$bitrate, x[which(x$codec=="hevc"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=2)

  xx <- subset (x, codec=="h264_vaapi")
  text (xx$bitrate, xx$vmaf, xx$q, pos=4, col=cc, cex=0.75)
  # text (x[9,]$bitrate, x[9,]$vmaf, x[9,]$codec, pos=4, col=cc)
  par(new=T)

#
  x <- subset (vmaf, sample=="baka"); cc=hsv (0.75, 1, 1)

  plot (x[which(x$codec=="h264"),]$bitrate, x[which(x$codec=="h264"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=0)

  par(new=T)

  plot (x[which(x$codec=="h264_vaapi"),]$bitrate,
    x[which(x$codec=="h264_vaapi"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=1)

  par(new=T)

  plot (x[which(x$codec=="hevc"),]$bitrate, x[which(x$codec=="hevc"),]$vmaf,
    log=lt, xlim=xr, ylim=c(70, 100),
    axes=F, xlab="", ylab="", type="b", col=cc, pch=2)

  legend (10000, 90, c("h264", "h264_vaapi", "hevc"), pch=0:3)
  legend (10000, 84, c("endeavour", "engei", "neko", "baka"), col=c(hsv(c(0, 0.25, 0.5, 0.75), 1, 1)), lty=1)
  title ("VMAF Comparison")

dev.off()
#