ffmpegvideo-compressioncrfencoding

How to Compress Video with FFmpeg Without Losing Quality

·Javid Jamae·8 min read
How to Compress Video with FFmpeg Without Losing Quality

You've got a 500MB video that needs to be 50MB. The catch? You can't make it look terrible. This is the most common FFmpeg problem developers run into, and the solution is simpler than you'd think.

FFmpeg gives you precise control over the quality-to-size tradeoff through a setting called CRF (Constant Rate Factor). Get it right, and you'll cut file sizes by 50-80% with no visible quality loss.

What Is CRF and Why Does It Matter for Video Compression?

CRF stands for Constant Rate Factor. It tells the encoder how much quality you're willing to sacrifice for a smaller file. Lower CRF = higher quality = bigger file. Higher CRF = lower quality = smaller file.

For H.264 (libx264), the CRF scale runs from 0 (lossless) to 51 (worst). The sweet spot for most developers is CRF 18-28:

  • CRF 18: Visually lossless. You won't see the difference from the original. Files are still large.
  • CRF 23: The default. Good balance between quality and size. Most projects should start here.
  • CRF 28: Noticeable quality loss on close inspection, but perfectly fine for web delivery and social media.

Every 6 CRF points roughly doubles or halves the file size. So going from CRF 18 to CRF 24 cuts your file size by about 75%.

How to Compress Video with FFmpeg Using CRF

The basic command is one line:

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

That takes your input video, re-encodes it with H.264 at CRF 23, and compresses the audio to 128kbps AAC. For most 1080p content, this drops a 500MB file down to roughly 50-100MB.

Want better quality? Lower the CRF:

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

Notice the -preset slow flag. Presets control how much time FFmpeg spends optimizing compression. Slower presets produce smaller files at the same quality. The options from fastest to slowest are: ultrafast, superfast, veryfast, faster, fast, medium (default), slow, slower, veryslow.

In practice, slow gives you about 5-10% better compression than medium with a meaningful increase in encoding time. Going beyond slow rarely justifies the extra wait unless you're encoding a massive library.

H.264 vs H.265 vs AV1: Which Codec Should You Use?

The codec you choose has a bigger impact on file size than almost any other setting.

CodecFFmpeg encoderTypical size reduction vs H.264Browser supportEncoding speed
H.264libx264BaselineUniversalFast
H.265 (HEVC)libx26525-50% smallerSafari, Edge, Chrome (partial)2-3x slower
AV1libsvtav130-50% smallerChrome, Firefox, Edge5-10x slower

H.264 with libx264 is the safe default. Every browser, every device, every player supports it. If you need maximum compatibility, stop here.

H.265 produces significantly smaller files but has licensing complications and inconsistent browser support. Use it when you control the playback environment (mobile apps, set-top boxes).

AV1 is the future. It's royalty-free and produces the smallest files, but encoding is slow. Google uses it for YouTube. If you're encoding content once and serving it millions of times, AV1 is worth the encoding cost.

H.265 compression at CRF 28 (roughly equivalent quality to H.264 CRF 23):

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

And AV1 with libsvtav1:

ffmpeg -i input.mp4 -c:v libsvtav1 -crf 30 -preset 6 -c:a libopus -b:a 128k output.webm

Note that CRF scales differ between codecs. CRF 28 in H.265 is not the same as CRF 28 in H.264.

Two-Pass Encoding for Target File Size

CRF is great when you care about quality. But sometimes you need to hit a specific file size, like a 25MB upload limit. Two-pass encoding solves this.

Two-pass encoding analyzes the video first, then encodes with a target bitrate that produces your desired file size.

Calculate your target bitrate: target_bitrate = (target_size_in_bits / duration_in_seconds) - audio_bitrate

For a 60-second video at 25MB with 128kbps audio:

# Pass 1: Analyze
ffmpeg -i input.mp4 -c:v libx264 -b:v 3200k -pass 1 -an -f null /dev/null

# Pass 2: Encode
ffmpeg -i input.mp4 -c:v libx264 -b:v 3200k -pass 2 -c:a aac -b:a 128k output.mp4

The first pass generates a log file. The second pass uses that log to distribute bits efficiently across the video. Scenes with lots of motion get more bits. Static scenes get fewer.

Reducing Audio Bitrate (The Easy Win)

Audio often accounts for 10-20% of a video file. If you're compressing aggressively, don't ignore it.

Most people can't tell the difference between 192kbps and 128kbps AAC. For voice-only content (tutorials, podcasts, screencasts), you can go as low as 64kbps:

ffmpeg -i input.mp4 -c:v libx264 -crf 23 -c:a aac -b:a 64k output.mp4

If the video doesn't need audio at all, strip it entirely:

ffmpeg -i input.mp4 -c:v libx264 -crf 23 -an output.mp4

The -an flag removes all audio tracks.

Common Gotchas with FFmpeg Video Compression

CRF values mean different things for different codecs. CRF 23 in H.264 and CRF 23 in H.265 produce very different quality levels. Always test with your actual content before committing to a value.

Hardware encoding (NVENC, VideoToolbox) trades quality for speed. GPU encoders are 5-10x faster but produce larger files at the same perceived quality. Use them for real-time encoding. Use software encoders (libx264, libx265) when file size matters.

Don't re-encode already compressed video. Each re-encode loses quality. If your source is already H.264 at a reasonable bitrate, compressing it again will make it worse. Check the source bitrate first:

ffmpeg -i input.mp4

Look for the bitrate in the output. If it's already under 2000 kbps for 1080p, you don't have much room to compress further without visible degradation.

Container format matters. MP4 is universally supported. WebM is smaller but limited to VP8/VP9/AV1 codecs. MKV is flexible but not supported natively in browsers.

Compress Video with the FFmpeg Micro API

If you don't want to manage FFmpeg on your own servers, you can offload compression to FFmpeg Micro with a single API call. Send your video URL and the encoding options you want:

curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": [{"url": "https://example.com/large-video.mp4"}],
    "outputFormat": "mp4",
    "options": [
      {"option": "-c:v", "argument": "libx264"},
      {"option": "-crf", "argument": "23"},
      {"option": "-preset", "argument": "slow"},
      {"option": "-c:a", "argument": "aac"},
      {"option": "-b:a", "argument": "128k"}
    ]
  }'

Same FFmpeg power, no server setup. You get back a job ID, poll for status, and download the compressed result. FFmpeg Micro is a cloud API that lets you add video processing to any app with a single HTTP call. No FFmpeg installation, no server management. It handles scaling whether you're compressing 1 video or 1,000.

For simpler cases, skip the manual options and use a preset:

curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inputs": [{"url": "https://example.com/large-video.mp4"}],
    "outputFormat": "mp4",
    "preset": {"quality": "medium", "resolution": "1080p"}
  }'

The medium quality preset maps to CRF 23 with sensible defaults for web delivery. For a deeper dive on transcoding options, see the FFmpeg Micro docs.

FAQ

Does CRF 0 in FFmpeg mean no compression?

CRF 0 produces a lossless encode. The file will be huge, often larger than the original if the source was in a different codec. For practical purposes, CRF 18 is "visually lossless" and dramatically smaller.

Can I compress video without re-encoding?

You can't reduce quality-based file size without re-encoding. But you can strip unnecessary streams (subtitles, extra audio tracks) or remux to a more efficient container using -c copy, which is instant and lossless.

What CRF value should I use for YouTube uploads?

YouTube re-encodes everything anyway, so upload at the highest quality you can. CRF 18 with -preset slow gives YouTube the best source material to work with. Don't over-compress before upload.

How much can FFmpeg reduce video file size?

With CRF 23 and H.264, expect 50-80% size reduction from uncompressed or lightly compressed source video. Switching to H.265 or AV1 can cut another 25-50% on top of that. Results vary based on content complexity. Talking-head videos compress better than action footage.

Is two-pass encoding better than CRF?

They solve different problems. CRF targets consistent quality (file size varies). Two-pass targets a specific file size (quality varies). For most use cases, CRF is simpler and produces better results. Use two-pass only when you have a hard file size constraint.

Ready to process videos at scale?

Start using FFmpeg Micro's simple API today. No infrastructure required.

Get Started Free