Want to convert 60fps footage to 30fps for the web, get a cinematic 24fps feel, or create a timelapse? FFmpeg’s fps filter handles all of these in a single command. Understanding the difference between -vf fps and -r lets you get stable results even with variable frame rate source material. Time to complete: 10 minutes.

Tested with: FFmpeg 6.1 (ubuntu-latest / GitHub Actions CI-validated)


What You Will Learn

  1. How to check frame rate with ffprobe
  2. The -r option vs the fps filter — differences and when to use each
  3. Decreasing frame rate (60 → 30fps, etc.)
  4. Increasing frame rate (24 → 60fps)
  5. Commands for common use cases
  6. Timelapse creation
  7. Five common errors and fixes
  8. Five frequently asked questions

First: Check the Current Frame Rate

Before converting, check the source file’s frame rate.

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
FieldMeaning
r_frame_rateFrame rate stored in container metadata (nominal value)
avg_frame_rateAverage frame rate calculated from actual frame count

For variable frame rate (VFR) video these values may differ. 60000/1001 ≈ 59.94fps (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 — target frame rate; drops excess frames based on timestamps
  • -c:a copy — copy 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. Fine for simple cases, but the fps filter is more stable with VFR source material.

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

When increasing frame rate, the fps filter achieves the target by duplicating existing frames — no new intermediate frames are generated. True motion interpolation requires the minterpolate filter.

4. Timelapse: Extract at 1fps

# Extract one frame per second — creates ultra-low-frame-rate video
ffmpeg -i input.mp4 -vf fps=1 -an -c:v libx264 -crf 23 output_timelapse.mp4
  • -an — remove audio (audio would be out of sync with the shortened video)

5. Build Timelapse from Image Sequence

ffmpeg -framerate 1 -i img%03d.png -c:v libx264 -r 30 -pix_fmt yuv420p output.mp4
  • -framerate 1 — read input images at 1fps (1 image = 1 second)
  • -r 30 — output at 30fps (each image becomes 30 frames)
  • -pix_fmt yuv420p — pixel format for broad compatibility

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 timingImmediately before encodingWithin the filter graph (earlier stage)
Timestamp referenceLimitedReferences frame timestamps
VFR source stabilityMay be unstableMore stable conversion
Combining with filtersPossibleIntegrates into filter chain
Recommended forSimple CFR sourcesVFR sources, precise control

Recommendation: When in doubt, use -vf fps=N. It’s especially effective for VFR sources (smartphone footage, OBS recordings, etc.).


Common Frame Rate Reference

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

Option Reference

OptionMeaningRecommended Value
-vf fps=NConvert frame rate in filter graph24 / 30 / 60
-r NSet output frame rate (before encoding)Simple CFR conversion
-framerate NRead speed for input image sequenceTimelapse creation
-pix_fmt yuv420pPixel format specificationRequired for broad compatibility
-c:a copyLossless audio copyAlways recommended for frame rate changes

Troubleshooting

Problem 1: Audio Is Out of Sync After Conversion

Symptom: Video and audio timing is misaligned after conversion
Cause: Converting VFR source with -r can cause audio timestamp drift when frames are dropped or duplicated
Fix:

# Use fps filter instead — more stable
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: Video is short but audio runs for the original duration
Cause: fps=1 shortens the video but leaves audio unchanged
Fix: Remove audio for timelapse:

ffmpeg -i input.mp4 -vf fps=1 -an -c:v libx264 -crf 23 output.mp4

Problem 3: No such encoder libx264

Cause: FFmpeg was built without libx264 support
Fix: Install the full-featured FFmpeg:

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

Problem 4: Output Frame Rate Didn’t Change

Cause: -r was placed on the input side (before -i) instead of the output side
Fix: Always place 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 (pts has no value)

Cause: Missing -framerate flag, or the filename pattern doesn’t match
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. Use -vf fps=N when in doubt. It references timestamps and produces stable results especially with VFR sources like smartphone or OBS recordings. Use -r for simple, constant frame rate sources.

Q2. Does increasing the frame rate make motion smoother?
A. No — the fps filter duplicates existing frames. Motion smoothness stays the same as the original. For genuine interpolation (generating new in-between frames via motion estimation), use the minterpolate filter — but it’s significantly 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. Technically yes, but the audio won’t sync with the shortened video. The practical approach is to remove audio (-an) and add background music separately in post-production.

Q5. Can I specify fractional frame rates like 29.97fps?
A. Yes — use the rational form:

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


Tested with: ffmpeg 6.1.1 / Ubuntu 24.04 (GitHub Actions runner)
Primary sources: ffmpeg.org/ffmpeg.html / ffmpeg.org/ffmpeg-filters.html / ffmpeg.org/ffmpeg-codecs.html