Best Video Settings for Instagram Reels (Bitrate, Resolution + FFmpeg Preset)

Conventional wisdom says crank the bitrate as high as your encoder allows and Reels will look sharp. It won't. Instagram re-encodes every upload on its own servers, so a 30 Mbps master doesn't buy you 30 Mbps of quality on someone's phone. It buys you a file that fails the upload check or gets mangled harder in transcode. What actually matters is hitting Instagram's ingest spec cleanly so their encoder has an easy job.
Quick answer: For Instagram Reels, export at 1080x1920 (9:16), H.264 High profile, 30fps, yuv420p pixel format, with a video bitrate around 5 Mbps and +faststart enabled. Keep the file under 50 MB and audio at AAC 128–256 kbps. The Instagram Reels bitrate that gives clean re-encodes without wasted bytes is roughly 5 Mbps for 1080p vertical.If you're exporting one clip by hand, this is a five-minute FFmpeg job. If you're pushing 50 Reels a night out of an n8n workflow, you want the same spec baked into a preset you can call once per clip. Both are below.
The exact Instagram Reels export spec
Instagram Reels wants a vertical H.264 MP4 that its own transcoder can re-encode without a fight. Here is the full target spec, with the values that matter for a clean ingest.
| Setting | Value | Why |
|---|---|---|
| Resolution | 1080 x 1920 (9:16) | Native Reels frame; anything else gets scaled or padded |
| Container | MP4 | Universally accepted; MOV works but MP4 is safest |
| Video codec | H.264 (High profile) | The only codec Instagram reliably ingests |
| Frame rate | 30 fps (up to 60) | 30 is the safe default; keep it constant, not variable |
| Video bitrate | ~5 Mbps (3–8 Mbps range) | Enough detail for the re-encode, not so much you bloat the file |
| Pixel format | yuv420p | 4:2:0 chroma; yuv444p or 10-bit gets rejected or force-converted |
| Audio codec | AAC-LC | Standard for MP4 |
| Audio bitrate | 128–256 kbps | 128k is fine for voice, 256k for music |
| Audio sample rate | 44.1 kHz | 48 kHz also works; avoid odd rates |
| Fast start | `+faststart` | Moves the moov atom to the front so playback starts before full download |
| Max file size | Keep under 50 MB | Practical target for fast uploads and clean transcodes |
| Duration | Up to 90 seconds (3 min on newer accounts) | Trim to fit or Instagram truncates |
Two of these trip people up. yuv420p is non-negotiable: FFmpeg's libx264 defaults to yuv444p for some sources, and Instagram's encoder either rejects that or silently converts it and softens your footage. And +faststart isn't about upload success, it's about the moov atom sitting at the front of the file so the player can begin before the whole thing downloads.
The copy-paste FFmpeg command for Reels
Here is the one command that takes any input (horizontal, square, odd aspect ratio) and produces a Reels-ready file. It scales to fit 1080x1920, pads the rest with black, and encodes to the spec above.
ffmpeg -i input.mp4 \
-vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black,setsar=1" \
-c:v libx264 -profile:v high -preset medium -crf 23 \
-pix_fmt yuv420p -r 30 \
-c:a aac -b:a 128k -ar 44100 \
-movflags +faststart \
output.mp4
What each piece does:
scale=...:force_original_aspect_ratio=decreaseshrinks the source to fit inside 1080x1920 without distorting it.pad=1080:1920:(ow-iw)/2:(oh-ih)/2:blackfills the leftover space with black bars so the output is exactly 9:16. Swap black bars for a blurred fill if you'd rather, covered in how to add a blurred background to vertical video.setsar=1forces a square pixel aspect ratio, which prevents the stretched-video bug some players show.-crf 23targets quality instead of a fixed bitrate. For a typical talking-head or screen-recording Reel this lands around 3–6 Mbps and well under 50 MB.
When you need to guarantee a file size
CRF gives you consistent quality but unpredictable size. If a 90-second clip has to stay under 50 MB no matter what, target the bitrate directly with two-pass encoding. 50 MB over 90 seconds is roughly 4.4 Mbps total, so leave headroom for audio and target ~4 Mbps video.
ffmpeg -i input.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black,setsar=1" \
-c:v libx264 -b:v 4M -maxrate 5M -bufsize 8M -pix_fmt yuv420p -r 30 \
-pass 1 -an -f mp4 /dev/null && \
ffmpeg -i input.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black,setsar=1" \
-c:v libx264 -b:v 4M -maxrate 5M -bufsize 8M -pix_fmt yuv420p -r 30 \
-pass 2 -c:a aac -b:a 128k -ar 44100 -movflags +faststart output.mp4
The broader math on bitrate versus perceived quality is in compress video for the web, which walks through CRF, codecs, and one-call presets in more detail.
The batch problem: same spec, 200 clips a night
Conventional wisdom: this FFmpeg command scales fine, just loop it. The problem isn't the command, it's where it runs. A faceless-channel builder assembling 200 clips a night from a Make scenario doesn't have FFmpeg installed on Make's servers, and neither does an n8n Cloud instance or a Zapier Zap. The two-pass encode above also chews CPU and can run for minutes on a long clip, which is exactly the kind of long-running job that trips n8n's HTTP timeout.
That's the wall most automation builders hit. Your workflow tool speaks HTTP and JSON. It does not compile FFmpeg, mount a filesystem, or babysit a two-pass encode. You end up standing up a media microservice on a VPS just to run one command, then keeping it patched and scaled.
The alternative is to keep the exact spec above and move the encode off your machine entirely. FFmpeg Micro exposes the FFmpeg toolkit as an API: submit a job with the input URL and your Reels settings, poll or receive a webhook, download the output. One call replaces the microservice.
curl -X POST https://api.ffmpeg-micro.com/v1/jobs \
-H "Authorization: Bearer $FFMPEG_MICRO_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "https://your-bucket.s3.amazonaws.com/raw-clip.mp4",
"operation": "transcode",
"output": {
"width": 1080,
"height": 1920,
"fit": "pad",
"video_codec": "h264",
"fps": 30,
"pixel_format": "yuv420p",
"video_bitrate": "5M",
"faststart": true
}
}'
The job runs on managed infrastructure, so there's no server to run and no FFmpeg to install. Because it's just an HTTP call that returns a job ID, it drops straight into n8n, Make, or Zapier, and it sidesteps the workflow-timeout trap covered in how to fix n8n timeout errors when processing video. Check the docs for the current parameter names before wiring it up.
CLI vs API, side by side
| Local FFmpeg | FFmpeg Micro API | |
|---|---|---|
| Setup | Install and patch FFmpeg per machine | None; it's an HTTP endpoint |
| Runs inside n8n/Make/Zapier | No, needs a server | Yes, one HTTP node |
| Long two-pass encodes | Blocks your worker | Runs off your infra, webhook on done |
| Scaling to 200 clips/night | You manage the queue | Submit jobs, they run in parallel |
Common pitfalls exporting Reels programmatically
Most failed Reels uploads trace back to a handful of spec mismatches. These are the ones worth checking first.
- Wrong pixel format. If you skip
-pix_fmt yuv420p,libx264may output 4:4:4 or 10-bit and Instagram rejects it or over-softens it. This is the exact class of failure behind the well-known PHP-FFMpeg GitHub issue where exports silently missed Reels requirements. Always set it explicitly. - Missing faststart. Without
-movflags +faststartthe moov atom sits at the end of the file. Uploads still work but playback and preview generation stall. Add it every time. - Odd resolution or non-square pixels. H.264 needs even dimensions, and a non-1:1 sample aspect ratio makes video look stretched.
setsar=1and the 1080x1920 target handle both. - Variable frame rate. Screen recordings and phone footage often ship VFR, which desyncs audio after re-encode. Force constant frame rate with
-r 30. - File too large. A high-bitrate 3-minute master can blow past 50 MB and slow or fail the upload. Use the two-pass command or lower CRF. Run ffprobe on the output to confirm size, bitrate, and pixel format before you push it.
When you don't need any of this
If you're posting one Reel a week from your phone, the Instagram app already exports to spec, and running FFmpeg is overkill. If you're editing in CapCut or Premiere, use their built-in "Instagram" or "9:16 1080p" presets and skip the command line entirely.
FFmpeg, local or API, earns its place when export is programmatic: you're generating clips from a template, repurposing long-form into shorts at volume, or assembling faceless videos where a human never touches the export dialog. That's when a fixed, verified spec and a repeatable command stop being nice-to-have and start being the thing that keeps your queue moving.
FAQ
What bitrate should I use for Instagram Reels?
Around 5 Mbps for 1080x1920 H.264 video is the practical target. Instagram re-encodes every upload, so pushing 20–30 Mbps mostly bloats your file without improving the final result. A 3–8 Mbps range covers everything from talking-head clips to fast-motion footage.
What resolution and aspect ratio do Instagram Reels use?
Reels use 1080x1920, a 9:16 vertical aspect ratio. Export at that exact resolution so Instagram's encoder doesn't have to scale, which softens the image. For horizontal or square sources, scale to fit and pad to 9:16 rather than stretching.
What is the best FFmpeg preset for Instagram Reels?
Use libx264 with -profile:v high -preset medium -crf 23 -pix_fmt yuv420p -r 30 and -movflags +faststart, scaled and padded to 1080x1920. The -preset medium value balances encode speed against file size; use slow for a bit more compression if encode time doesn't matter.
Why does my Reel fail to upload or look blurry?
The two most common causes are a non-yuv420p pixel format and a missing +faststart flag. Instagram's ingest expects 4:2:0 chroma and a front-loaded moov atom; anything else gets rejected or degraded. Check the output with ffprobe to confirm both before uploading.
What is the maximum file size and length for a Reel?
Keep the file under 50 MB for fast, reliable uploads, and trim video to 90 seconds (up to 3 minutes on newer accounts). Longer or heavier files upload slower and are more likely to be truncated or re-compressed harder.
Want to test the exact spec above without installing anything? Drop a clip into the playground to see the 1080x1920 output, then sign up free to run the same preset across every clip in your pipeline.
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

FFmpeg in the cloud vs running FFmpeg yourself: total cost of ownership
FFmpeg cloud vs self hosted cost, compared with real numbers: EC2, engineer time, egress, and hidden DevOps overhead vs a usage-based video API.

Compress video for the web: bitrate, codecs, and one-call presets
Compress video for the web with the right bitrate, codec, and CRF preset. See the exact FFmpeg command plus a one-call video compression API you can try free.

How to Replace Audio in Video with FFmpeg (Track Swap API Guide)
Replace audio in video with FFmpeg by mapping the video and new audio streams, or run the same track swap as one API call with FFmpeg Micro's hosted API.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free