TechEarl

How to Speed Up or Slow Down a Video with ffmpeg

Change a video's speed from the command line with ffmpeg: setpts for the video, atempo for the audio, why you still chain atempo in steps of 2.0 even though it now accepts up to 100, and keeping both tracks in sync.

Ishan Karunaratne⏱️ 8 min readUpdated
Share thisCopied
Speed up or slow down a video with ffmpeg using the setpts video filter and the atempo audio filter, including the atempo 0.5 to 100 range and why you still chain it in steps of 2.0 for larger factors.

To double a video's speed, scale the presentation timestamps with setpts and drop the audio:

bash
ffmpeg -i in.mp4 -filter:v "setpts=0.5*PTS" -an out.mp4

That is the whole trick for video. The number in front of PTS is the inverse of the speed: 0.5 plays back in half the time (2x faster), 2.0 stretches it to twice the length (half speed). This catches almost everyone the first time, so it is worth saying plainly: smaller multiplier means faster video. If you want the audio to follow along too, that is a separate filter (atempo) with its own quirk, which is most of what this page is about.

Speed up or slow down the video (setpts)

setpts rewrites each frame's presentation timestamp. Multiply the timestamps by less than 1 and the frames are presented closer together, so the clip runs faster; multiply by more than 1 and they spread out, so it runs slower.

bash
# 2x faster (video only)
ffmpeg -i in.mp4 -filter:v "setpts=0.5*PTS" -an out.mp4

# 4x faster
ffmpeg -i in.mp4 -filter:v "setpts=0.25*PTS" -an out.mp4

# Half speed (2x slower)
ffmpeg -i in.mp4 -filter:v "setpts=2.0*PTS" -an out.mp4

If you would rather think in terms of the speed factor directly, divide: setpts=PTS/4 is the same as setpts=0.25*PTS, and setpts=PTS/1.3 gives a tidy 1.3x without reaching for a calculator. Both forms are valid; pick whichever reads more clearly for the factor you want.

The -an flag drops the audio. For a pure speed change with no sound (a silent time-lapse, a screen recording you are going to narrate over), that is all you need, and it keeps the command simple because you are not dragging the audio quirk along with you.

Speed up the audio too (atempo)

To change the audio speed without making everyone sound like a chipmunk or a slowed-down record, use atempo. It time-stretches the audio while preserving pitch:

bash
# Audio at 2x, no pitch shift
ffmpeg -i in.mp4 -filter:a "atempo=2.0" out.mp4

atempo takes the speed factor directly, not the inverse: atempo=2.0 is twice as fast, atempo=0.5 is half speed. So setpts and atempo move in opposite directions for the same playback change, which is the part to keep straight. 2x faster overall is setpts=0.5*PTS paired with atempo=2.0.

The atempo range, and why you still chain it

This is the part everyone half-remembers wrong, so here is the current truth: a single atempo accepts a factor in the range [0.5, 100.0]. You can write atempo=4.0 in one filter and ffmpeg will run it. The old [0.5, 2.0] ceiling that older guides (and older ffmpeg builds, before the limit was raised in 2018) describe is no longer the hard wall it once was.

There is still a real reason to chain the filter, though, and it is about quality, not about avoiding an error. The docs are explicit that any factor above 2.0 skips samples rather than blending them, which makes large single-step speed-ups sound worse than the same factor split across stages. So the practical rule stands: keep each atempo at or below 2.0 and chain them with a comma, where the factors multiply.

bash
# 4x audio = 2.0 * 2.0
ffmpeg -i in.mp4 -filter:a "atempo=2.0,atempo=2.0" out.mp4

# 8x audio = 2.0 * 2.0 * 2.0
ffmpeg -i in.mp4 -filter:a "atempo=2.0,atempo=2.0,atempo=2.0" out.mp4

# 0.25x audio (very slow) = 0.5 * 0.5
ffmpeg -i in.mp4 -filter:a "atempo=0.5,atempo=0.5" out.mp4

The factors do not have to be equal. For 3x you can chain atempo=1.5,atempo=2.0 (1.5 times 2.0 is 3.0), or atempo=sqrt(3),atempo=sqrt(3) if you want the two stages balanced. Any pair whose product is your target works, as long as each member stays at or below 2.0 so neither stage drops into the sample-skipping regime. The product is the speed you get; keeping the steps small is what keeps it sounding clean.

Keep audio and video in sync

Most of the time you want both tracks to change together. Apply setpts to the video and a matching atempo to the audio in one -filter_complex, then map both outputs:

bash
# 2x faster, audio and video together
ffmpeg -i in.mp4 -filter_complex \
  "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
  -map "[v]" -map "[a]" out.mp4

For factors beyond 2x, the atempo chain rides along inside the same complex filter. The setpts side never needs chaining (it is a single multiply), only the audio does:

bash
# 4x faster, audio and video together
ffmpeg -i in.mp4 -filter_complex \
  "[0:v]setpts=PTS/4[v];[0:a]atempo=2.0,atempo=2.0[a]" \
  -map "[v]" -map "[a]" out.mp4

The thing to get right is that the video multiplier and the audio factor describe the same speed change from opposite ends: setpts=PTS/4 (video) goes with a chain that multiplies to 4 (audio). Mismatch them and your sound drifts out of sync with the picture, which is the usual symptom when "the speed-up worked but the audio is off."

Smoother slow motion with minterpolate

Slowing a clip with setpts=2.0*PTS does not create new frames; it just holds each existing frame on screen longer, so heavy slow-downs look stuttery. To synthesize the in-between frames, add the minterpolate filter, which generates intermediate frames by estimating motion between the real ones:

bash
# Slow to half speed, interpolate up to a smooth 60 fps
ffmpeg -i in.mp4 -filter:v "setpts=2.0*PTS,minterpolate=fps=60:mi_mode=mci" -an out.mp4

minterpolate is slow to run and can smear fast or chaotic motion (it is guessing where pixels go), so it is a tool for genuine slow-motion polish, not something to leave on by default. For ordinary speed changes the plain setpts result is fine, and footage that was actually shot at a high frame rate will always slow down better than interpolated frames can fake.

A note on the inverse, one more time

If you remember nothing else: setpts is inverse (smaller equals faster), atempo is direct (bigger equals faster), and although a single atempo now accepts up to 100, you still chain it in steps of 2.0 or less so the audio blends instead of skipping samples. Once those three facts are in your head, every speed command on this page is the same shape with different numbers.

For the full set of filters and conversions in one place, see the ffmpeg command cheat sheet. To play a clip backwards rather than faster, the reverse a video page covers the reverse and areverse filters, and to pull just the sound out (which a speed change does not do for you), see extract audio from a video.

FAQ

See also

Sources

Authoritative references this article was fact-checked against.

Tagsffmpegsetptsatempovideo speedslow motiontime-lapseCLI

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

How to Reverse a Video with ffmpeg

Reverse a video with ffmpeg using the reverse filter for picture and areverse for sound. Why you must write to a new output file, and why you trim before you reverse.

How to Crop a Video with ffmpeg

Crop a video with ffmpeg's crop filter: crop=w:h:x:y from the top-left origin, centered crops with in_w/in_h expressions, square crops for social, and cropdetect to strip black bars automatically.

How to Trim or Cut a Video with ffmpeg

Trim or cut a video from the command line with ffmpeg: the fast lossless -c copy way, the keyframe gotcha that makes your cut land early, and the frame-accurate re-encode. With -ss and -to/-t explained.