Optimizing Video with FFmpeg: A Comprehensive Introduction

FFmpeg is an efficient cross-platform tool capable of recording, converting, editing and streaming digital audio and video in various formats. Although it can perform most multimedia tasks quickly and easily, it is a command-line tool, making it challenging and verbose to use. In this guide, we will demonstrate how to perform some typical operations to produce videos for web and social media.

ffmpeg video optimized

To easily resize and edit your videos online for web and social media, you can use Abraia Studio. For testing, we will use the Big Buck Bunny trailer, which you can download in FullHD video format from this link.

Converting video for the web

The first step in producing a video for the web is to encode it in the appropriate format. The most widely supported format for the web is MP4 encoded with H264. This codec generates small files with excellent quality and works on web browsers, phones, tablets, and TVs.

To encode a video as MP4 with H264, use the following command:

ffmpeg -i trailer_1080p.mov video.mp4

By default, FFmpeg uses the file extension to select the encoding. For example, a .mp4 file is encoded in H264. Typically, FFmpeg has a good selection of parameters by default, so we don't need to know anything about video encoding. A full specification of video encoding parameters is as follows:

ffmpeg -i trailer_1800p.mov -c:v libx264 -crf 21 -preset veryfast -profile:v high -level 4.0 -color_primaries 1 -color_trc 1 -colorspace 1 -movflags +faststart -c:a aac -b:a 128k video.mp4

The only important parameter to consider from the above command is -movflags +faststart, which enables quick start playing on web browsers.

Resizing video for social media

A typical operation required before publishing is resizing a video for a platform or device. To resize a video with FFmpeg we just need to specify the new size (width and height) using the "scale" filter. When we specify the height as -2 this will be calculated to preserve the current aspect ratio.

ffmpeg -i trailer_1080p.mov -vf "scale=1280:-2" video.mp4

However, if we need to change the aspect ratio of the video, simply resizing it may not yield good results. In such cases, we can either pad the video with a flat color or crop it.

For instance, to pad a video to an aspect ratio of 1:1 for sharing on Instagram, we can use the following command:

ffmpeg -i trailer_1080p.mov -vf "scale=720:720:force_original_aspect_ratio=decrease,pad=720:720:(ow-iw)/2:(oh-ih)/2:black" video.mp4

In the above command, we are scaling the video down to 720x720 and using the "force_original_aspect_ratio" option to maintain the original aspect ratio while scaling. We are then padding the video with a black color to make it square.

Or, to crop a video to an aspect ratio of 1:1, we can use the following command:

ffmpeg -i trailer_1080p.mov -vf "crop='min(iw,1*ih)':'min(iw/1,ih)',scale=720:720" video.mp4

In this command, we are cropping the video to a square aspect ratio of 1:1 by specifying the minimum of the input width and height for both the width and height of the crop, and then scaling the cropped video to 720x720.

ffmpeg resized padding ffmpeg resized cropping
Resize to a square aspect ratio with padding (first) and with cropping (second)

Other resize option is to add a blurred background to the video. For this example, we need to use the "filter_complex" option to merge two video streams: one for the background and one for the foreground.

  1. First, we take the video input with [0:v] and we apply a blur filter to produce the background [bg].

  2. Second, we take again the video input with [0:v] and we resize the video to create the foreground [fg].

  3. Third, we take the background [bg] and overlay the [fg] to build the final video stream [outv].

  4. Fourth, we take the audio input with [0:a] and we create a final audio stream without effects [outa].

  5. Finally, we map both outputs for video [outv] and audio [outa] to get the final result.

The following command shows how to do this:

ffmpeg -i trailer_1080p.mov -filter_complex "[0:v]scale=720:720,boxblur=luma_radius=min(h\,w)/20:luma_power=1:chroma_radius=min(cw\,ch)/20:chroma_power=1[bg];[0:v]scale=720:720:force_original_aspect_ratio=decrease[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2[outv]" -map [outv] -map 0:a? video.mp4

We can even add a logo, we just need a PNG image with our logo or message in a transparent background an run a command as bellow:

ffmpeg -i video_clip.mp4 -i logo.png -filter_complex "overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2" video.mp4
ffmpeg resized blur background ffmpeg resized logo overlay
Resize with a blurred background (first) and with a logo overlay (second)

Trimming a video short clip

Lots of time we need to select a clip from a video. Trimming an video with FFmpeg is a little tedious because we need to use some video player to look for the starting and stopping times of the clip that we want to cut.

ffmpeg -i trailer_1080p.mov -ss 13.2 -to 16 video_clip.mp4

You can also use the time duration to specify the video cut end.

ffmpeg -i trailer_1080p.mov -ss 13.2 -t 2.8 video_clip.mp4

Create a video frame poster

Other common task is to create a poster from a video frame. This can be easily made with just to know the timing of such frame.

ffmpeg -i video.mp4 -ss 14.5 -vframes 1 -q:v 2 poster.jpg

Convert a video to GIF

Finally, a useful option to include our videos in, for instance, mail marketing campaigns is to convert it to an animated GIF. This can be directly done with one command, but the result with FFmpeg is very disappointing.

ffmpeg -i video_clip.mp4 -vf "fps=10,scale=320:-2:flags=lanczos" video_clip.gif

The problem rises because the GIF format only supports 256 colors. This demands to generate a custom color palette first to improve the results.

ffmpeg -i video_clip.mp4 -vf "fps=10,scale=320:-2:flags=lanczos,palettegen" palette.png

Created the color palette (palette.png) with the most representative 256 colors for our animation, we can already generate the GIF animation.

ffmpeg -i video_clip.mp4 -i palette.png -filter_complex "fps=10,scale=320:-2:lanczos[video];[video][1:v]paletteuse" video_clip-palette.gif
ffmpeg animation nocolor palette ffmpeg animation color palette
Animated GIFs created directly from the video (first) and with the custom color palette (second)