Video file too large to email? Uploads taking forever? FFmpeg’s CRF mode can reduce file size by 50–80% while preserving quality — all from a single command. This guide covers the right settings for every use case, with concrete benchmarks and tested examples.

Tested with: FFmpeg 6.1 (ubuntu-latest / GitHub Actions CI-validated)


What You Will Learn

  1. CRF mode (constant quality) vs bitrate mode — when to use each
  2. H.264 vs H.265 — which codec to pick
  3. CRF value and preset comparison tables (quality, size, speed)
  4. Combining resolution downscaling for maximum size reduction
  5. Audio stream optimization
  6. 2-pass encoding for precise file-size control
  7. Five common errors and fixes
  8. Five frequently asked questions

Command Examples

1. Universal: CRF Mode with H.264 (Most Versatile)

ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4
  • -c:v libx264 — H.264 codec
  • -crf 23 — quality factor (0–51; lower = better; default 23)
  • -preset medium — balanced encoding speed and compression
  • -c:a aac -b:a 128k — re-encode audio to AAC at 128 kbps

2. Higher Compression with H.265 (HEVC)

Produces files ~40–50% smaller than H.264 at equivalent quality. Encoding takes longer.

ffmpeg -i input.mp4 -c:v libx265 -crf 28 -preset medium -c:a aac -b:a 128k output.mp4

3. Small-Size Priority (SNS / Email Attachment)

ffmpeg -i input.mp4 -c:v libx264 -crf 32 -preset fast -vf scale=1280:-2 -c:a aac -b:a 96k output.mp4
  • -crf 32 — trades quality for a smaller file
  • -vf scale=1280:-2 — downscale to 1280px wide (height auto-rounded to even)
  • -b:a 96k — lower audio bitrate too

4. High-Quality Archive (Time Not a Constraint)

ffmpeg -i input.mp4 -c:v libx265 -crf 22 -preset slow -c:a aac -b:a 192k output.mp4

5. Bitrate-Controlled Compression (Strict Size Target)

Use when a streaming platform imposes a bitrate cap, or you need predictable file sizes.

# Video 2 Mbps + audio 128 kbps ≈ 2.1 Mbps total
ffmpeg -i input.mp4 -c:v libx264 -b:v 2000k -c:a aac -b:a 128k output.mp4

6. 2-Pass Encoding (Most Accurate Size Control)

# Pass 1: analyze video (no output generated)
ffmpeg -i input.mp4 -c:v libx264 -b:v 2000k -pass 1 -an -f null /dev/null

# Pass 2: generate the actual output
ffmpeg -i input.mp4 -c:v libx264 -b:v 2000k -pass 2 -c:a aac -b:a 128k output.mp4

The ffmpeg2pass-0.log file created by pass 1 can be deleted after pass 2 completes.


CRF Value Reference

CRFPerceived QualityUse CaseEstimated Size vs. Original
15–17Transparent (near visually lossless)Production masters60–80%
18–20ExcellentYouTube upload, archival40–60%
21–23High (default)General sharing, web25–40%
24–26GoodSocial media, preview15–25%
27–30Visible degradationEmail attachments8–15%
31–35Noticeable artifactsMinimum file size4–8%

Note: These estimates vary heavily by content type (action video, animation, talking-head, etc.). Always verify with your actual footage.


Preset Comparison

Same CRF value, different preset — size and speed change but perceived quality stays nearly the same.

PresetSpeedFile SizeRecommended For
ultrafastFastestLargestReal-time streaming
veryfastVery fastLargeLive transcoding, quick tests
fastFastSlightly largeQuick turnaround needed
mediumDefaultBalancedGeneral use
slowSlowSmallerYouTube uploads, archival
slowerVery slowSmallLong-term storage
veryslowSlowestSmallestMaximum efficiency required

Practical recommendation: Use medium by default; switch to slow when encoding time is not a concern.


H.264 vs H.265: Which to Choose?

AspectH.264 (libx264)H.265 (libx265)
CompatibilityNearly universal (phones, TVs, browsers)Moderate (older Android, some browsers need plugin)
CompressionStandard~40–50% smaller than H.264 at same quality
Encoding speedFast2–4× slower than H.264
Software playbackUniversally supportedWidely supported; some players need additional codec
Recommended CRF18–2824–34 (set ~5 higher than H.264 for same quality)
Best forWeb delivery, social media, broad audiencesPersonal storage, space-saving, controlled environments

Combining Resolution Downscaling

Downscaling resolution multiplies the size reduction from codec compression.

# 4K → 1080p + H.265
ffmpeg -i input_4k.mp4 -c:v libx265 -crf 26 -preset medium \
  -vf scale=1920:-2 -c:a aac -b:a 128k output_1080p.mp4

# 1080p → 720p + H.264 (social media)
ffmpeg -i input_1080p.mp4 -c:v libx264 -crf 26 -preset fast \
  -vf scale=1280:-2 -c:a aac -b:a 96k output_720p.mp4

-vf scale=1280:-2: the -2 rounds the height to the nearest even number. Use -2 instead of -1 to avoid codec errors.


Audio Optimization

Audio alone can contribute significantly to file size.

# Drop audio entirely (video only)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -an output.mp4

# Convert to mono (effective for voice-only content)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -c:a aac -ac 1 -b:a 64k output.mp4

Audio size reference: 128k stereo ≈ 5.6 MB/min | 96k ≈ 4.2 MB/min | 64k mono ≈ 2.8 MB/min


Option Reference

OptionMeaningRecommended Value
-c:v libx264H.264 encoderBest compatibility
-c:v libx265H.265 encoderWhen size matters more than speed
-crf NQuality factor (0–51)H.264: 18–28 / H.265: 24–34
-preset NAMESpeed vs. compressionmedium default; slow for storage
-b:v NkVideo bitrate target720p: 1500k / 1080p: 4000k / 4K: 15000k
-b:a NkAudio bitrateStereo: 128k–192k / Voice: 64k–96k
-vf scale=W:-2Resize videoscale=1280:-2 (width=1280, even height)
-movflags +faststartMove moov atom to startRequired for web streaming / progressive download

Troubleshooting

Problem 1: Encoder libx265 not found

Cause: Your FFmpeg build lacks H.265 support.
Fix: Check with ffmpeg -codecs | grep hevc. If E is missing, reinstall the full FFmpeg binary:

brew install ffmpeg          # macOS
sudo apt install ffmpeg      # Ubuntu/Debian

Problem 2: Encoding Is Extremely Slow

Cause: -preset veryslow/slow on high-resolution video, or H.265 on older hardware.
Fix: Switch to medium or fast. For H.265, the slowness is inherent — consider H.264 if time matters.

Problem 3: Output File Is Larger Than Expected

Cause: CRF too low, or preset ultrafast/veryfast with poor compression efficiency.
Fix: Raise CRF by 2–4 and/or switch to a slower preset:

ffmpeg -i input.mp4 -c:v libx264 -crf 26 -preset slow -c:a aac -b:a 128k output.mp4

Problem 4: width not divisible by 2

Cause: The scale filter produced an output dimension that’s an odd number.
Fix: Use -vf scale=1280:-2 (the -2 ensures the height is rounded to an even number).

Problem 5: Pass 1 Finished But No Output File

Cause: This is expected behavior. Pass 1 uses -f null /dev/null intentionally — it only generates the stats log file, not a video.
Fix: Run the pass 2 command to produce the actual output.


FAQ

Q1. Should I use CRF mode or bitrate mode?
A. CRF mode for almost everything. It maintains consistent quality across varying scene complexity. Use bitrate mode only when you need strict file-size control (e.g., platform bitrate caps).

Q2. Is CRF 23 the best setting for any video?
A. No — CRF 23 is just the encoder default. Action-heavy video may need CRF 20; animation with flat colors can go down to CRF 18–22. Always review the actual output.

Q3. Should I copy or re-encode the audio?
A. Use -c:a copy to avoid any quality loss. Use -c:a aac -b:a 128k if you also need to reduce audio size. Re-encoding always introduces a small quality reduction.

Q4. Can I use GPU encoding on macOS?
A. Yes — VideoToolbox is available on Apple Silicon and Intel Macs:

ffmpeg -i input.mp4 -c:v h264_videotoolbox -b:v 4000k -c:a aac output.mp4

CRF mode is not available; specify bitrate with -b:v instead.

Q5. How do I compress all videos in a folder at once?

for f in *.mp4; do
  ffmpeg -i "$f" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k "compressed_${f}" -y
done


Tested with: ffmpeg 6.1.1 / Ubuntu 24.04 (GitHub Actions runner)
Primary sources: ffmpeg.org/ffmpeg.html / ffmpeg.org/ffmpeg-codecs.html / ffmpeg.org/ffmpeg-filters.html