FFmpeg change frame rate: the fps filter vs -r

Change a video's frame rate with FFmpeg's fps filter: -vf fps=30 drops or duplicates frames and keeps the running time. How -r and framerate differ.

5 min readSume
All posts

To change a video's frame rate with FFmpeg, use the fps filter: ffmpeg -i input.mp4 -vf fps=30 -c:a copy output.mp4. It converts the video to a constant 30 frames per second by duplicating or dropping frames, so the running time stays the same and the copied audio stays in sync. -r 30 as an output option also drops or duplicates frames, right before encoding.

The FFmpeg behavior below is quoted from the FFmpeg filters documentation and the ffmpeg documentation, and the Sume facts come from the Video filter, Video trim, and Timeline 1.0 docs, all read on 2026-09-29. The commands were run on a 4-second, 60 fps test clip.

What is the difference between -r and the fps filter?

Both give a constant output rate by dropping or duplicating frames. The fps filter does it inside the filtergraph, where you choose its place among other filters. -r depends on where it sits and what the stream does:

  • As an output option on an encoded stream, -r duplicates or drops frames right before encoding them.
  • On a stream copy (-c copy), -r only tells the muxer the rate: nothing is dropped or duplicated, and the docs warn this may produce invalid files if it doesn't match the real timestamps. Changing the frame rate needs a re-encode.
  • As an input option (before -i), -r ignores the file's timestamps and assumes a constant rate, which changes timing rather than converting it. If in doubt, the docs say, use -framerate instead of the input option -r.
  • -fps_mode cfr duplicates and drops frames to reach exactly the requested constant rate; the default, auto, picks between cfr and vfr for the muxer.

How do I convert 60 fps to 30, or 23.976 to 24?

Give fps the target as a number, a fraction, or an abbreviation. 23.976 is really 24000/1001, so use the fraction or ntsc_film rather than a rounded decimal; 23.976 vs 24 fps explains the difference. Going from 23.976 to 24, or back, only adds or drops a frame now and then.

From the fps filter and -r option in the FFmpeg filters documentation and ffmpeg documentation, read 2026-09-29. Output rates checked with ffprobe.
GoalFilterOutput rate
60 fps to 30fps=3030/1
To NTSC film (23.976)fps=ntsc_film or fps=24000/100124000/1001
To film (24)fps=film or fps=2424/1
To PAL (25)fps=pal or fps=2525/1
To NTSC (29.97)fps=ntsc30000/1001
# 60 fps to 30 fps; audio copied, running time unchanged
ffmpeg -i input.mp4 -vf fps=30 -c:a copy output.mp4

# 23.976 fps, written as the exact fraction
ffmpeg -i input.mp4 -vf fps=24000/1001 -c:a copy output.mp4

# Blend frames instead of repeating them
ffmpeg -i input.mp4 -vf framerate=fps=50 -c:a copy output.mp4

Can FFmpeg blend frames instead of repeating them?

Yes, with the framerate filter, which the docs say changes the rate "by interpolating new video output frames from the source frames". It builds some output frames as a linear interpolation of two source frames, detects scene changes by default, and isn't designed for interlaced video: deinterlace first. Its default target is 50 fps. The fps filter never blends; it only repeats or removes whole frames.

Can I change a video's frame rate with Sume?

Yes, for a file already in your workspace on media.sume.com, such as an earlier Sume job's output. fps and framerate are on the allowlist of Sume's video filter, so "filtergraph": "fps=30" runs the same conversion on a clip of up to 300 seconds, and each encode job reserves $0.02. Video trim and Timeline 1.0 also take an output.fps of 24, 25, 30, or 60; change a video's frame rate or resolution with the Sume API covers each call.

curl -X POST https://api.sume.com/v1/video-filter \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: fps-30-001" \
  -d '{
    "video_url": "https://media.sume.com/artifacts/artf_demo/talk.mp4",
    "filtergraph": "fps=30"
  }'

Sources

Related posts

More in Developers

All Developers posts

Written by Sume