Created
October 29, 2023 17:57
-
-
Save rdump/9f3c14544b8479c9fc7810e10a965927 to your computer and use it in GitHub Desktop.
Script for Handbrake CLI encoding standards including languages and subtitles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# Handbrake ISO tracks transcode | |
# Mount an ISO, and give this script | |
# -i the path to the ISO's mount directory | |
# -d the path to the destination file directory (will be created) | |
# TODO: Figure out how to do AC3 passthrough for 2nd track of audios | |
# Handbrake Presets for reference, a subset from 'HandbrakeCLI -z' | |
# & https://handbrake.fr/docs/en/latest/technical/official-presets.html | |
# ... | |
# HQ 1080p30 Surround | |
# High quality H.264 video (up to 1080p30), AAC stereo audio, | |
# and Dolby Digital (AC-3) surround audio, in an MP4 | |
# container. | |
# HQ 720p30 Surround | |
# High quality H.264 video (up to 720p30), AAC stereo audio, | |
# and Dolby Digital (AC-3) surround audio, in an MP4 | |
# container. | |
# ... | |
# Super HQ 1080p30 Surround | |
# Super high quality H.264 video (up to 1080p30), AAC stereo | |
# audio, and Dolby Digital (AC-3) surround audio, in an MP4 | |
# container. | |
# Super HQ 720p30 Surround | |
# Super high quality H.264 video (up to 720p30), AAC stereo | |
# audio, and Dolby Digital (AC-3) surround audio, in an MP4 | |
# container. | |
# ... | |
# Vimeo YouTube HQ 2160p60 4K | |
# High quality H.264 video (up to 2160p60) and high bit rate | |
# AAC stereo audio in an MP4 container. Compatible with video | |
# hosting services supporting 4K video, such as Vimeo and | |
# YouTube. | |
# Vimeo YouTube HQ 1440p60 2.5K | |
# High quality H.264 video (up to 1440p60) and high bit rate | |
# AAC stereo audio in an MP4 container. Compatible with video | |
# hosting services supporting 2.5K video, such as Vimeo and | |
# YouTube. | |
# Vimeo YouTube HQ 1080p60 | |
# High quality H.264 video (up to 1080p60) and high bit rate | |
# AAC stereo audio in an MP4 container. Compatible with video | |
# hosting services supporting 1080p60, such as Vimeo and | |
# YouTube. | |
# Vimeo YouTube HQ 720p60 | |
# High quality H.264 video (up to 720p60) and high bit rate | |
# AAC stereo audio in an MP4 container. Compatible with video | |
# hosting services supporting 720p60, such as Vimeo and | |
# YouTube. | |
# ... | |
# Android 1080p30 | |
# H.264 video (up to 1080p30) and AAC stereo audio, in an MP4 | |
# container. Compatible with Android devices. | |
# Android 720p30 | |
# H.264 video (up to 720p30) and AAC stereo audio, in an MP4 | |
# container. Compatible with Android devices. | |
# ... | |
# Apple 1080p30 Surround | |
# H.264 video (up to 1080p30), AAC stereo audio, and Dolby | |
# Digital (AC-3) surround audio, in an MP4 container. | |
# Compatible with Apple iPhone 5, 5s, SE, 6, 6 Plus, 6s, 6s | |
# Plus and later; iPod touch 6th Generation and later; iPad | |
# Pro; iPad Air; iPad 3rd, 4th Generation and later; iPad | |
# mini; Apple TV 3rd Generation and later. | |
# Apple 720p30 Surround | |
# H.264 video (up to 720p30), AAC stereo audio, and Dolby | |
# Digital (AC-3) surround audio, in an MP4 container. | |
# Compatible with Apple iPhone 4, 4S and later; iPod touch | |
# 4th, 5th Generation and later; Apple TV 2nd Generation and | |
# later. | |
# Apple 540p30 Surround | |
# H.264 video (up to 540p30), AAC stereo audio, and Dolby | |
# Digital (AC-3) surround audio, in an MP4 container. | |
# Compatible with Apple iPhone 1st Generation, 3G, 3GS, and | |
# later; iPod touch 1st, 2nd, 3rd Generation and later; iPod | |
# Classic; Apple TV 1st Generation and later. | |
export PATH="~/bin:/opt/local/bin:/opt/local/sbin:/sw/bin:/sw/sbin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin" | |
PROG=`basename $0` | |
HB="HandbrakeCLI" | |
MAXAUDIOTRACKS=8 # DVDs support at most 8 audio tracks on each video title | |
esc_str() { | |
echo "$1" | sed "s/'/'\\\''/g;/ /s/^\(.*\)$/'\1'/" | |
} | |
getopt -T > /dev/null | |
if [ $? -eq 4 ]; then | |
# GNU enhanced getopt is available" | |
ARGS=$(getopt -o i:d: -l "iso:,destination:" -n "${PROG}" -- "$@"); | |
else | |
# Original getopt is available" | |
ARGS=$(getopt i:d: "$@"); | |
fi | |
if [ $? -ne 0 ]; then | |
echo "${PROG}: Usage: read the source, Luke" >&2 | |
exit 2 | |
fi | |
eval set -- "$ARGS"; | |
while [ $# -gt 0 ]; do | |
case "$1" in | |
-i | --iso ) | |
if [ -n "$2" ]; then | |
SOURCE="$2" | |
echo "${PROG}: ISO: ${SOURCE}" | |
fi | |
shift | |
;; | |
-d | --destination ) | |
if [ -n "$2" ]; then | |
DEST="$2" | |
echo "${PROG}: Destination: ${DEST}" | |
fi | |
shift | |
;; | |
-- ) | |
break | |
;; | |
esac | |
shift | |
done | |
if [ "X${SOURCE}" == "X" ] || [ "X${DEST}" == "X" ]; then | |
echo "${PROG}: Usage: read the source, Luke" >&2 | |
exit 2 | |
else | |
BASESOURCE=`basename "$SOURCE"`; | |
mkdir -p "$DEST" | |
for TYPE in shq1080p a540p; do | |
case $TYPE in | |
a540p) | |
PRESET='Apple 540p30 Surround' | |
SUBOPT="-s 1,2,3,4,5,6,7,8" | |
HBAUDIOSTYLE='slim' | |
EXT="m4v" | |
MINDUR=20 # minimum duration to bother with, in seconds | |
;; | |
shq1080p) | |
PRESET='Super HQ 1080p30 Surround' | |
SUBOPT="-s 1,2,3,4,5,6,7,8" | |
HBAUDIOSTYLE='fat' | |
EXT="m4v" | |
MINDUR=11 # minimum duration to bother with, in seconds | |
;; | |
webhq1440p) | |
PRESET='Vimeo YouTube HQ 1440p60 2.5K' | |
SUBOPT="-s 1,2,3,4,5,6,7,8" | |
HBAUDIOSTYLE='fat' | |
EXT="m4v" | |
MINDUR=11 # minimum duration to bother with, in seconds | |
;; | |
webhq2160p) | |
PRESET='Vimeo YouTube HQ 2160p60 4K' | |
SUBOPT="-s 1,2,3,4,5,6,7,8" | |
HBAUDIOSTYLE='fat' | |
EXT="m4v" | |
MINDUR=11 # minimum duration to bother with, in seconds | |
;; | |
esac | |
# Enumerate titles with a scan | |
echo "$PROG: Enumerating $BASESOURCE titles for $TYPE with minimum duration $MINDUR seconds" | |
SCANFILE=`mktemp -t ${PROG}-Scan` | |
echo "$PROG: Scan File: $SCANFILE" | |
TITLESFILE=`mktemp -t ${PROG}-Titles` | |
echo "$PROG: Titles File: $TITLESFILE" | |
$HB --verbose 0 --title 0 --min-duration $MINDUR -i "$SOURCE" 2> "$SCANFILE" | |
grep "^+ title " $SCANFILE | awk -F" |:" '{print $3}' > "$TITLESFILE" | |
NUMTITLESFOUND=`wc -l "$TITLESFILE" | awk '{print $1}'` | |
echo "$PROG: Found $NUMTITLESFOUND total titles of sufficient duration to transcode for $TYPE" | |
# Transcode the enumerated titles | |
TITLELIST="" | |
while read TITLENUM junk; do | |
TITLELIST="$TITLENUM $TITLELIST" | |
done < "$TITLESFILE" | |
rm -f "$TITLESFILE" | |
echo "$PROG: Complete title list for ${TYPE}: ${TITLELIST}." | |
echo ================ | |
for TN in $TITLELIST; do | |
# Process audio info for the current title of interest alone | |
echo "$PROG: Scanning audio languages for title $TN" | |
LANGSFILE=`mktemp -t ${PROG}-Lang` | |
echo "$PROG: Langs File: $LANGSFILE" | |
$HB --verbose 0 --title $TN --scan -i "$SOURCE" 2> "$SCANFILE" | |
# We always take audio track 1 to hopefully harmlessly work | |
# around track labeling bug in some DVD reads (e.g., track 4 | |
# is 3cc=eng, but is blank, and track 1 has the audio despite | |
# no 3cc= or other label | |
echo "1" >> "$LANGSFILE" | |
i=2; | |
while [ $i -le "$MAXAUDIOTRACKS" ]; do | |
echo "$PROG: Looking for audio track $i of $MAXAUDIOTRACKS" | |
grep -A1 "scan: checking audio $i" "$SCANFILE" | egrep "(3cc=|lang=)" | |
if [ $? -eq 0 ]; then | |
echo "$PROG: Found language info for audio track $i, looks real" | |
case "$HBAUDIOSTYLE" in | |
# For fat, we want all audio tracks in addition to | |
# track 1 from above | |
fat) | |
echo $i >> "$LANGSFILE" | |
;; | |
# For slim, we want 'eng' or 'und' in addition to | |
# track 1 from above | |
slim) | |
grep " + $i, .*iso639-2.*Hz," "$SCANFILE" | \ | |
egrep "iso639-2: (eng|und)" | |
if [ $? == 0 ]; then | |
echo $i >> "$LANGSFILE" | |
fi | |
;; | |
esac | |
fi | |
i=`expr $i + 1` | |
done | |
echo ================ | |
# Generate -a -R -D-E for the proper number of tracks based on languages, & slim or fat | |
echo "$PROG: Audio tracks of interest for style $HBAUDIOSTYLE in title $TN:" | |
cat "$LANGSFILE" | |
a_OPT="" | |
R_OPT="" | |
D_OPT="" | |
E_OPT="" | |
case "$HBAUDIOSTYLE" in | |
# For slim, we just transcode aac | |
# For fat, we transcode aac, and copy ac3 | |
fat) | |
while read TRACKNUM junk; do | |
echo "$PROG: Adding style $HBAUDIOSTYLE options for audio track $TRACKNUM in title $TN" | |
if [ ! -z $a_OPT ]; then | |
a_OPT="${a_OPT},$TRACKNUM,$TRACKNUM" | |
R_OPT="${R_OPT},Auto,Auto" | |
D_OPT="${D_OPT},0.0,0.0" | |
E_OPT="${E_OPT},ca_aac,copy:ac3" | |
else | |
a_OPT="$TRACKNUM,$TRACKNUM" | |
R_OPT="Auto,Auto" | |
D_OPT="0.0,0.0" | |
E_OPT="ca_aac,copy:ac3" | |
fi | |
done < "$LANGSFILE" | |
;; | |
slim) | |
while read TRACKNUM junk; do | |
echo "$PROG: Adding style $HBAUDIOSTYLE options for audio track $TRACKNUM in title $TN" | |
if [ ! -z $a_OPT ]; then | |
a_OPT="${a_OPT},$TRACKNUM" | |
R_OPT="${R_OPT},Auto" | |
D_OPT="${D_OPT},0.0" | |
E_OPT="${E_OPT},ca_aac" | |
else | |
a_OPT="$TRACKNUM" | |
R_OPT="Auto" | |
D_OPT="0.0" | |
E_OPT="ca_aac" | |
fi | |
done < "$LANGSFILE" | |
;; | |
esac | |
# Build final option string for non-empty audio tracks | |
if [ ! -z $a_OPT ]; then | |
a_OPT="-a ${a_OPT}" | |
R_OPT="-R ${R_OPT}" | |
D_OPT="-D ${D_OPT}" | |
E_OPT="-E ${E_OPT}" | |
fi | |
rm -f "$LANGSFILE" | |
echo ================ | |
echo "$PROG: Transcoding $TYPE title number $TN." | |
echo "$PROG: HandbrakeCLI options: -Z $PRESET $a_OPT $R_OPT $D_OPT $E_OPT $SUBOPT -t $TN -i $SOURCE -o ${DEST}/${BASESOURCE}-t${TN}-${TYPE}.${EXT}" | |
$HB -Z "$PRESET" -t $TN "$a_OPT" "$R_OPT" "$D_OPT" "$E_OPT" "$SUBOPT" -i "$SOURCE" -o "${DEST}/${BASESOURCE}-t${TN}-${TYPE}.${EXT}" 1> /dev/null | |
echo "$PROG: Finished transcoding $TYPE title number $TN." | |
echo ================ | |
done | |
echo | |
rm -f "$SCANFILE" | |
done | |
fi | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment