How can I reduce a video's size with ffmpeg?
This answer was written in 2009. Since 2013 a video format much better than H.264 is widely available, namely H.265 (better in that it compresses more for the same quality, or gives higher quality for the same size). To use it, replace the libx264 codec with libx265, and push the compression lever further by increasing the CRF value — add, say, 4 or 6, since a reasonable range for H.265 may be 24 to 30. Note that lower CRF values correspond to higher bitrates, and hence produce higher quality videos.
ffmpeg -i input.mp4 -vcodec libx265 -crf 28 output.mp4
To see this technique applied using the older H.264 format, see this answer, quoted below for convenience:
Calculate the bitrate you need by dividing your target size (in bits) by the video length (in seconds). For example for a target size of 1 GB (one gigabyte, which is 8 gigabits) and 10 000 seconds of video (2 h 46 min 40 s), use a bitrate of 800 000 bit/s (800 kbit/s):
ffmpeg -i input.mp4 -b 800k output.mp4
Additional options that might be worth considering is setting the Constant Rate Factor, which lowers the average bit rate, but retains better quality. Vary the CRF between around 18 and 24 — the lower, the higher the bitrate.
ffmpeg -i input.mp4 -vcodec libx264 -crf 20 output.mp4
You mentioned wanting to reduce filesize to fit more videos on a mobile device, which is my usecase as well. All the answers here are for reducing the compression quality but nobody has mentioned reducing video frame size. It's a lot quicker, from about 3 to 5 times quicker than recompressing in my experience. See the ffmpeg docs on scaling for more info.
ffmpeg -i input.mkv -vf "scale=iw/2:ih/2" half_the_frame_size.mkv
ffmpeg -i input.mkv -vf "scale=iw/3:ih/3" a_third_the_frame_size.mkv
ffmpeg -i input.mkv -vf "scale=iw/4:ih/4" a_fourth_the_frame_size.mkv
I tested most of the other proposed answers to this question. The test data conclusions are below. These are the proposed answers that I tested:
(BR) Modify the bitrate, using:
ffmpeg -i $infile -b $bitrate $newoutfile
(CR) Vary the Constant Rate Factor, using:
ffmpeg -i $infile -vcodec libx264 -crf 23 $outfile
(SZ) Change the video screen-size (for example to half its pixel size), using:
ffmpeg -i $infile -vf "scale=iw/2:ih/2" $outfile
(BL) Change the H.264 profile to "baseline", using:
ffmpeg -i $infile -profile:v baseline $outfile
(DF) Use the default ffmpeg processing, using:
ffmpeg -i $infile $outfile
DATA
- "size" - percent pixel size of the converted video in relation to the original.
- "bitrate" - bitrates of original and converted videos.
- "definition" - pixel size of videos.
- "convert" - time to convert the video in seconds.
I calculated the target bitrate for (BL)using the proposed method.
=== File A - How Node Is Helping To Propel Angular-Fnbixa7Ts6M.mkv ===
original BR CR SZ BL DF
-------- --- -- -- -- --
size 64152 kb 214% 76% 40% 83% 76%
bitrate 411 kb/s 883 313 165 342 313
definition 1920x1080 1920x1080 1920x1080 960x540 1920x1080 1920x1080
convert -- 648 509 225 427 510
=== File B - Using GraphQL with Angular _ By - Lee Costello-OGyFxqt5INw.mkv ===
original BR CR SZ BL DF
-------- --- -- -- -- --
size 410301 kb 33% 109% 28% 143% 109%
bitrate 2687 kb/s 880 2920 764 3843 2920
definition 3840x2160 3840x2160 3840x2160 1920x1080 3840x2160 3840x2160
convert -- 2307 3188 1116 2646 3278
CONCLUSIONS
The (SZ) method is definitely the quickest method. It was 2X to 4X faster. This can be very much an issue on high-def videos, since all of the other methods took longer to convert than the actual length of the video! For example, The (CR) method took 53 minutes to convert the 21 minute video.
The (SZ) method is definitely the best method if the definition of the video is larger than the definition of the screen that will be displaying it. For example, if your phone can only display a 1080p picture, sending it a 3840x2160 video is just wasteful. It would be best to half its size to 1080p.
Some of the proposed answers actually INCREASED the size of some videos. For example, the (BR) method more than doubled the size of the 1080p sample. It did however make the 2160p size one-third. For the high-def sample, the (CR), (BL) and (DF) methods all INCREASED the size of the video.
Correct (or best) Answer
It is always best to first lower the resolution to the maximum supported by your target display.
If you want to reduce file size further, it will depend on personal choices. You can either reduce information content or increase compression.
You can lower the resolution more if that is not something that concerns you.
If the video doesn't include fast action scenes, you may want to lower the frame rate.
If you have a powerful processor and space is the only issue, you can increase the compression rate.
Bit rate is a combination of multiple factors. So just telling ffmpeg to lower the bit rate may not give you the results you want.
Another way of lower information content is to lower the color depth. How to do this was not yet discussed.