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
#
# Best usage for scaling down video OR just simply reencode video into WEBM.
# Change me.
OUTPUT_PREFIX=""
# Set to 0 as it is.
OUTPUT_BASECRF="0"
__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")
# 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="19"
tcolumn1=2
tcolumn2=3
threads=8
;;
720)
# For reasonable online sharing
scale="720"
qcrf="20"
tcolumn1=2
tcolumn2=2
threads=8
;;
480)
# 10+ mins long or VGA
scale="480"
qcrf="24"
;;
360)
# Half of 720p
scale="360"
qcrf="28"
;;
240)
# Very 2000-ish (OR MEME QUALITY; DO NOT REMOVE)
scale="240"
qcrf="30"
;;
*)
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
# Recalculate crf base: 18 to 23 = lossless
qcrf=$(( $OUTPUT_BASECRF + $qcrf ))
# 35 is the maximum recommended
qcrf=$(( $qcrf < 35 ? $qcrf : 35 ))
# lesser than 18 is placebo
qcrf=$(( $qcrf > 18 ? $qcrf : 18 ))
# https://developers.google.com/media/vp9/settings/vod/#ffmpeg_command_lines
ffmpeg -i "$input" -vf "$filter" \
-tile-columns "$tcolumn1" -g 240 -threads "$threads" -quality good -crf "$qcrf" \
-c:v libvpx-vp9 -c:a libopus -b:a 256k -pass 1 -speed 4 "${OUTPUT_PREFIX}${output}" && \
ffmpeg -i "$input" -vf "$filter" \
-tile-columns "$tcolumn2" -g 240 -threads "$threads" -quality good -crf "$qcrf" \
-c:v libvpx-vp9 -c:a libopus -b:a 256k -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