To change a video’s frame rate, for example from 60fps to 30fps for the web or to 24fps for a film look, use FFmpeg’s fps filter. Together with setpts, it also makes timelapses. The -r option can change the frame rate too.

First: Check the Current Frame Rate

Check the frame rate of the source file before you convert it.

ffprobe -v error -select_streams v:0 \
  -show_entries stream=r_frame_rate,avg_frame_rate \
  -of default=noprint_wrappers=1 input.mp4

Example output:

r_frame_rate=60000/1001
avg_frame_rate=60000/1001
Field Meaning
r_frame_rate Base frame rate that FFmpeg guesses for the stream (the lowest rate that can represent all timestamps)
avg_frame_rate Average frame rate calculated from actual frame count

For variable frame rate (VFR) video, the two values can differ. 60000/1001 is about 59.94fps (the NTSC standard).

Command Examples

# 60fps → 30fps (web delivery, social media)
ffmpeg -i input.mp4 -vf fps=30 -c:v libx264 -crf 23 -c:a copy output.mp4

# 29.97fps → 25fps (PAL standard, Europe)
ffmpeg -i input.mp4 -vf fps=25 -c:v libx264 -crf 23 -c:a copy output.mp4

# 30fps → 24fps (cinematic look)
ffmpeg -i input.mp4 -vf fps=24 -c:v libx264 -crf 23 -c:a copy output.mp4
  • fps=N — the target frame rate; extra frames are dropped based on their timestamps
  • -c:a copy — copy the audio without re-encoding (fast, lossless)

2. Use the -r Option (for simple cases)

# Set output frame rate to 30fps
ffmpeg -i input.mp4 -r 30 -c:v libx264 -crf 23 -c:a copy output.mp4

-r duplicates or drops frames immediately before encoding. The fps filter also duplicates or drops frames based on their timestamps, but it works inside the filter graph, so you can chain it with other filters such as scale.

3. Increase Frame Rate (frame duplication)

# 24fps → 60fps (frame duplication)
ffmpeg -i input.mp4 -vf fps=60 -c:v libx264 -crf 23 -c:a copy output.mp4

To raise the frame rate, the fps filter duplicates existing frames. It does not create new in-between frames. For real motion interpolation, use the minterpolate filter.

4. Timelapse: Speed Up 30×

# 30x timelapse (60 seconds -> 2 seconds, no audio)
ffmpeg -i input.mp4 -vf "setpts=PTS/30,fps=30" -an -c:v libx264 -crf 23 output_timelapse.mp4
  • setpts=PTS/30 — shrink time to 1/30 (30× speed)
  • fps=30 — output 30fps (the extra frames are dropped)
  • -an — remove the audio (it would be out of sync with the shortened video)

-vf fps=1 on its own only gives a choppy video with one frame per second, at the same length (a 60-second clip stays 60 seconds). To speed it up, shrink the time with setpts.

5. Build a Video from an Image Sequence

ffmpeg -framerate 1 -i img%03d.png -c:v libx264 -r 30 -pix_fmt yuv420p output.mp4
  • -framerate 1 — read the input images at 1fps (1 image = 1 second, a slideshow; for a timelapse use more images per second, such as -framerate 30)
  • -r 30 — output at 30fps (each image becomes 30 frames)
  • -pix_fmt yuv420p — a pixel format that most players support

6. Batch Convert All Videos in a Folder to 30fps

for f in *.mp4; do
  ffmpeg -i "$f" -vf fps=30 -c:v libx264 -crf 23 -c:a copy "30fps_${f}" -y
done

-r Option vs fps Filter Comparison

Comparison -r (output option) -vf fps=N (filter)
Processing timing Immediately before encoding Within the filter graph (earlier stage)
Timestamp reference Duplicates/drops by timestamp Duplicates/drops by timestamp
VFR sources Output is CFR; check the result Output is CFR; check the result
Combining with filters Possible Integrates into filter chain
Recommended for Simple conversions Conversions combined with other filters

If you are unsure, use -vf fps=N. It goes in the same -vf chain as your other filters. Both methods turn VFR sources (smartphone footage, OBS recordings and so on) into CFR (constant frame rate), but check the length and audio sync afterwards.

Common Frame Rate Reference

fps Use Case
24 / 23.976 Film standard — cinematic feel
25 PAL standard (Europe, Middle East, parts of Asia)
29.97 / 30 NTSC standard (Japan, North America), web video
50 High frame rate PAL
59.94 / 60 Gaming, sports, high-quality web video
120 Latest smartphones, high-speed recording

Option Reference

Option Meaning Recommended Value
-vf fps=N Convert frame rate in filter graph 24 / 30 / 60
-r N Set output frame rate (before encoding) Simple CFR conversion
-framerate N Read speed for input image sequence Timelapse creation
-pix_fmt yuv420p Pixel format specification Required for broad compatibility
-c:a copy Lossless audio copy Always recommended for frame rate changes

Troubleshooting

Problem 1: Audio Is Out of Sync After Conversion

Symptom: After the conversion, the video and audio don’t line up
Cause: -r was put before -i, which re-times the video but not the audio (see Problem 4). After -i, both -r and the fps filter only drop or duplicate frames by their timestamps. They do not move the audio, so they keep the sync of the source
Fix:

# Set the frame rate after -i, then check the length and audio sync
ffmpeg -i input.mp4 -vf fps=30 -c:v libx264 -crf 23 -c:a copy output.mp4

Problem 2: Timelapse Has Audio That’s Too Long

Symptom: The video is short, but the audio plays for the original length
Cause: setpts shortens only the video; the audio keeps its original length
Fix: Remove the audio from the timelapse:

ffmpeg -i input.mp4 -vf "setpts=PTS/30,fps=30" -an -c:v libx264 -crf 23 output.mp4

Problem 3: Unknown encoder 'libx264'

Cause: FFmpeg was built without libx264 support
Fix: Install an FFmpeg build that includes it:

sudo apt install ffmpeg        # Ubuntu/Debian
brew install ffmpeg            # macOS

Problem 4: Output Became Longer and Plays in Slow Motion

Cause: -r was put before -i (on the input side) instead of after it. As an input option, -r ignores the file’s timestamps and re-times every frame at the given rate. So -r 30 on a 60fps clip makes it twice as long (slow motion), while the audio keeps its original length
Fix: Put frame rate options after -i:

# Wrong (input-side -r)
ffmpeg -r 30 -i input.mp4 output.mp4

# Correct (output-side)
ffmpeg -i input.mp4 -vf fps=30 -c:v libx264 -crf 23 output.mp4

Problem 5: Image Sequence Fails to Load (Could find no file or sequence with path ...)

Cause: The file name pattern (such as the number of digits in %03d) or the start number doesn’t match the actual files. If the numbering doesn’t start between 0 and 4, set the first number with -start_number. A missing -framerate does not cause this error; the images are then read at 25fps
Fix:

# Check file naming pattern first
ls img*.png | head -3
# Example: img001.png img002.png img003.png → use %03d
ffmpeg -framerate 24 -i img%03d.png -c:v libx264 -pix_fmt yuv420p output.mp4

FAQ

Q1. Should I use -r or -vf fps=N?
A. If you are unsure, use -vf fps=N; it chains with your other filters. -r also duplicates or drops frames by timestamp, so for simple conversions the results are nearly the same. With VFR sources such as smartphone or OBS recordings, check the length and audio sync whichever you use.

Q2. Does increasing the frame rate make motion smoother?
A. No. The fps filter duplicates existing frames, so motion looks the same as in the original. For real interpolation (new in-between frames made by motion estimation), use the minterpolate filter. It is much slower.

Q3. How do I verify the output frame rate after conversion?

ffprobe -v error -select_streams v:0 \
  -show_entries stream=avg_frame_rate \
  -of default=noprint_wrappers=1 output.mp4

Q4. Can I keep audio in a timelapse?
A. You can, but the audio won’t match the shortened video. Usually it is better to remove the audio (-an) and add background music separately afterwards.

Q5. Can I specify fractional frame rates like 29.97fps?
A. Yes. Use the fraction form:

# 29.97fps (NTSC)
ffmpeg -i input.mp4 -vf fps=30000/1001 -c:v libx264 -crf 23 output.mp4