VP8 single pass conversion with good quality in ffmpeg

5,946

Solution 1

Although the perceived quality is subjective you can adjust the overall quality using the -quality variable for example -quality good. The bitrate will impact the quality which you have set to 0, which I assume was just a mistake.

Solution 2

The only way to get good quality results in a single pass is to use a constant rate factor (CRF) mode. Please read the VP8 and VP9 guides for more info.

When setting -crf X, each frame is encoded with that target quality level X. However, an additional constraint is applied in the encoder, depending on the bitrate set by -b:v:

  • If -b:v 0 is used, the bitrate can vary freely depending on the source sequence and the set target quality. This is the option you want for a “normal CRF mode”, equivalent to -crf X with x264.

  • If -b:v is set to a positive bitrate, that constraint will be used as a maximum bitrate.

    For example, with VP8, using -crf 10 and -b:v 500K for a 1080p video will most certainly always reduce the bitrate to 500 kBit/s rather than letting the quality vary freely, making the output look rather bad, since 1080p video requires much more than 500 kBit/s. Setting -crf 10 -b:v 5M would make more sense for VP8. For VP9, you generally want lower bitrate values, since it is more efficient.

  • If -b:v is not set at all, ffmpeg will choose a default of 200 kBit/s, which will very likely lead to bad quality (unless you have a low resolution, easy to encode sequence). So, don't do this when using -crf.

You can verify the encoder settings by looking at the output produced by ffmpeg when run with the -loglevel debug setting.

In your specific case, I don't see anything wrong with the options, except maybe -speed 2. Setting this will disable some encoder features at the expense of rate control accuracy. Remove the option and see if that improves your quality.

Note that the -quality option is misleading; it's a legacy option now called -deadline (see ffmpeg -h encoder=libvpx for more info). The only viable settings for -quality are good or best (and realtime, but this is for live streaming). good is the default, so you don't have to explicitly specify it. best will result in very long encoding times.

Share:
5,946
Radu
Author by

Radu

Updated on September 18, 2022

Comments

  • Radu
    Radu over 1 year

    I am working at a raw to timelapse program, and I am using ffmpeg to generate a video out of a sequence of JPGs that my program outputs.

    The user can select from different codecs, such as libx264, mjpeg, vp8, vp9.

    I am having good results with h264 and mjpeg, but vp8 gives me some very bad quality videos, even though I set the quality pretty high, and the file size is comparable to h264 videos.

    I am using the following settings:

    ffmpeg.exe -framerate 12 -i "./output/img_%05d.jpg" -dst_range 1 -color_range 2 -c:v libvpx -b:v 0 -threads 8 -speed 2 -crf 8 "./output/video.webm"
    

    You can see a sample video here: https://www.youtube.com/watch?v=eG2jxzR3Uxs (the encoding problems are mostly visible after 9 seconds).

    Someone at Stack Overflow said that VP8 needs two passes, but this is unpractical. Is it any way to get good results in a single pass? Something comparable to h264 in terms of size/quality?

    • Arete
      Arete over 6 years
      -b:v 0? Seems you have set the bitrate to 0 for some reason...
    • Radu
      Radu over 6 years
      That is needed to use -crf
    • Radu
      Radu over 6 years
      Hmm, it seems the v:b 0 was for VP9 encoding. I'll run some tests with set rates.
    • Arete
      Arete over 6 years
      You can also set quality with the -quality variable. Here is a great guide.
    • Radu
      Radu over 6 years
      Thank you, it seems that the b:v 0 was the problem. I assumed that, like vp9, it will automatically select whatever rate would match the best compression. Please post it as an answer, so I can mark it as solved.
    • Gyan
      Gyan over 6 years
      Someone at Stack Overflow, for context, is Ronald Bultje, who maintains the libvpx wrappers in ffmpeg.
    • glenneroo
      glenneroo almost 6 years
      @Radu Can you link the thread or edit your question to include it? I would be interested in the 2-pass answer but I'm having trouble finding it.
    • Radu
      Radu almost 6 years
  • Radu
    Radu over 6 years
    Thanks again. As a side note, is there any way to get an acceptable quality without specifying the bit rate?
  • Arete
    Arete over 6 years
    No problem. As far as I know you don't have to specify the bitrate at all. You can leave it out and let -quality do the job.
  • Gyan
    Gyan over 6 years
    -b:v 0 is the correct way for CRF encoding in VP8. VP8, by default, implements CRF as constrained quality i.e. it encodes a frame to maintain the specified quality and then compresses it further, if required, to keep it under the specified bitrate. When no bitrate is specified, vp8 inherits ffmpeg's default bitrate of 200 kbps. When some bitrate is specified, like 1M, VP8 will further compress the CRF encode to meet that target, if needed. If 0 is specified, it's "pure" CRF, like x264.
  • slhck
    slhck over 6 years
    -quality good is the default anyway; the only viable alternative here is -quality best, but then encoding will take forever.
  • Gyan
    Gyan over 6 years
    Weirdly, I get lower PSNR (-0.5) and SSIM with best relative to both good and realtime. Size, though, is ~60% of good.
  • Radu
    Radu over 6 years
    After doing a lot of tests, I get the best results like so: ffmpeg.exe -framerate 12 -i "./output/img_%05d.jpg" -dst_range 1 -color_range 2 -c:v libvpx -qmin 0 -qmax 32 -bufsize 100M -quality good -cpu-used 0 -minrate 50M -maxrate 50M -b:v 50M -threads 8 -speed 1 "./output/vide o.webm". I have to set those two values too, or else the quality is not good enough even with a 100M bitrate: -qmin 0 -qmax 32
  • Radu
    Radu over 6 years
    -b:v 0 is for vp9, it's not specified in the vp8 guides, and it doesn't work. Setting it to 100M works much better, but there are other things that need to be set too, such as -qmin 0 -qmax 32
  • Gyan
    Gyan over 6 years
    The fallback maximum bitrate is 1000M which is set when -b:v is set to 0.
  • slhck
    slhck over 6 years
    @Radu Just because it's not in the guides doesn't mean libvpx doesn't work the same with VP8 and VP9… at least in principle :) (I rewrote the FFmpeg VP8 and VP9 guides a while ago but never cared to update VP8 when I improved the VP9 one, since it's rather a legacy format.)
  • slhck
    slhck over 6 years
    @Radu Hm, that doesn't seem right, since setting -minrate, -b:v and -maxrate to the same value will essentially get you a constant bitrate encode, not a constant quality one (for constant quality you have to set CRF). Also, -cpu-used and -speed are the same option, so you're overwriting your own settings (choose either of those). The default is -qmax 63, so in essence you're limiting how efficient the encoder can be at compressing easy sources. But I have the feeling that your source in particular may screw up rate control. Have you tried this with other clips?
  • Radu
    Radu over 6 years
    Well, my program is for timelapse videos, so I am not interested in other usage scenarios. My goal was trying to get similar results as with h264 (similar visual quality, and similar file size). I wish it were possible to just set the constant quality value and not worry about anything else, as is the case for h264. Not setting min/max rates too will give me smaller file size, but the quality isn't that good.
  • Radu
    Radu over 6 years
    Well, I am not trying to disagree with you, but setting -v:b to 0 is what got me those really bad frames, and a file size comparable to h264.