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
- How to check frame rate with ffprobe
- The
-roption vs thefpsfilter — differences and when to use each - Decreasing frame rate (60 → 30fps, etc.)
- Increasing frame rate (24 → 60fps)
- Commands for common use cases
- Timelapse creation
- Five common errors and fixes
- 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
| Field | Meaning |
|---|---|
r_frame_rate | Frame rate stored in container metadata (nominal value) |
avg_frame_rate | Average 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
1. Decrease Frame Rate (fps filter — recommended)
# 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
fpsfilter achieves the target by duplicating existing frames — no new intermediate frames are generated. True motion interpolation requires theminterpolatefilter.
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 timing | Immediately before encoding | Within the filter graph (earlier stage) |
| Timestamp reference | Limited | References frame timestamps |
| VFR source stability | May be unstable | More stable conversion |
| Combining with filters | Possible | Integrates into filter chain |
| Recommended for | Simple CFR sources | VFR 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
| 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: 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
Related Articles
- Scale and Resize Video — scale Filter Guide
- Create Slideshow and Timelapse Videos
- Video Compression Complete Guide — CRF, Bitrate, and Presets
- FFmpeg Command Basic Syntax — Inputs, Filters, and Outputs
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