VP8 single pass conversion with good quality in ffmpeg
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
withx264
.-
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.
Radu
Updated on September 18, 2022Comments
-
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 over 6 years
-b:v 0
? Seems you have set the bitrate to 0 for some reason... -
Radu over 6 yearsThat is needed to use -crf
-
Radu over 6 yearsHmm, it seems the v:b 0 was for VP9 encoding. I'll run some tests with set rates.
-
Arete over 6 yearsYou can also set quality with the
-quality
variable. Here is a great guide. -
Radu over 6 yearsThank 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 over 6 yearsSomeone at Stack Overflow, for context, is Ronald Bultje, who maintains the libvpx wrappers in ffmpeg.
-
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 almost 6 yearsHi, it was this thread: stackoverflow.com/questions/47965327/…
-
-
Radu over 6 yearsThanks again. As a side note, is there any way to get an acceptable quality without specifying the bit rate?
-
Arete over 6 yearsNo 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 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 over 6 years
-quality good
is the default anyway; the only viable alternative here is-quality best
, but then encoding will take forever. -
Gyan over 6 yearsWeirdly, I get lower PSNR (-0.5) and SSIM with
best
relative to bothgood
andrealtime
. Size, though, is ~60% of good. -
Radu over 6 yearsAfter 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 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 over 6 yearsThe fallback maximum bitrate is
1000M
which is set when-b:v
is set to0
. -
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 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 over 6 yearsWell, 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 over 6 yearsWell, 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.