Short version: Why did my total file size increase when I switched from constant quality to constrained quality at the same crf? Shouldn't this just set a maximum bitrate and thus only either do nothing or lower file size, depending on whether the maximum is hit?
Long version: I'm trying to maximise (subjective) overall quality in a library of video files given a fixed total file size limit for the entire library.
I started off with constant quality, and adjusting the crf until I hit my limit. But I found a subset of scenes (usually simple but with a single moving object) looked particularly low quality/smeary. After watching the bitrate meter during encoding I concluded too much of the budget was spent in complex high-action scenes (where subjectively I think the extra quality is somewhat wasted), leaving not enough for "simpler" scenes, so, short of a more direct method to apply an adjustable bias towards simpler scenes (I don't want to just switch straight to constant quantization or constant bitrate or anything, I'm trying to find an optimal middle ground), I decided to try constrained quality, as described here: https://trac.ffmpeg.org/wiki/Encode/VP9, where I intended to slowly lower the maximum until I couldn't justify lower quality complex scenes, then use the freed space to boost the crf to the benefit of the simple scenes.
This seems to have sort of worked, but the behaviour I'm seeing is surprising, and I don't understand it.
I expected that setting a maximum bitrate with -b:v 1M
(I'd seen quite a few complex scenes were exceeding that bitrate, pushing to around 1.5M) would reduce the total size of the entire library of video files (at the cost of reducing quality in complex scenes).
Instead, I found the total file size had increased after I applied this, meaning constrained quality mode does not behave the way I expected.
Theories:
- My original expectation was that constrained quality meant "match constant quality but any scenes that exceed the maximum bitrate will use VBR/target bitrate rules to control their bitrate instead".
- Now I wonder if perhaps another possibility is that the constraint only applies globally for the entire video, and once the constant quality goal tries to cross the bitrate constraint (momentarily?, or on average over a video?), the entire video stops trying to match constant quality, and instead follows the VBR rules, which forces the "simple" scenes to suddenly use vastly more bitrate than they needed in constant quality mode. That seems insane and pointless to me, constrained quality makes no claim about boosting the quality beyond that requested, so why waste bits giving higher quality that wasn't asked for?
Some videos use significantly less in constrained quality mode, as expected, and some videos use significantly more, which I didn't expect at all. On the other hand, without me having to change the crf at all, the "simple" scenes I originally wanted to boost the quality for have actually increased in quality, exactly as I originally wanted, I just don't know why it behaves this way!
I'm seeing a subset of longer videos reduce in size by 7% or so (276MB -> 257MB total for 17 files), but I'm seeing a subset of shorter videos increase in size by 40% or so (95MB -> 133MB total for 220 files).
Commands used look something like
Constant Quality:
ffmpeg -y -i in_file.mov -c:v libvpx-vp9 -crf 32 -b:v 0 -pass 1 -passlogfile in_file.webm.log -an -f null /dev/null && ffmpeg -i in_file.webm -c:v libvpx-vp9 -crf 32 -b:v 0 -pass 2 -passlogfile in_file.webm.log -an out_file.webm
Constrained Quality:
ffmpeg -y -i in_file.mov -c:v libvpx-vp9 -crf 32 -b:v 1M -pass 1 -passlogfile in_file.webm.log -an -f null /dev/null && ffmpeg -i in_file.webm -c:v libvpx-vp9 -crf 32 -b:v 1M -pass 2 -passlogfile in_file.webm.log -an out_file.webm
(so identical beyond the -b:v value)