Skip to content

Instantly share code, notes, and snippets.

@nuvious
Created March 23, 2025 21:44
Show Gist options
  • Save nuvious/ec9eac457ecd6d3a1ed83f341b0eeee2 to your computer and use it in GitHub Desktop.
Save nuvious/ec9eac457ecd6d3a1ed83f341b0eeee2 to your computer and use it in GitHub Desktop.
Script to scale a video to an excact time length with ffmpeg without pitch shift in audio.
#!/bin/bash
# Anything breaks, we need to stop trying to encode
set -e
# If not enough arguments are provided, inform the user of the user
if [ $# -lt 4 ]; then
echo "This tool re-encodes a video stretching or shrinking to the target" \
"video length with no changes to audio pitch."
echo "Usage: scale_vid.sh [input video] [hours] [minutes] [seconds]"
exit 1
fi
# Ensure bc and ffmpeg are available
if ! which bc; then
echo "This script depends on the bc command line calculator utility. " \
"Install bc and try again."
exit 1
fi
if ! which ffmpeg; then
echo "This script depends on the ffmpeg. Install ffmpeg and try again."
exit 1
fi
# Grab the duration from ffmpeg of the original file
time_str=$(
ffmpeg -i $1 2>&1 |
grep Duration |
sed -E 's/.*Duration: ([0-9]+:[0-9]+:[0-9]+\.[0-9]+),.*/\1/'
)
h=$(cut -d':' -f1 <<< "$time_str")
m=$(cut -d':' -f2 <<< "$time_str")
s=$(cut -d':' -f3 <<< "$time_str")
# Next we need to calculate the presentation timestamp values for audio/video
total_seconds=$(bc <<< "$h * 3600 + $m * 60 + $s")
target_seconds=$(bc <<< "$2 * 3600 + $3 * 60 + $4")
apts=$(bc <<< "scale=8; $total_seconds/$target_seconds")
vpts=$(bc <<< "scale=8; 1/$apts")
# Now just encode the video
ffmpeg -i $1 -map [v] -map [a] -preset fast -crf 23 scaled_$2-$3-$4_$1 \
-filter_complex "[0:v]setpts=$vpts*PTS[v];[0:a]atempo=$apts[a]"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment