Skip to content

Instantly share code, notes, and snippets.

@gphg
Last active November 18, 2024 14:02
Show Gist options
  • Save gphg/1dd083b89bddd17548eb721d6475433c to your computer and use it in GitHub Desktop.
Save gphg/1dd083b89bddd17548eb721d6475433c to your computer and use it in GitHub Desktop.
My attempt on writing script for ffmpeg on WEBM.
#!/bin/bash
# Usage:
# v9-ffmpeg.sh 720 input.mp4
# v9-ffmpeg.sh 720 input.mp4 output.webm
# Change me.
OUTPUT_PREFIX=""
# Set to 0 as it is.
OUTPUT_BASECRF="-12"
__get_info() {
local input="$1"
local entry="$2"
ffprobe -v error -select_streams v:0 -of default=nw=1:nk=1 \
-show_entries stream="$entry" "$input"
}
__encode() {
local target="$1"
local input="$2"
local output="$3"
local w=$(__get_info "$input" "width")
local h=$(__get_info "$input" "height")
local dim=$(( w < h ? w : h ))
local din=$(( w > h ? w : h ))
local fps=$(( $(__get_info "$input" "avg_frame_rate") ))
# https://developers.google.com/media/vp9/settings/vod/#recommended_settings
local filter
local scale
local bitrate
local minrate
local maxrate
local qcrf
local tcolumn1=1
local tcolumn2=1
local threads=4
case $target in
1080)
# For modern mobile device storing
scale="1080"
qcrf="31"
bitrate="1800k"
minrate="900k"
maxrate="2610k"
tcolumn1=2
tcolumn2=3
threads=8
# 50 or 60 fps
if [[ $fps -ge "50" ]]; then
bitrate="3000k"
minrate="1500k"
maxrate="4350k"
fi
;;
720)
# For reasonable online sharing
scale="720"
qcrf="32"
bitrate="1024k"
minrate="512k"
maxrate="1485k"
tcolumn1=2
tcolumn2=2
threads=8
# 50 or 60 fps
if [[ $fps -ge "50" ]]; then
bitrate="1800k"
minrate="900k"
maxrate="2610k"
fi
;;
480)
# 10+ mins long or VGA
scale="480"
qcrf="33"
bitrate="750k"
minrate="375k"
maxrate="1088k"
;;
360)
# Half of 720p
scale="360"
qcrf="34"
bitrate="512k"
minrate="256k"
maxrate="742k"
;;
240)
# Very 2000-ish
scale="240"
qcrf="36"
bitrate="276k"
minrate="138k"
maxrate="400k"
;;
*)
echo "Preset doesn't exist."
exit 1
;;
esac
# Output follows input with different file extension, relative to CWD
if [ -z "$output" ]; then
output=$(basename "${input%.*}.webm")
fi
# Portrait orientation?
if [[ $h -gt $w ]]; then
filter="scale=${scale}:-2"
else
filter="scale=-2:${scale}"
fi
# Calculate crf base: 18 to 23 = lossless
qcrf=$(( $OUTPUT_BASECRF + $qcrf ))
# https://developers.google.com/media/vp9/settings/vod/#ffmpeg_command_lines
ffmpeg -i "$input" -vf "$filter" \
-b:v "$bitrate" -minrate "$minrate" -maxrate "$maxrate" \
-tile-columns "$tcolumn1" -g 240 -threads "$threads" -quality good -crf "$qcrf" \
-c:v libvpx-vp9 -c:a libopus -pass 1 -speed 4 "${OUTPUT_PREFIX}${output}" && \
ffmpeg -i "$input" -vf "$filter" \
-b:v "$bitrate" -minrate "$minrate" -maxrate "$maxrate" \
-tile-columns "$tcolumn2" -g 240 -threads "$threads" -quality good -crf "$qcrf" \
-c:v libvpx-vp9 -c:a libopus -pass 2 -speed 4 -y "${OUTPUT_PREFIX}${output}"
}
# Pass the args into function. This script only takes one file.
__encode "$@"
@gphg
Copy link
Author

gphg commented Nov 18, 2024

Omitted bitrate, minbitrate, and maxbitrate. Previous version can be viewed here: https://gist.github.com/gphg/1dd083b89bddd17548eb721d6475433c/474a465094e8102e6cea1e03d46ac9f3d12294b3

It is now tied to CRF clamp between 18 and 35.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment