Sunday 24 March 2019

Video compression with ffmpeg - Constant quality


I am trying to compress videos of 10 seconds at different bitrates with ffmpeg. My aim is to obtain the same video at different qualities (from very low to very high). I don't want to touch audio part and I am using H264 as a video codec. I am using the following CLI:


ffmpeg -i input.mkv -c:v libx264 -b:v $j'k' -c:a copy output.mkv

Where $j vary from 150 to 4000.


My problem is that I get 10s videos compressed but the quality is not constant at all through the time. Here is an example: With a very low bitrate ($j = 150), at the beginning (between 0 and 3s), the video is really poor but at the end (between 8 and 10s), the quality is proper! Besides, while watching the video, one can see this increasing of quality through the time. Can someone explain me this phenomenon? How to get a constant quality?


Thanks'



Answer



As @LordNeckbeard already points out, constant bitrate is not the same as constant quality. In fact, it's quite the opposite. Certain parts of video sequences are easier to encode than others (easier in the sense of requiring less bits), and others are not. If you spend all your bits on the easy parts, you're going to lack them for the harder parts.


That's where constant quality comes into play. In x264 there is the Constant Rate Factor, which does exactly that. I suggest you read the linked article if you want more background info. Basically, the CRF ranges from 0 (lossless, best) to 51 (worst). Steps of ±6 roughly egal double or half the bitrate.


So, to adapt your script, simply do something like the following:


for i in $(seq 0 5 51); do 
ffmpeg -i input.mkv -c:v libx264 -crf $i -c:a copy output-$i.mkv
done

The scale itself is—unless I'm mistaken—close to logarithmic in terms of quality, so you can calculate your steps based on that instead of the seq call.





With a very low bitrate ($j = 150), at the beginning (between 0 and 3s), the video is really poor but at the end (between 8 and 10s), the quality is proper! Besides, while watching the video, one can see this increasing of quality through the time. Can someone explain me this phenomenon?



Doing constant bit rate is not an easy task for an encoder. You give it a certain value to work with, e.g. tell it "give me 150 kBit per second", but the encoder does not even know what it's going to encode at the next frame.


So, how much should it spend on this frame? How much on the next? Some frames—like I mentioned above—are easy to encode and just take a few kilobits, while others may take much more. But the encoder can really only look at what it's encoded in the past in order to scale for future pictures. Also take into account the different picture types.


Algorithmically, doing constant bitrate is really hard, and it's also the worst of the rate control modes x264 has to offer. Especially for short clips, since the encoder won't know what it can expect without doing a 2-pass encoding, you might notice this in the way you describe: the quality drastically changes throughout the ten seconds. But 150 kBit/s is really not enough for video of somewhat decent dimensions anyway.


No comments:

Post a Comment

How can I VLOOKUP in multiple Excel documents?

I am trying to VLOOKUP reference data with around 400 seperate Excel files. Is it possible to do this in a quick way rather than doing it m...