“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

  1. How setpts and atempo relate (mind the coefficient direction)
  2. Speed up commands (2×, 4×, 10×) with audio kept in sync
  3. Slow down commands (0.5×, 0.25×)
  4. atempo limits (0.5–100) and the chained workaround for old builds
  5. Speeding up video only with -an
  6. Pitch-preserving speed change via the rubberband filter
  7. Per-time-range variable speed
  8. Smooth slow-mo via minterpolate
  9. 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.

StreamFilterCoefficient meaningExample (2× speed)
Videosetpts=N*PTSSmaller = faster (compresses PTS)setpts=0.5*PTS
Audioatempo=NLarger = 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 speedsetpts coefficientatempo coefficient
0.25× (4× slow)4*PTS0.5,atempo=0.5 (or 0.25)
0.5× (2× slow)2*PTS0.5
1.0× (normal)1*PTS1.0
2.0× (fast)0.5*PTS2.0
4.0×0.25*PTS4.0
10.0×0.1*PTS10.0

Since FFmpeg 4.2, a single atempo instance accepts 0.5–100×. Older builds cap at 0.5–2.0, so chain with atempo=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: setpts only stretches time — it does not generate new frames. A 30fps source slowed to 0.25× has effective 7.5fps and looks choppy. See the minterpolate section below for true frame interpolation.


atempo Limits and Workarounds

A single atempo instance accepts:

FFmpeg versionSingle-instance rangePractical range with chaining
4.1 and older0.5 – 2.0Any ratio via chaining
4.2 and newer0.5 – 100.0Single 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, -vf is enough; you don’t need filter_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

rubberband requires an FFmpeg build with --enable-librubberband. Use gyan.dev’s full build on Windows, brew install ffmpeg on macOS, or the official PPA on Ubuntu. Check with ffmpeg -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× slow
  • minterpolate=fps=60 — output frame rate of 60fps
  • mi_mode=mci — Motion Compensated Interpolation (synthetic in-between frames)
mi_modeMeaningUse case
dupDuplicate frames onlyFast, low quality
blendCross-fade blendMid quality, light
mciMotion-compensated (recommended)High-quality slow-mo

minterpolate is CPU-heavy — HD video can be tens of times slower than real time. For long clips, use -ss / -to to 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*PTSatempo=2.0, 0.333*PTSatempo=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.



Tested with ffmpeg 8.1 / Windows 11 + Ubuntu 24.04
Primary source: ffmpeg.org/ffmpeg-filters.html#setpts / ffmpeg.org/ffmpeg-filters.html#atempo