mediacodec.dev

Compress a video

The single most common FFmpeg job. The right way to shrink a video is not to pick a bitrate, it is to pick a quality: CRF mode spends bits where the picture needs them and saves them where it does not, and the file lands as small as that quality allows.

Codec

-c:v

libx264: plays on effectively every device made this century. The compatibility king.

Newer codecs pack the same quality into fewer bits, at the price of encode time and playback reach. If the file must play anywhere, H.264 is still the safe answer.

Quality (CRF)

-crf
bettersmaller23

CRF 23: H.264's default, chosen by its authors as the sweet spot for most content.

Each codec reads the number on its own scale: x264 and x265 run 0–51 (defaults 23 and 28), SVT-AV1 runs 0–63 (35 is a sane middle). A step of ±6 roughly halves or doubles the file size.

Encode speed

-preset

The default, and a sane one.

Slower presets search harder for savings: the file gets smaller at the same CRF, but the encode takes longer. Quality does not change; size does.

Your command

ffmpeg -i input.mp4 \
  -c:v libx264 -crf 23 \
  -preset medium -c:a copy \
  output.mp4

Worth knowing

-c:a copy passes the audio through untouched: audio is rarely worth re-encoding when the goal is a smaller video.

For H.265 in MP4, -tag:v hvc1 is the difference between a file QuickTime and Safari will play and one they will not. FFmpeg defaults to the other tag.

CRF numbers are not comparable across codecs: x265 at 28 and x264 at 23 target roughly similar quality, on different scales.

Run this on your own file

no FFmpeg · runs in this tab

The command above needs FFmpeg on a machine. The settings it encodes do not: your browser can perform the same operation on a real file, right here, through WebCodecs.

Drop a video or audio file here, or

Files are processed in this tab and never uploaded.

WebCodecs has no CRF, so -crf 23 becomes a bitrate target for the output resolution, using the rule that every 6 CRF steps halve or double the size.

Encoder presets are not exposed through WebCodecs; your encoder picks its own speed trade-off.

Audio passes through untouched when the container allows it, matching -c:a copy.

Waiting on a file.