Understanding what two-pass video encoding is, why use it and how to do two-pass video encoding with FFmpeg.
Two-pass compared to one-pass
Two-pass media encoding means on the first pass of encoding, information is gathered and used in the second pass to perform optimized encoding.
Using two-pass encoding gives you control over the output file size. You can calculate this as
bitrate = file size / duration.
One-pass encoding will do the encoding on the fly based on the parameters given to it.
Two-pass encoding will take longer as it goes over the video twice, look at two-pass encoding being the method to achieve a set file size and one-pass encoding to achieve a set quality.
How to do two-pass encoding with FFmpeg
Doing a simple two-pass encode with FFMpeg:
-b:v is the video bitrate.
-maxrate is maximum bitrate allowed (Optional).
-minrate is minimum bitrate allowed (Optional).
-bufsize is the video amount to enforce these rules for(Optional).
K = Kbit/s and
M = Mbit/s.
ffmpeg -y -i input.mkv -c:v libx264 -b:v 2M -maxrate 3M -bufsize 1M -pass 1 -f mp4 NUL ^ && ffmpeg -i input.mkv -c:v libx264 -b:v 2M -maxrate 3M -bufsize 1M -pass 2 output.mkv
Note If using Linux replace
The above command will do a two-pass encode for 2 Mbit/s with the max bitrate allowed being 3 Mbit/s. These rules are enforced for each 1 Mbit of video.
source.mkv is a 31 second, 371 Megabyte, 720p video file with a bitrate of 98.295 Mbit/s. This is an extremely high bitrate for a resolution of 1280x720p, it is downscaled from 4k, 120 Mbps H.265/HEVC drone footage.
To get this into a 20 Megabyte file the calculation is:
Megabytes / duration x 8 = Megabits
Multiplying by 8 turns Megabytes into Megabits.
20 / 31 = 0.645 x 8 = 5.16
Now this in the FFmpeg two-pass encode command is:
ffmpeg -y -i source.mkv -c:v libx264 -b:v 5.16M -maxrate 6M -bufsize 2M -pass 1 -f mp4 NUL ^ && ffmpeg -i source.mkv -c:v libx264 -b:v 5.16M -maxrate 6M -bufsize 2M -pass 2 output.mkv
For maxrate I rounded up to the next whole number just to give the encoding some legroom.
The video file size was 19.3 MB or 20,300,906 bytes. This is 351 Megabytes smaller than the source.
The output video as MP4:
For further documentation look here.