Ahosting Logo
Knowledge Base

How to Speed Up, Slow Down and Reverse Video

A speed change is two separate adjustmentsThe video· presentation timestamps are rewritten· multiplying them slows it down· dividing them speeds it upThe audio· tempo is changed separately· and extreme factors are applied in stages· or the result sounds wrongReversingNeeds the whole file in memory or on disk at once, which is why it fails on long input and worksfine on a clip.

Changing playback speed is two operations that happen to be requested as one. The video and the audio are adjusted by different filters, and the two factors do not even run in the same direction.

Video: timestamps

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

The presentation timestamp of each frame is multiplied by the factor. Halving the timestamps plays the video in half the time, twice as fast.

So the number runs the opposite way to the speed: 0.5 is double speed, 2.0 is half speed. Getting this backwards once is a rite of passage.

Audio: tempo

ffmpeg -i in.mp4 -filter:a "atempo=2.0" -vn fast.m4a

atempo changes speed without changing pitch, which is what you want. The alternative makes voices sound comical.

Its factor reads normally: 2.0 is twice as fast.

Each atempo accepts between 0.5 and 2.0. Beyond that, chain them:

-filter:a "atempo=2.0,atempo=2.0" # four times faster

Both together

ffmpeg -i in.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
 -map "[v]" -map "[a]" -c:v libx264 -crf 22 out.mp4

This is the form to use. Changing only the video leaves the audio at its original length, so it drifts further out of step as the clip runs, and the file is still valid, so nothing reports an error.

If the audio is not wanted, drop it deliberately with -an instead of leaving it unadjusted.

Understanding FFmpeg filters walks through why two inputs and two outputs need the complex form.

Slow motion has a frame rate problem

Slowing footage does not create frames. A 30-frame clip played at half speed shows each frame twice, and the result stutters.

Source shot at a high frame rate is the real answer: 120 frames per second slowed to a quarter gives genuine 30-frame slow motion with no duplication.

Failing that, frames can be invented:

ffmpeg -i in.mp4 -filter:v "minterpolate=fps=60,setpts=2.0*PTS" -an slow.mp4

It is slow to compute and produces visible distortion around fast movement and edges. Worth trying on specific material, not worth applying as a habit. Deinterlacing and changing frame rate explains the same filter's other use.

Reversing

ffmpeg -i in.mp4 -vf reverse -af areverse reversed.mp4

The important constraint: reversing holds the entire decoded video in memory. A short clip is fine. A long one will exhaust the machine's memory and be killed, which on a shared server affects more than your job.

For anything beyond a few seconds, split, reverse each part, then concatenate in reverse order. For the joining step, see trimming, cutting and concatenating.

Timelapse from a long recording

ffmpeg -i long.mp4 -filter:v "setpts=0.05*PTS" -an -r 30 timelapse.mp4

Twenty times faster, audio dropped, audio at that speed is unusable anyway.

The explicit -r 30 matters: without it the output can carry an absurd frame rate that some players refuse. Setting it also lets frames be dropped rather than encoded, which is faster.

Speed changes always re-encode

Timestamps are inside the stream, so nothing here can be done as a copy. Every speed change decodes and encodes the whole file.

Which makes it worth combining with any other filtering you intended in the same pass rather than running two jobs. There is more on choosing the encoding settings for that pass in CRF, two-pass and bitrate.

Know which change forces a re-encode

Some speed changes can be done cheaply and most cannot, and the difference decides how long the job takes.

ffmpeg -i in.mp4 -filter:v "setpts=0.5*PTS" -an fast.mp4
ffprobe -v error -show_entries stream=codec_name,r_frame_rate -of csv=p=0 fast.mp4

Changing the presentation timestamps alters playback speed and requires the video to be re-encoded, because the frame timing is part of the encoded stream.

The one exception is a container level change to the declared frame rate, which is fast and only useful when the source and target rates are close. Anything involving interpolation or audio is a full encode, and the cost scales with the length of the material.

Audio and video have to be changed together

Adjusting only the video produces a file where the sound drifts out of step, and the error grows through the file.

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

The two filters take reciprocal values, which is the part people get wrong. Halving the timestamps doubles the speed, so the audio tempo doubles as well.

The tempo filter accepts a limited range per instance, so larger changes need it applied more than once in sequence. Applying a value outside the range fails rather than clamping, which at least makes the mistake visible.

Slow motion needs frames that do not exist

Slowing footage stretches the existing frames, and the result stutters unless new ones are produced.

ffmpeg -i in.mp4 -filter:v "minterpolate=fps=60:mi_mode=mci" -an slowmo.mp4

Interpolation generates intermediate frames by estimating motion between the real ones. It is slow, considerably slower than an ordinary encode, and on complex movement it produces visible artefacts.

Footage recorded at a high frame rate specifically for this purpose needs none of it, since the frames already exist. That is the difference between slow motion that looks right and slow motion that is a computation.

Check the result rather than the exit code

Speed changes produce files that complete successfully and are wrong in ways the command cannot detect.

for f in in.mp4 out.mp4; do
  printf '%-10s %s\n' "$f" "$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$f")"
done

The output duration should be the input duration divided by the speed factor. Anything else means one of the filters did not apply, and a file where the video changed and the audio did not is the usual result.

Listen to the end rather than the beginning. Drift accumulates, so a file that appears synchronised for the first minute can be visibly wrong by the last.

Reversing needs the whole file in memory

Playing material backwards requires reading it all before writing anything, which makes it the most demanding operation here.

ffmpeg -i in.mp4 -vf reverse -af areverse out.mp4

On a long or high resolution file this exhausts memory rather than running slowly, and the process is terminated with no useful message.

Splitting the material into segments, reversing each, and joining them in reverse order keeps the memory requirement bounded. It is more work and it is the only approach that scales beyond short clips. Trimming and concatenating covers the split and join.

Preserve the audio when only the video changes

A speed change applied to a clip with no sound still discards the audio unless it is mapped explicitly.

ffmpeg -i in.mp4 -filter:v "setpts=2.0*PTS" -c:a copy out.mp4
ffprobe -v error -select_streams a -show_entries stream=codec_name -of csv=p=0 out.mp4

The check is the second command. An empty result means the output has no audio track, which is easy to miss when reviewing the picture.

Copying the audio while changing the video speed produces a file where they disagree, so this is only correct when the audio is intended to run at its original length, such as a soundtrack over sped up footage.