DEV Community

Cover image for FFmpeg for Instagram
alfg
alfg

Posted on

FFmpeg for Instagram

Uploading high quality video to Instagram 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 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 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.

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.

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, 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

With optimized video

Without optimizing as a story

Optimized video as a story

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

Top comments (0)