mediacodec.dev

Change a video’s frame rate

Screen recordings and game captures ship at 60fps that nothing downstream needs. Capping the rate drops frames, and with them a large slice of the bitrate, before the encoder even starts. The subtlety is where you say it: the fps filter and the -r flag sound alike and behave differently.

Target rate

fps=

The web delivery workhorse. From 60fps, every second frame is simply dropped.

Halving 60fps to 30 keeps motion smooth for screen content and talking heads; film-style 24 reads as deliberate; 15 is a preview economy.

Quality (CRF)

-crf
bettersmaller20

CRF 20: high-quality delivery.

Dropping frames means re-encoding the survivors. x264’s 0–51 scale; 18–23 is the useful range.

Your command

ffmpeg -i input.mp4 -vf fps=30 \
  -c:v libx264 -crf 20 \
  -preset medium -c:a copy \
  output.mp4

Worth knowing

The fps filter drops or duplicates frames to hit the target exactly, keeping audio sync intact. Prefer it over -r for output rate changes.

-r before -i reinterprets the input clock instead: the same frames play faster or slower, and the audio drifts. A classic footgun.

Frame rate only helps file size because fewer frames need bits; at the same CRF the saving is real but less than proportional, since the surviving frames now differ more from each other.

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.

Mediabunny’s frameRate option does the fps filter’s job: frames are dropped to hit the target, audio timing untouched.

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

Waiting on a file.