A simple guide to FFmpeg

10/13/2021

“This file format is not supported!” If you’ve ever received a notification like this, and you create content on a regular basis, then this blog post is probably for you!

Being a creative of any sort in this digital age, requires you to juggle a variety of different file formats across different platforms. On top of that, platforms (such as Twitter) have very strict format rules for things you want to upload, this makes it crucial to have an easy way to manage and convert different files to different formats at will.

In this blog post I’ll gently introduce you to ffmpeg and how it can help you with converting and editing your files! Here’s a quick index of the topics we’ll tackle:

Getting started with FFmpeg

  1. What is FFmpeg?
  2. FFmpeg command syntax
  3. File conversion example
  4. Command Options

Generally useful FFmpeg commands

  1. Collating frames into a GIF
  2. Cropping and Resizing
  3. Trimming Videos
  4. Converting to a web safe video format
  5. Converting multiple files in a directory

Additional Information

  1. Installing FFmpeg
  2. Cheat Sheet
  3. Reducing the size of your gifs
  4. End Notes

1.1 What's ffmpeg?

Simply put, FFmpeg is an open source video and audio processing tool. It allows you to convert between different encoding formats, in addition to editing video and audio files in a number of ways. It’s mainly designed to be a command-line interface (CLI) that you execute from your terminal (this is how we’ll be using it in this blog post), however it can also be integrated as a part of other software.

Know those fancy apps on your phone, that help you format your videos for IG? A lot of them probably use FFmpeg in the background. Can’t blame them though, why reinvent the wheel when FFmpeg exists? It’s super fast and versatile.

How can WE use FFmpeg? Well, for example, you were just about to upload a GIF file to some website when it notifies you that this file format is not supported. With FFmpeg we could easily convert this GIF file into an mp4 file, or a mov file, or an avi file, etc…

Video file too long? No problem we can trim it with FFmpeg. Video file size too large? No problem we can reduce it’s size with ffmpeg. You get the idea! In the rest of this blog post I’ll run over the most useful FFmpeg commands (especially for creatives).

1.2 FFmpeg command syntax

Before you have a heart attack, writing FFmpeg commands is actually super easy, but to elucidate how these commands are composed we’ll have to have a look at the general FFmpeg command syntax:

ffmpeg [global_options] {[input_file_options] -i input_url} ...
 {[output_file_options] output_url} ...

FFmpeg commands essentially always consists of two parts, an input stream and an output stream. With streams we generally mean input and output files, and it’s improtant to note that you we can have multiple input and multiple output streams. For example, you’d like to overlay two videos and merge them into a single video file.

For each one of these streams we can specify a number of conversion options that, in addition to converting between two formats, allow us to manipulate specific properties of the file. For example, you want the output file to have a secific frame rate, this could then be specified as an option. As you might’ve noticed, there are options that are applied specifically to the input stream, others specifically to the output stream, and others to the entire command.

1.3 Converting files with ffmpeg

The simplest and quintessential ffmpeg command would be the simple conversion command. It goes as shown:

ffmpeg -i input.mp4 output.gif

In this case we would be converting an mp4 file into a gif file. Notice the statement preceding the input file ‘-i’, this is how an option is specified FFmpeg (also often called flags). Here we’re telling FFmpeg that what follows is the input file. There are many such options in ffmpeg, each of which have their own purpose.

Aside videos and gifs, FFmpeg also allows you to convert audio files! I often record my guitar with my samsung phone. It’s recording app stores these files in the m4a format, which isn’t supported by sound editing applications and DAWs like Ableton Live. A much more sensible format would be MP3 or WAV:

ffmpeg -i recording.m4a output.wav

Same command as before, only thing that changed are the file types! FFmpeg will automatically handle the conversion between differen file types.

1.4 FFmpeg options

You can think about options as modifiers, that depending on their function, will somehow change the output and purpose of your command. To see a list of options that are avaiable in FFmpeg, you can simply type in ‘ffmpeg -h’, hit enter and it will print a relatively long list of different options as well as a description of what they do. If you want to see more or ALL options you can type in ‘ffmpeg -h long’ and ‘ffmpeg -h full’ respectively.

Let’s have a look at some of them:

ffmpeg -i input.mp4 -r 25 output.mp4

Say you have a video file that you’d like to turn into a GIF with a framerate of 25 fps. To achieve that, you’d add the ‘-r’ flag in front of the output file name, along with the rate you’d like to set it to.

Framerate would be one of many things that we could modify through an additional flag, and this will make much more sense in the coming next sections. If you’d like to read up on specific options and what they do, then FFmpeg has a wonderfully detailed documentation about all of them here.


2.1 Converting a series of frames into a gif/video

One super useful command that I often require for my p5js sketches, is collating/combining a sequence of frames into a video/gif:

ffmpeg -i frame%d.png output.gif

By manner of using a percentage sign ‘%’ in the input file stream, FFmpeg understands that it should be looking for multiple files that need to be processed. If you’ve exported them from p5js or processing, usually you’ll already have them appropriately named and numbered, generally in a sequential order, something like: frame1.png, frame2.png, frame3.png, …

Here the ‘%d’ signifies that FFmpeg should expect a sequentially increasing number in this position of the file name. You can learn more about these patterns in this section of the official documentation. (FYI tFFmpeg calls this a slideshow if it’s unrelated images, for googling purposes).

Optionally you may also add the framerate flag to the command, otherwise the default framerate will be 25 fps. Naturally, you can also split up a gif into it’s constituent frames by reversing the command:

ffmpeg -i  output.gif frame%d.png

And if for any unorthodox reason whatsoever, you need to convert a single image into a video or gif, you can also do that:

ffmpeg -i img.png output.gif

2.2 Cropping and Resizing

Cropping and resizing files are two things you’ve probably had to do at some point, and found them to be quite tedious, either using some software that isn’t very versatile, or online editors that are incredibly tedious to navigate. Well, fret not, FFmpeg has your back yet again.

Cropping

For a good run-down on croppping with FFmpeg, I’ve foun this stackexchange answer to be the best. The command for cropping a file is the following:

ffmpeg -i in.mp4 -vf crop="out_w:out_h:x:y" out.mp4

Here we’re using the vf flag, which stands for ‘video filter’, basically applying a video filter to the output stream. This flag is followed by ‘crop’, which tells FFmpeg that we’re using the crop video filter, and we also need to pass some parameters to this cropping filter.

Here the parameters ‘out_w’ and ‘out_h’ stand for the width and height of the area that you want to crop out, and equivalently ‘x’ and ‘y’ represent the coordinates of the top left corner of the cropping area. Essentially you’re recording a rectangular area of the input video, and you’re positioning this rectangular area with the parameters passed to the filter.

Scaling and Resizing

In a similar manner we can resize an input stream as follows:

ffmpeg -i in.mp4 -vf scale="out_w:-1" out.mp4

Here we use the ‘scale’ video filter. To the scale video filter we pass two arguments: a width and a height. In this case we’re choosing a specific output width ‘out_w’ and set the output height to ‘-1’. -1 essentially tells ffmpeg to calculate the correct output height, such that the output video has the same aspect ratio as the input video. Of course you can also do this the other way around ‘-1:out_h’ as well. Or set both width and height to different values.

2.3 Trimming Videos

Another command that I’ve found useful a couple of times:

ffmpeg -i input.gif -ss 00:00:00 -to 00:00:03 output.gif

Which essentially allows you to truncate the duration of a gif or video file, by setting a specific start and end time stamp in seconds. Trimming the video based on exact frames is a little bit more complicated, and is elucidated in this stackexchange answer.

2.4 Converting to a web safe format

Displaying full size GIFs on your website is a bad idea. Their size is huge, and if things don’t load quickly, it makes an immediate bad impression. A couple of weeks ago I decided to really clean up my blog and compress my GIFs into a much more manageable file format like MP4. It worked like a charm, but then I opened my blog on my phone to see how it looks, and it turns out that certain browsers only support certain types of pixel formats.

This was a problem that actually drove me a little bit mad for a while, since I couldn’t pinpoint what the issue was for a while, until I stumbled upon this blog post by Sidney Liebrand, that explains a little what web safe formats are, and provides an FFmpeg command to convert to an appropriate MP4 version:

ffmpeg -i file.gif -movflags +faststart -pix_fmt yuv420p -vf scale="trunc(iw/2)*2:trunc(ih/2)*2" file.mp4

The moveflags option is not necessary, but is nice to have, since it’ll automatically make your video run once it starts loading. The yuv420p pixel format is necessary for your video to be displayed in certain browsers. And an additional necessity of this pixel format is that the video needs to be resized such that it’s width and height are divisible by 2. The FFmpeg documentation offers a little explanation on this in a note called ‘encoding for dumb players’:

You may need to use -vf format=yuv420p (or the alias -pix_fmt yuv420p) for your output to work in QuickTime and most other players. These players only support the YUV planar color space with 4:2:0 chroma subsampling for H.264 video. Otherwise, depending on your source, ffmpeg may output to a pixel format that may be incompatible with these players.

To display your video on your website, and have it behave like a gif in disguise, is with the following html snippet:

<video autoplay="" loop="" muted="" playsinline="" draggable="true">
	<source src="path/to/video" type="video/mp4">
</video>

This is also very useful for perfectly looping GIFs. The ‘loop’ statement allows for seamless transitions from end to start.

2.5 Converting multiple files in a directory

This isn’t really a command specific to ffmpeg, but something I’ve found to come in handy in a couple of situations. Let’s assume we have a folder full of files that we’d like to process in some manner, and we don’t want to tediously type out an FFmpeg command for each one. We can accomplish this on windows with some additional syntax as follows:

FOR /F "tokens=*" %G IN ('dir /b *.gif') DO ffmpeg -i "%G" "%~nG.mp4"

And for macOS as well as Linux:

for i in *.gif; do ffmpeg -i "$i" "${i%.*}.mp4"; done

3.1 Installing FFmpeg

Maybe the most tedious part about getting started with FFmpeg is installing it, which will vary on the operating system that you currently have. Since there’s already so many tutorials on installing FFmpeg, I didn’t feel the necessity of including this info here again, but rather link to resources.

Here’s a good guide on installing FFmpeg on windows (what I’m using), just make sure that you create a new environment variable, such that you can run FFmpeg from your terminal, no matter what directory you open a terminal from.

And here’s a good guide on installing FFmpeg on macOs.

3.2 Cheat Sheet

I’ll be honest with you, the hardest part about ffmpeg commands is remembering them. Therefore I’ve made a little cheat sheet of the aforementioned commands and what they do:

Use case Command
Help
ffmpeg -h
Inspect File
ffmpeg -i filename.gif -hide_banner
Conversion
ffmpeg -i input.gif output.mp4
Frames to GIF
ffmpeg -i frame%d.png output.gif
GIF to frames
ffmpeg -i input.gif frame%d.png
Scaling/Resizing
ffmpeg -i in.mp4 -vf scale="out_w:-1" out.mp4
Cropping
ffmpeg -i in.mp4 -vf crop="out_w:out_h:x:y" out.mp4
Trim duration
ffmpeg -i input.gif -ss 00:00:00 -to 00:00:03 output.gif
Web Safe
ffmpeg -i file.gif -movflags +faststart -pix_fmt yuv420p \
-vf scale="trunc(iw/2)*2:trunc(ih/2)*2" file.mp4
Multiple Files Windows  
FOR /F "tokens=*" %G IN ('dir /b *.flac') \ 
DO ffmpeg -i "%G" -acodec mp3 "%~nG.mp3"

MacOs & Linux  
for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done

3.3 Reducing the size of gifs

This isn’t a single command per se, but we’ll have a quick look at some strategies that can potentially reduce the size of your gif files. I’d like to give a shout-out to two superb posts on the topic of quality and size of gif files with FFmpeg, this one as well as this one.

The topic of gifs, compression and size/quality tradeoffs are a can of worms, that better be opened in a separate future post, but for the sake of this section let’s have a look at some ways to reduce the file size of gifs.

One quick and dirty trick that I like a lot, is simply scaling the resolution of gif files down (which we have covered above). This tends to have a dramatic effect on the quality of the gif, but sometimes I just can’t be bothered when my GIF file size is just barely above the 15mb size limit of Twitter. Shaving off those 1-2mbs can usually be achieved by scaling down around 10%.

3.4 End notes

If you’ve made it this far, I sincerely hope this run down of FFmpeg was useful and you learned something new! I’m planning on making another blog post about FFmpeg, where we’ll use it for creative purposes and video effects, rather than just using it as a tool for conversion operations.

If you’ve enjoyed this blog post consider sharing it with a friend! Otherwise subscribe to the newsletter for the occasional update or come and say hi on Twitter! Cheers, and happy sketching!

News and Updates

If you enjoyed this post, consider subscribing to my mailing list for the occasional update on new blog posts. No spam, promise. Otherwise come join me on Twitter!