FFmpeg for Instagram
Tags: ffmpeg, instagram, video, tutorial
Published: 2021-05-20 18:01:51

Uploading high quality video to [Instagram](https://www.instagram.com/) can result in lower quality video on posts and stories due to aggressive re-encoding to save on bandwidth and storage for users. You will notice this especially if uploading videos from [GoPro](https://gopro.com) or other devices captured in 4K or 1440p with larger file sizes. Although the video preview on Instagram looks high quality, the resulting output will be degraded drastically.

This guide describes various [FFmpeg](https://ffmpeg.org) encoding presets that can be used to help improve your video quality output when uploading to Instagram. These settings can also be applied to other encoders, such as [Handbrake](https://handbrake.fr).

## Recommended Encoding Settings
Instagram does not provide an official list of encoding requirements. These settings are gathered from various sources and through trial and error. However, Instagram does provide some [encoding requirements for IGTV](https://help.instagram.com/1038071743007909).

Set your encoder to use these settings: 
* MP4 Container format
* H.264 Video Codec
* AAC Audio
* 3500kbps bitrate
* 30 FPS
* 60 seconds maximum in length
* 1080p 16:9 max (vertical or horizontal)

Also, if you inspect a story video using a tool like [mediainfo](https://mediaarea.net/en/MediaInfo), you'll see something like the following:
```
First video stream:
1 367 kb/s 640*1136 (0.563) at 30.000 FPS, AVC (Main@L3)(CABAC 4 Ref Frames)
64.0 kb/s 44.1 kHz, 1 channel, AAC LC
```

Stories without audio, don't have an audio stream within the container at all.

## Optimize with FFmpeg
We can apply the settings above using `FFmpeg`. Here are some encoding profiles to try out.

#### `720p30 @ CRF 23`
Using CRF only without targetting a bitrate.
```
ffmpeg -i INPUT.MOV -vf scale=-2:720 -c:v libx264 -profile:v main -level:v 3.0 -x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72 -c:a aac -preset slow -crf 23 -r 30 -sn -f mp4 OUTPUT.mp4
```

#### `720p30 @ 3500k video bitrate + 256k audio bitrate`
Variable bitrate with a max of 3500k.
```
ffmpeg -i INPUT.MOV -vf scale=-2:720 -c:v libx264 -profile:v main -level:v 3.0 -x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72:ref=4 -c:a aac -crf 23 -maxrate 3500k -bufsize 3500k -r 30 -ar 44100 -b:a 256k -sn -f mp4 OUTPUT.mp4
```

#### `720p30 @ 3500k video bitrate + 256k audio bitrate - 2-pass encoding`
Using 2-pass encoding with a targetted bitrate of 3500k. This doesn't necessarily improve quality, but helps target a filesize more accurately.
```
ffmpeg -i INPUT.MOV -vf scale=-2:720 -c:v libx264 -profile:v main -level:v 3.0 -x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72:ref=4 -c:a aac -b:v 3500k -maxrate 3500k -bufsize 3500k -r 30 -ar 44100 -b:a 256k -pass 1 -sn -f mp4 NUL && \ 
 ffmpeg -i INPUT.MOV -vf scale=-2:720 -c:v libx264 -profile:v main -level:v 3.0 -x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72:ref=4 -c:a aac -b:v 3500k -maxrate 3500k -bufsize 3500k -r 30 -ar 44100 -b:a 256k -pass 2 OUTPUT.mp4
```

Try adjusting a few settings to get the optimal quality and filesize before uploading. Maybe try 1080p for IGTV, per their specification.

#### What do those options mean?
* `-i INPUT.MOV` - Input movie file.
* `-vf scale=-2:720` - Video filter to scale to 720p while keeping aspect ratio.
* `-c:v libx264` - Use `x264` video codec.
* `-profile:v main -level:v 3.1` - Mostly for H.264 compatibility for older devices. This seems to be the profile Apple devices export to.
* `-x264-params scenecut=0:open_gop=0:min-keyint=72:keyint=72:ref=4` - Some x264 codec options I use to improve video for streaming.
* `-c:a aac` - Use AAC audio codec.
* `-preset slow` - Slower presets will result in better quality. Feel free to also try `slower` and `veryslow`.
* `-crf 23` - Constant Rate Factor encoding mode that adjusts the file data rate up or down to achieve a selected quality level rather than a specific data rate.
* `-b:v 3500k` - Targets video bitrate to 3500k.
* `-b:a 256k` - Targets audio bitrate to 256k.
* `-ar 44100` - Sets audio sample rate to 44.1 kHz.
* `-r 30` - Sets the framerate to 30.
* `-f mp4` - Sets the MP4 container format. This is optional if you have `.mp4` in the output filename.
* `OUTPUT.mp4` - The encoded output movie file.

## Demo
Here's a before and after test I created using the above requirements. These were downloaded directly from Instagram after posting to compare results.

The source video file being a 3840x2160 @ 60fps (4K) file recorded from a GoPro Hero 8 at 567MB in size.

The optimized video encoded at 1280x720 @ 30fps using the 2-pass profile settings at 34.7MB in size.

#### Without optimizing video
<video src="https://video-examples-public.s3.us-west-2.amazonaws.com/ig/01_ig_video_before.mp4" controls muted />

#### With optimized video
<video src="https://video-examples-public.s3.us-west-2.amazonaws.com/ig/02_ig_video_after.mp4" controls muted />

#### Without optimizing as a story
<video src="https://video-examples-public.s3.us-west-2.amazonaws.com/ig/03_ig_story_before.mp4" controls muted />

#### Optimized video as a story
<video src="https://video-examples-public.s3.us-west-2.amazonaws.com/ig/04_ig_story_after.mp4" controls muted />

Notice the unoptimized videos have more jagged edge artifacts around the guard rails and curb, especially for video with a lot of motion.

The goal is basically to reduce your video to an optimal size and image quality so it doesn't get affected as much by Instagram's aggressive encoding.

Try adjusting some settings to find the best results for your use case and picture. Results will vary!

## Thanks for reading!

Find me on GitHub at: https://github.com/alfg for more video-related projects!

## Resources
* https://ffmpeg.org/
* https://trac.ffmpeg.org/wiki/Encode/H.264
* https://handbrake.fr/
* [Video upload requirements for IGTV ](https://help.instagram.com/1038071743007909)
* https://mediaarea.net/en/MediaInfo