Dup Ver Goto 📝

Retime Video aka Change Framerate

PT2/media/ffmpeg ffmpeg does not exist
To
102 lines, 442 words, 2704 chars Page 'RetimeVideo' does not exist.

The aim here is to take e.g. a 25fps video, change it so that it becomes 24fps using the same frames (so is slightly longer), and also stretch the audio to fit the new length.

To take a 24fps video and make it 30fps (same frames, sped up, shorter duration): (from this stackoverflow

With re-encoding

Note that you have to compute the 1.25 passed to setpts.

ffmpeg -y -i in.mp4 -vf "setpts=1.25*PTS" -r 24 out.mp4

Without re-encoding

This is useful since there is no need to compute the fraction of input-fps/output-fps.

First step - extract video to raw bitstream

ffmpeg -y -i in.mp4 -c copy -f h264 in.h264

Remux with new framerate

ffmpeg -y -r 24 -i in.h264 -c copy out.mp4

Stretching Audio

You could use a DAW like Reaper, or a command line app like rubber band.

Combined script

This is something rough cobbled together. I think it works, but haven't properly tested it, and it's not robust. The getvdur script returns the duration of a media file in the format: filename.mp4: 3661 1h1m1s. Something more robust could be written in Python.

#!/bin/bash
# usage:
#   retime OFR file1 [file2...]
# where OFR is TARGET frame rate.

chk() {
  for s; do
    which "$s" >& /dev/null || { echo "no $s"; exit 1; }
  done
}
chk ffprobe ffmpeg rubberband-r3 getvdur

ofrate="$1"
shift

# temporary filenames
wav="tmp_audio.wav"
rwav="tmp_raudio.wav"
h264="tmp_video.h264"
tmp4="tmp_video.mp4"

for ifn; do
  if ! rm -f "$wav" "$rwav" "$h264" "$tmp4"; then
    echo "Failed to delete temporary files"
    exit 1
  fi
  ofn="rt_$ifn"
  if [ -e "$ofn" ]; then
    echo "$ofn exists already"
    continue
  fi

  # must h264 to mp4 to get resulting dur for rubber band
  ffmpeg -y -i "$ifn" "$wav"
  if [ ! -e "$wav" ]; then
     echo "Failed to extract audio"
     exit 1
  fi

  ffmpeg -y -i "$ifn" -an -c:v copy -f h264 "$h264"
  if [ ! -e "$h264" ]; then
     echo "Failed to extract h264 video"
     exit 1
  fi

  VIDCODEC="-c:v h264_nvenc -b:v 8M" # full hd with nvidia gpu
  VIDCODEC="-b:v 8M" # full hd using cpu
  ffmpeg -y -r "$ofrate" -i "$h264" -an $VIDCODEC "$tmp4"
  if [ ! -e "$tmp4" ]; then
     echo "Failed to convert frame rate to $tmp4"
     exit 1
  fi

  d="$(getvdur "$tmp4" | cut -f2 -d: | awk '{ print $1 }')"

  rubberband-r3 -D$d "$wav" "$rwav"
  if [ ! -e "$rwav" ]; then
     echo "Failed to stretch audio"
     exit 1
  fi

  ffmpeg -i "$tmp4" -i "$rwav" -c:v copy -map 0:0 -map 1:0 -b:a 160k "$ofn"
  if [ ! -e "$ofn" ]; then
     echo "Failed to combine to output file"
     exit 1
  fi
done