Lossless video - where a video has been transferred directly from a camera or generated by motion graphics software is typically very large. It is possible for the file size of uncompressed video to take up gigabytes of disk space for each minute of video. This is useful for high end cinematic or broadcast video production but is less useful for most every day video tasks, especially where the video is used online.
There are several reasons why you might need to compress videos, including:
While it is simple to compress and resize videos using the Shotstack Ingest API, you might want to use a desktop tool and compress videos locally. In this post, we will learn how to use FFmpeg to compress video file sizes using different approaches. FFmpeg is an open-source command line tool that can be used to compress videos by adjusting codecs, resolution, bitrates and frame rate.
To follow along with this tutorial, download and install the latest version of FFmpeg for your operating system from the FFmpeg official downloads page. The tutorial also assumes you have some working knowledge of how to run commands in a terminal.
You will also want a large, high resolution test video with low compression. For this tutorial we are going to use a 1080p MOV sample file. Right click and save this file to your hard-drive and save or rename it to input.mov.
The sample video is 28 seconds long, 269MB in size and has a resolution of 1920x1080 pixels, frame rate of 23.976 and a bitrate of 78,270 kb/s. It is compressed using Apple ProRes 422 LT codec, which is similar to how a video might be recorded on a modern iPhone, DJI drone or high end video camera. The audio codec is PCM (pcm_s161e), which is a lossless audio compression algorithm.
Here is a preview of the video:
Given the short duration of the video and the large file size, it would be highly desirable to compress the video to a smaller size while maintaining a high visual quality.
The first step to compress the video is to use a different video compression codec. A codec is simply an algorithm used to encode and compress video to a smaller file size without losing visual quality. One of the most popular and widely supported video formats is MP4. This is largely thanks to its video compression options made available using the H.264 codec - a highly efficient, open-source compression algorithm, that can create very small file sizes with minimal loss of visual quality.
To convert the MOV file to MP4 and compress it using the H.264 codec run the following command from the folder you saved the input.mov sample file:
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p output.mp4
Here's a breakdown of the command:
If you compare the file size of the input.mov file to the new output.mp4 file you will see a reduction in file size of 220MB, the compressed MP4 file is 49MB.
It is worth noting you could use other codecs and file formats (containers) to compress the video. For example, you could use the H.265 codec as an MP4 file, or you could use the VP9 codec as a WebM file.
ffmpeg -i input.mov -c:v libx265 -pix_fmt yuv420p output.mp4
ffmpeg -i input.mov -c:v libvpx-vp9 -pix_fmt yuv420p output.webm
If you run either of these commands you might run in to a couple of problems. The H265 codec results in a much smaller file size, but when I tried to open the file using Windows built in media player I have to pay for and install a new codec - this will put a lot of people off. When encoding using VP9 codec, it is very slow and the final file is larger than a using H264/MP4 file. It is for these reasons that H264/MP4 files are still the most popular format.
One way to compress the video further is using a constant rate factor (CRF). This is the simplest way to control the compression without controlling individual settings. You can provide a value between 0-51. Lower values generate higher quality but larger files, and higher values create lower visual quality but smaller files. Sensible values are between 17 and 28 for MP4 files but you can experiment with different values to find the sweet spot that balances quality and file size. The default value is 23.
The command looks like this, with the -crf 28
option added:
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -crf 28 output.mp4
The new file size is now 22.6MB, however you might notice a slight reduction in visual quality and less vibrant colours.
There are many other command-line options that we can use to configure how FFmpeg performs the compression. Consider this command:
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -crf 28 -preset fast -tune zerolatency -c:a aac output.mp4
Let's explore the additional parameters:
-preset
option sets the compression efficiency, which in turn impacts the encoding speed. Available options include ultrafast
, fast
, medium
, slow
, and placebo
. Choose a preset depending on your priorities. For example, if you want faster encoding, you can go with fast
or ultrafast
. Conversely, if you are looking for superior quality, and don't mind longer encoding times, you can choose slower
or slow
.-tune
option can be used to configure settings based on the type of input video. For example, use zerolatency
to optimize encoding for reduced latency. Other available options include: film
, animation
, stillimage
, and fastdecode
.The file size of the output.mp4 file is now only 18.6MB, a reduction of 93%.
For more details on how to compress videos using FFmpeg and the H.264 codec, check out the FFmpeg H.264 encoding guide.
Another way to reduce a video's size is by changing its resolution - the dimensions of the video. Our input.mov file is 1920px x 1080px, which is a common resolution for high definition video. But you might be able to get away with a lower resolution, especially if the video is going to be viewed on a mobile device or embedded in a web page.
Let's look at a few examples of how to compress a video by reducing the resolution using FFmpeg:
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -crf 28 -vf scale=1280:720 output.mp4
In the above command, we added the scale
filter to one of our earlier commands to resize the video's width and height to 1280px x 720px. The -vf
option is used to apply the filter and is short for video filter.
The new files size is 9.8MB, a total reduction reduction of 96%.
It is also common to maintain the aspect ratio of the video so it does not become distorted. To do this we can use the scale
filter with a -1
value, which will automatically calculate the correct height or width based on the other dimension. Like this:
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -crf 28 -vf scale=-1:720 output.mp4
This will resize the height to 720px, while maintaining the original aspect ratio of the video.
Reducing the bitrate of a video can also impact its file size and gives you a lot of control over the compression. The bitrate is the number of bits per second that are used to encode the video. The higher the bitrate, the higher the quality of the video, but the larger the file size. Conversely, the lower the bitrate, the lower the quality of the video, but the smaller the file size.
Let's look at a few examples:
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -b:v 1000k -vf scale=-1:720 output.mp4
Here, we replace the -crf
parameter and use the -b:v 1000k
option to set the video bitrate to 1000 Kbps.
The file size now is 3.35MB, a reduction of almost 99%. You can definitely see a reduction in visual quality now, but depending on your use case this might be acceptable.
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -b:v 1000k -b:a 128k -vf scale=-1:720 output.mp4
We added the -b:a 128k
to set the audio bitrate to 128 Kbps. This won't have any effect on our sample video as it doesn't have any audio.
Finally, we can compress the video even further by reducing its frame rate. The frame rate is the number of frames per second (fps) that are displayed when the video is played. The higher the frame rate, the smoother the video, but the larger the file size. Conversely, the lower the frame rate, the choppier the video, but the smaller the file size.
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -b:v 1000k -b:a 128k -vf scale=-1:720 -r 15 output.mp4
In the above command, we use the -r
option to set the output frame rate to 15 frames per second.
Curiously, this has actually increased the file size to 3.37MB, so this option might not be needed when combined with other compression options.
If we run the command like this, without any other compression options, we can see the file size is 46.5MB, which is a slight reduction from 49MB when maintaining the original frame rate of 23.976:
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -r 15 output.mp4
Here is our final compressed video:
In this article we showed how it is possible to compress a video using FFmpeg by changing its properties. By using FFmpeg and applying the correct compression settings, you can drastically reduce the file size of your videos while optimising the visual quality level.
In our example we were able to reduce the original file size by up to 99% from 269MB to 3.35MB. Even if you don't go to such extremes, compressing a video by even 80-90% will save massive amounts on storage and bandwidth costs and lead to a better user experience with faster downloads and smoother playback.
If you are looking for an easier and more automated way to manage your media optimisation and compression needs, consider Shotstack as a viable FFmpeg alternative. The Shotstack Ingest API can be used to upload, ingest and compress videos using a simple JSON schema and cloud based processing.
curl --request POST 'https://api.shotstack.io/v1/render' \
--header 'x-api-key: YOUR_API_KEY' \
--data-raw '{
"timeline": {
"tracks": [
{
"clips": [
{
"asset": {
"type": "video",
"src": "https://shotstack-assets.s3.amazonaws.com/footage/beach-overhead.mp4"
},
"start": 0,
"length": "auto"
}
]
}
]
},
"output": {
"format": "mp4",
"size": {
"width": 1280,
"height": 720
}
}
}'