“I sped up my clip 2× and the audio is still at 1×.” “Slow-mo looks choppy.” “atempo=3.0 errors out.” Changing playback speed sounds trivial but is full of audio-sync traps. The correct FFmpeg approach is to combine video-side setpts and audio-side atempo with matching ratios. This guide covers every speed from 0.25× to 10×, pitch preservation, and per-section variable speed — all with copy-pasteable commands. Time to complete: 12 minutes.
Tested with: FFmpeg 8.1 (Windows / macOS / Linux)
What You’ll Learn
- How
setptsandatemporelate (mind the coefficient direction) - Speed up commands (2×, 4×, 10×) with audio kept in sync
- Slow down commands (0.5×, 0.25×)
atempolimits (0.5–100) and the chained workaround for old builds- Speeding up video only with
-an - Pitch-preserving speed change via the
rubberbandfilter - Per-time-range variable speed
- Smooth slow-mo via
minterpolate - Troubleshooting and FAQ
Speed Basics: setpts and atempo
FFmpeg changes speed by editing the video presentation timestamps and the audio tempo independently. Get the direction wrong and you’ll desync.
| Stream | Filter | Coefficient meaning | Example (2× speed) |
|---|---|---|---|
| Video | setpts=N*PTS | Smaller = faster (compresses PTS) | setpts=0.5*PTS |
| Audio | atempo=N | Larger = faster (playback multiplier) | atempo=2.0 |
Important: the setpts coefficient is the reciprocal of the playback multiplier. To play 2× as fast, halve the PTS (0.5*PTS); to play half-speed, double the PTS (2*PTS). atempo, by contrast, takes the multiplier directly.
Speed / coefficient cheat sheet
| Playback speed | setpts coefficient | atempo coefficient |
|---|---|---|
| 0.25× (4× slow) | 4*PTS | 0.5,atempo=0.5 (or 0.25) |
| 0.5× (2× slow) | 2*PTS | 0.5 |
| 1.0× (normal) | 1*PTS | 1.0 |
| 2.0× (fast) | 0.5*PTS | 2.0 |
| 4.0× | 0.25*PTS | 4.0 |
| 10.0× | 0.1*PTS | 10.0 |
Since FFmpeg 4.2, a single
atempoinstance accepts 0.5–100×. Older builds cap at 0.5–2.0, so chain withatempo=2.0,atempo=2.0(covered below).
Speed Up (2×, 4×, 10×)
2× speed (with synced audio)
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
-map "[v]" -map "[a]" output_2x.mp4
setpts=0.5*PTS compresses video timestamps to half, and atempo=2.0 doubles audio tempo. Without -map "[v]" -map "[a]", the filter_complex outputs may be ignored and you’ll get silent video.
4× speed
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.25*PTS[v];[0:a]atempo=4.0[a]" \
-map "[v]" -map "[a]" output_4x.mp4
A 20-second clip becomes 5 seconds. atempo=4.0 works directly on FFmpeg 4.2+.
10× speed
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.1*PTS[v];[0:a]atempo=10.0[a]" \
-map "[v]" -map "[a]" output_10x.mp4
10× is great for surveillance digests and timelapse-like summaries. Speech becomes unintelligible at this tempo, so dropping audio with -an is usually the right call.
Slow Down (0.5×, 0.25×)
0.5× (half speed)
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=2*PTS[v];[0:a]atempo=0.5[a]" \
-map "[v]" -map "[a]" output_half.mp4
setpts=2*PTS doubles each frame’s display duration, and atempo=0.5 halves audio tempo.
0.25× (4× slow)
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=4*PTS[v];[0:a]atempo=0.5,atempo=0.5[a]" \
-map "[v]" -map "[a]" output_quarter.mp4
Chaining atempo=0.5 twice yields 0.25×. On FFmpeg 4.2+ you can also write atempo=0.25 directly, but chaining is the safe portable form.
Slow-mo choppiness:
setptsonly stretches time — it does not generate new frames. A 30fps source slowed to 0.25× has effective 7.5fps and looks choppy. See theminterpolatesection below for true frame interpolation.
atempo Limits and Workarounds
A single atempo instance accepts:
| FFmpeg version | Single-instance range | Practical range with chaining |
|---|---|---|
| 4.1 and older | 0.5 – 2.0 | Any ratio via chaining |
| 4.2 and newer | 0.5 – 100.0 | Single instance usually enough |
0.25× on old FFmpeg without atempo=0.25
# Wrong: atempo=0.25 errors on FFmpeg 4.1 and older
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=4*PTS[v];[0:a]atempo=0.25[a]" \
-map "[v]" -map "[a]" output_bad.mp4
# Correct: chain two 0.5 instances → 0.25
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=4*PTS[v];[0:a]atempo=0.5,atempo=0.5[a]" \
-map "[v]" -map "[a]" output_quarter_safe.mp4
8× on old FFmpeg
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.125*PTS[v];[0:a]atempo=2.0,atempo=2.0,atempo=2.0[a]" \
-map "[v]" -map "[a]" output_8x.mp4
Chain three atempo=2.0 for 2 × 2 × 2 = 8×. The product of all coefficients must equal the target multiplier.
Speed Up Video Only
For silent timelapses or surveillance speed-ups, skipping audio simplifies the command.
ffmpeg -i input.mp4 -vf "setpts=0.25*PTS" -an output_4x_silent.mp4
-an— drop the audio stream-vf— for a single-video pipeline,-vfis enough; you don’t needfilter_complex
# Slow with no audio
ffmpeg -i input.mp4 -vf "setpts=2*PTS" -an output_slow_silent.mp4
If you want to keep the original audio (and accept the desync), use -c:a copy. This produces a video shorter or longer than the audio track.
Pitch-Preserving Speed Change (rubberband)
Plain atempo resamples audio, which makes 3× speech sound like a chipmunk. To change tempo while preserving pitch, use the rubberband filter.
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]rubberband=tempo=2.0[a]" \
-map "[v]" -map "[a]" output_2x_pitch_keep.mp4
rubberband=tempo=2.0 doubles tempo while keeping the original pitch. Ideal for interviews, lectures, and anything where intelligibility matters.
# Pitch-keeping slow-mo (no chipmunk reverse)
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=2*PTS[v];[0:a]rubberband=tempo=0.5[a]" \
-map "[v]" -map "[a]" output_half_pitch_keep.mp4
rubberbandrequires an FFmpeg build with--enable-librubberband. Use gyan.dev’s full build on Windows,brew install ffmpegon macOS, or the official PPA on Ubuntu. Check withffmpeg -filters | grep rubberband.
Variable-Speed Sections
“First 5 seconds slow, then normal speed” is doable two ways.
Option 1: setpts expression with a time conditional (video only)
ffmpeg -i input.mp4 -vf "setpts='if(lt(T,5),2,1)*PTS'" -an output_var.mp4
T is the output frame’s timestamp in seconds. if(lt(T,5),2,1) evaluates to 2 when T<5 and 1 otherwise — slowing the first 5 seconds (2× PTS) and keeping the rest at normal speed.
Option 2: trim + setpts + concat (audio supported)
ffmpeg -i input.mp4 -filter_complex \
"[0:v]trim=0:5,setpts=2*PTS[v1];[0:a]atrim=0:5,asetpts=PTS-STARTPTS,atempo=0.5[a1]; \
[0:v]trim=5:20,setpts=PTS-STARTPTS[v2];[0:a]atrim=5:20,asetpts=PTS-STARTPTS[a2]; \
[v1][a1][v2][a2]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" output_var_audio.mp4
trim / atrim carve out time ranges, each is sped up independently, then concat stitches them. Use this when audio sync matters. Variable speed is fiddly — start with the -an version, confirm the visual cuts, then add audio.
Smooth Slow-Mo with Frame Interpolation
setpts=2*PTS alone just stretches existing frames; the frame count doesn’t grow. The minterpolate filter generates intermediate frames from motion vectors for genuine smooth slow-mo.
ffmpeg -i input.mp4 -vf "setpts=4*PTS,minterpolate=fps=60:mi_mode=mci" -an output_smooth_slow.mp4
setpts=4*PTS— 4× slowminterpolate=fps=60— output frame rate of 60fpsmi_mode=mci— Motion Compensated Interpolation (synthetic in-between frames)
mi_mode | Meaning | Use case |
|---|---|---|
dup | Duplicate frames only | Fast, low quality |
blend | Cross-fade blend | Mid quality, light |
mci | Motion-compensated (recommended) | High-quality slow-mo |
minterpolateis CPU-heavy — HD video can be tens of times slower than real time. For long clips, use-ss/-toto crop to the relevant section first.
Re-encode After Speed Change
Speed change already triggers re-encoding, so it’s a natural place to optimise codec settings.
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
-map "[v]" -map "[a]" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output_optimized.mp4
-crf 23— standard quality (18–28 is the practical range, lower = better)-preset medium— balanced speed/compression-c:a aac -b:a 128k— common AAC 128kbps audio
Use -c:v libx265 -crf 28 if you need smaller files via H.265.
Troubleshooting
1. Only the audio (or only the video) sped up
Cause: you only wrote setpts or only atempo, or the -map was missing.
# Wrong: video sped up but audio still 1× — total length mismatches
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output_bad.mp4
# Correct: both sides processed via filter_complex, mapped explicitly
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
-map "[v]" -map "[a]" output_ok.mp4
2. “Value 3.000000 for parameter ‘tempo’ out of range”
Cause: FFmpeg 4.1 or older with atempo above 2.0.
Fix: upgrade FFmpeg, or chain like atempo=2.0,atempo=1.5 (product = 3.0).
3. Slight lipsync drift between audio and video
Cause: the setpts and atempo coefficients are not exact reciprocals of each other.
Fix: keep setpts=N*PTS and atempo=1/N strictly inverse — 0.5*PTS ↔ atempo=2.0, 0.333*PTS ↔ atempo=3.0.
4. Slow-mo looks choppy
Cause: setpts stretches existing frames without adding new ones, dropping effective fps.
Fix: chain minterpolate=fps=60:mi_mode=mci after setpts (see above).
5. Output duration looks wrong
Cause: concat segments lack a timestamp reset, or -shortest is missing.
Fix: insert setpts=PTS-STARTPTS / asetpts=PTS-STARTPTS inside each segment to zero the time origin.
FAQ
Q1. Why does only the video (or only the audio) end up sped up?
A. -vf does not touch audio. Use -filter_complex with separate video and audio chains, then map both with -map "[v]" -map "[a]". If you prefer -vf, pair it with -af "atempo=N" to handle audio.
Q2. 10× speed sounds broken — is that normal?
A. Yes — atempo=10.0 produces noisy speech. For intelligible voice, prefer rubberband=tempo=10, but anything above 5× is barely useful. For fast-forward previews, drop audio with -an.
Q3. My slow-motion is choppy. What’s wrong?
A. Nothing — setpts only stretches time without producing new frames. A 30fps source at 0.25× has effective 7.5fps. Add minterpolate=fps=60:mi_mode=mci to synthesize true intermediate frames.
Q4. Can I switch codecs in the same command after speed change?
A. Yes. Speed change always re-encodes, so simply add -c:v libx264 -crf 23 -c:a aac -b:a 128k (or your codec of choice) to the same command. Filters and output codecs are independent options.
Q5. Can I slow down an iPhone slow-mo clip even further?
A. Yes. iPhone slow-mo records at 240fps internally, so setpts=2*PTS still leaves you with effective 120fps — plenty of smoothness. Run ffprobe -show_streams to confirm r_frame_rate before picking a multiplier.
Q6. Will embedded subtitles stay in sync after a speed change?
A. Hard subs (burned in) re-encode with the video and stay aligned automatically. Soft subs are a separate stream and need manual re-timing via -itsoffset or PTS adjustment.
Related Articles
- FFmpeg Change Frame Rate — -r vs fps Filter: Which to Use and When
- Fix Audio/Video Sync with FFmpeg — itsoffset, adelay, async Complete Guide
Tested with ffmpeg 8.1 / Windows 11 + Ubuntu 24.04
Primary source: ffmpeg.org/ffmpeg-filters.html#setpts / ffmpeg.org/ffmpeg-filters.html#atempo