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
- CRF mode (constant quality) vs bitrate mode — when to use each
- H.264 vs H.265 — which codec to pick
- CRF value and preset comparison tables (quality, size, speed)
- Combining resolution downscaling for maximum size reduction
- Audio stream optimization
- 2-pass encoding for precise file-size control
- Five common errors and fixes
- 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.logfile created by pass 1 can be deleted after pass 2 completes.
CRF Value Reference
| CRF | Perceived Quality | Use Case | Estimated Size vs. Original |
|---|---|---|---|
| 15–17 | Transparent (near visually lossless) | Production masters | 60–80% |
| 18–20 | Excellent | YouTube upload, archival | 40–60% |
| 21–23 | High (default) | General sharing, web | 25–40% |
| 24–26 | Good | Social media, preview | 15–25% |
| 27–30 | Visible degradation | Email attachments | 8–15% |
| 31–35 | Noticeable artifacts | Minimum file size | 4–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.
| Preset | Speed | File Size | Recommended For |
|---|---|---|---|
ultrafast | Fastest | Largest | Real-time streaming |
veryfast | Very fast | Large | Live transcoding, quick tests |
fast | Fast | Slightly large | Quick turnaround needed |
medium | Default | Balanced | General use |
slow | Slow | Smaller | YouTube uploads, archival |
slower | Very slow | Small | Long-term storage |
veryslow | Slowest | Smallest | Maximum 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?
| Aspect | H.264 (libx264) | H.265 (libx265) |
|---|---|---|
| Compatibility | Nearly universal (phones, TVs, browsers) | Moderate (older Android, some browsers need plugin) |
| Compression | Standard | ~40–50% smaller than H.264 at same quality |
| Encoding speed | Fast | 2–4× slower than H.264 |
| Software playback | Universally supported | Widely supported; some players need additional codec |
| Recommended CRF | 18–28 | 24–34 (set ~5 higher than H.264 for same quality) |
| Best for | Web delivery, social media, broad audiences | Personal 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-2rounds the height to the nearest even number. Use-2instead of-1to 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
| Option | Meaning | Recommended Value |
|---|---|---|
-c:v libx264 | H.264 encoder | Best compatibility |
-c:v libx265 | H.265 encoder | When size matters more than speed |
-crf N | Quality factor (0–51) | H.264: 18–28 / H.265: 24–34 |
-preset NAME | Speed vs. compression | medium default; slow for storage |
-b:v Nk | Video bitrate target | 720p: 1500k / 1080p: 4000k / 4K: 15000k |
-b:a Nk | Audio bitrate | Stereo: 128k–192k / Voice: 64k–96k |
-vf scale=W:-2 | Resize video | scale=1280:-2 (width=1280, even height) |
-movflags +faststart | Move moov atom to start | Required 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
Related Articles
- Trimming Video — -ss/-to/-t Complete Guide
- Two-Pass Encoding — Precise Bitrate and File Size Control
- Convert Video to MP4 — Complete Guide
- Batch Convert with Shell Scripts
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