34

Is there a relatively simple way to speed up a video (mp4, with aac encoded audio), by say "x1.25" or "x1.3" while keeping the original audio-video sync, but also retaining the original pitch of the audio ?

I've read some discussions about extracting audio track into separate file, then use rubberband to lower the pitch by the requisite value, and then merge the audio video tracks using ffmpeg with speed-up, which raises the pitch of the audio back again to original. However, it appears that this is a bit of hit-n-miss, because rubberband appears to use number of octaves as the parameter to raise or lower pitch, and this may not always align perfectly with the video, as musical notes / octaves have specific ratios. Also, this is cumbersome.

So, is there any simpler ways using ffmpeg alone ?

3
  • 2
    rubberband offers a tempo option which takes in a decimal number.
    – Gyan
    Commented May 21, 2018 at 6:03
  • Thanks @Gyan. Sounds like a valid answer, even if it is not as simple as I'd hope it to be, but removes the issue of rubberband being (wrongly presumed to be) limited to pitch change based on number of notes (of a chromatic scale).
    – bdutta74
    Commented May 21, 2018 at 6:20
  • 1
    rubberband can be compiled as a ffmpeg filter, so no need to extract audio.
    – Gyan
    Commented May 21, 2018 at 6:42

3 Answers 3

45

It can be done with ffmpgeg using a complex filter:

  ffmpeg -i input.mkv -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" output.mkv

Documentation: https://trac.ffmpeg.org/wiki/How%20to%20speed%20up%20/%20slow%20down%20a%20video

The command above works if you want to multiply by 2 the speed. If you want to multiply by any <x>, the parameters become:

  ffmpeg -i input.mkv -filter_complex "[0:v]setpts=<1/x>*PTS[v];[0:a]atempo=<x>[a]" -map "[v]" -map "[a]" output.mkv

For instance, if you want to multiply by 1.15, the command is:

  ffmpeg -i input.mkv -filter_complex "[0:v]setpts=0.87*PTS[v];[0:a]atempo=1.15[a]" -map "[v]" -map "[a]" output.mkv
6
  • if i want to slow my video and audio down by exactly half, would atempo=0.5 and setpts=1.5 ??
    – nomaam
    Commented Sep 12, 2021 at 2:59
  • 2
    For half speed: atempo=0.5 and setpts=2 Commented Sep 13, 2021 at 7:20
  • @Weidenrinde Why doesn't this work: [0:a]asetpts=PTS*0.5[a] ??? Commented Jun 10, 2022 at 22:34
  • @RicardoBohner If I try that, I don´t receive any audio. Does it work for you? Commented Jun 13, 2022 at 17:31
  • @Weidenrinde No it doesn't but in my head it's the equivalent of [0:v]setpts=PTS*0.5[v] what works to speed up the vídeo I wonder why it doesn't work for audio the same way. Commented Jun 13, 2022 at 18:15
11

You can speed up video by 2.5X for example by doing this:

ffmpeg -i "input_video.mp4" -vf "setpts=(PTS-STARTPTS)/2.5" -af atempo=2.5 "input_video_2.5X.mp4"

Here is a bash script you can use for convenience (say convert_video.sh):

#!/bin/bash

# Arguments
FILE_RAW=$1
SPEED_FACTOR=${2:-1.0} # Default is 1.0 X speed

# Prepare variables
BASE_PATH=$(dirname $(readlink -f $FILE_RAW))
FILENAME_EXT="$(basename "${FILE_RAW}")"
FILENAME_ONLY="${FILENAME_EXT%.*}"
EXT_ONLY="${FILENAME_EXT#*.}"
FILENAME_ONLY_PATH="${BASE_PATH}/${FILENAME_ONLY}"

# Speed up/slow down video
ffmpeg -i "${FILENAME_ONLY_PATH}.${EXT_ONLY}" -vf "setpts=(PTS-STARTPTS)/${SPEED_FACTOR}" -af atempo=$SPEED_FACTOR "${FILENAME_ONLY_PATH}_${SPEED_FACTOR}X.${EXT_ONLY}"

Note: Make script executable: chmod +x convert_video.sh

Usage (Output File: <PATH_TO_INPUT_VIDEO>_<OPTIONAL_SPEED>X.mp4)

. <PATH_TO_THIS_SCRIPT>/convert_video.sh <PATH_TO_INPUT_VIDEO> <OPTIONAL_SPEED>

Example 1: Speed up video to 2.5X (Output: ~/Videos/input_video_2.5X.mp4)

. ~/convert_video.sh ~/Videos/input_video.mp4 2.5

Example 2: Slow down video to 0.5X (Output: ~/Videos/input_video_0.5X.mp4)

. ~/convert_video.sh ~/Videos/input_video.mp4 0.5

Hope it helps.

1
  • WFM with ffmpeg version 4.4 . Thanks. Commented Jul 6, 2022 at 17:45
2

The code I used.

speed_change(){
    input=$1
    output=$2
    a_speed=$3
    v_speed=$(awk -v a_speed=$a_speed 'BEGIN{print 1/a_speed}')
    echo -e "\nSpeed up ${a_speed}X, para to atempo is ${a_speed}, para to setpts is ${v_speed}.\n"
    ffmpeg -i $input -c:v hevc_videotoolbox -vf "setpts=$v_speed*PTS" -af atempo=$a_speed $output
}
2
  • 1
    Code without any explanation is useless. Can you elaborate on this a little more?
    – Toto
    Commented Oct 11, 2022 at 17:07
  • Using awk to do the math was clever but I believe you can do math in bash directly: shell-tips.com/bash/math-arithmetic-calculation
    – csells
    Commented Apr 28 at 17:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .