293 lines
9.8 KiB
Bash
Executable File
293 lines
9.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
shopt -s globstar
|
|
|
|
# Initialise variables
|
|
function showHelp() {
|
|
echo "----------------"
|
|
echo "Convert videos for Plex Media Server"
|
|
echo "----------------"
|
|
echo "Converts all videos in nested folders to h264 and audio to aac using HandBrake with the Normal preset."
|
|
echo "This saves Plex from having to transcode files which is CPU intensive."
|
|
echo
|
|
echo "Prerequisites"
|
|
echo
|
|
echo "Requires HandBrackCLI and media-info."
|
|
echo " macOS:"
|
|
echo " $ brew install handbrake"
|
|
echo " $ brew install media-info"
|
|
echo " Arch Linux:"
|
|
echo " $ sudo pacman -S handbrake-cli mediainfo"
|
|
echo "(Package names may vary depending on your distribution)"
|
|
echo "This script uses glob patterns, which requires Bash 4+ and globstar enabled"
|
|
echo " $ bash --version"
|
|
echo " Mac https://gist.github.com/reggi/475793ea1846affbcfe8"
|
|
echo
|
|
echo "----------------"
|
|
echo
|
|
echo "Command line options:"
|
|
echo "-a Select an audio track to use."
|
|
echo "-b Select a subtitle track to burn in."
|
|
echo "-c Codec to modify. Default is MPEG-4"
|
|
echo "-d Delete original."
|
|
echo "-f Force overwriting of files if already exist in output destination."
|
|
echo "-o Output folder directory path."
|
|
echo " Default is the same directory as the input file."
|
|
echo "-p The directory path of the movies to be tidied."
|
|
echo " Default is '.', the location of this script."
|
|
echo "-q Quality of HandBrake encoding preset. Default is 'Fast 1080p30'."
|
|
echo " For a full list of presets in CMD line run:"
|
|
echo " HandBrakeCLI --preset-list"
|
|
echo " https://handbrake.fr/docs/en/latest/workflow/select-preset.html"
|
|
echo "-r Run transcoding. Exclude for dry run."
|
|
echo "-s Skip transcoding if there is already a matching file name in the output destination."
|
|
echo " Force takes precedence over skipping files and will overwrite them if both flags present."
|
|
echo "-w Workspace directory path for processing. Set a local directory for faster transcoding over network."
|
|
echo
|
|
echo "Examples:"
|
|
echo " Dry run all movies in the Movies directory"
|
|
echo " .convert-videos-for-plex.sh -p Movies"
|
|
echo
|
|
echo " Transcode all movies in the current directory force overwriting matching .mp4 files."
|
|
echo " .convert-videos-for-plex.sh -fr"
|
|
echo
|
|
echo " Transcode all network movies using Desktop as temp directory and delete original files."
|
|
echo " .convert-videos-for-plex.sh -rd -p /Volumes/Public/Movies -w ~/Desktop"
|
|
echo
|
|
}
|
|
|
|
codec="MPEG-4"
|
|
delete=false
|
|
path="./"
|
|
out="$HOME/Movies"
|
|
name=""
|
|
ext=".mp4"
|
|
force=false
|
|
skip=false
|
|
forceOverwrite=false
|
|
run=false
|
|
workspace=""
|
|
fileIn=""
|
|
fileOut=""
|
|
count=0
|
|
#qualityPreset="Fast 1080p30"
|
|
qualityPreset="Apple 720p30 Surround"
|
|
audio=""
|
|
subtitle=""
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
version=$(ls /opt/homebrew/Cellar/handbrake 2>/dev/null)
|
|
if [ "$version" != "" ]; then
|
|
handbrake="/opt/homebrew/Cellar/handbrake/$version/bin/HandBrakeCLI"
|
|
echo "Handbrake $version"
|
|
else {
|
|
cli=$(which HandBrakeCLI)
|
|
if [ "$cli" != "" ]; then
|
|
handbrake="$cli"
|
|
version=$("$handbrake" --version 2>/dev/null | sed -n '1p')
|
|
echo "$version"
|
|
else
|
|
echo "handbrake not installed!"
|
|
fi
|
|
}
|
|
fi
|
|
|
|
function removeLock {
|
|
if [[ -f "$1" ]]; then
|
|
rm "$1"
|
|
fi
|
|
}
|
|
|
|
while getopts "h?dfsrp:o:c:w:q:a:b:" opt; do
|
|
case "$opt" in
|
|
h|\?)
|
|
showHelp
|
|
exit 0
|
|
;;
|
|
d) del=true
|
|
;;
|
|
f) force=true
|
|
;;
|
|
s) skip=true
|
|
;;
|
|
r) run=true
|
|
;;
|
|
p) path="$OPTARG"
|
|
;;
|
|
o) out="$OPTARG"
|
|
;;
|
|
c) codec="$OPTARG"
|
|
;;
|
|
w) workspace="$OPTARG"
|
|
;;
|
|
q) qualityPreset="$OPTARG"
|
|
;;
|
|
a) audio="--audio $OPTARG"
|
|
;;
|
|
b) subtitle="--subtitle $OPTARG --subtitle-burned"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Reset OPTIND
|
|
shift $((OPTIND-1))
|
|
|
|
echo
|
|
if [[ $run == true ]]; then
|
|
echo -e "${BLUE}TRANSCODING${NC}"
|
|
else
|
|
echo -e "${BLUE}DRY RUN${NC}"
|
|
fi
|
|
echo "----------------"
|
|
|
|
# Make sure all user inputted paths have trailing slashes
|
|
if [[ $path != */ ]]; then
|
|
path=$path"/"
|
|
fi
|
|
if [[ $out != "" && $out != */ ]]; then
|
|
out=$out"/"
|
|
fi
|
|
if [[ $workspace != "" && $workspace != */ ]]; then
|
|
workspace=$workspace"/"
|
|
fi
|
|
|
|
for i in "${path}"{,**/}*.*; do
|
|
forceOverwrite=false
|
|
|
|
# Prevent processing on non-files
|
|
if [[ $i != *\*.* ]]; then
|
|
# Loop over avi, mkv, iso, img, mp4 and m4v files only.
|
|
if [[ $i == *.avi || $i == *.mkv || $i == *.iso || $i == *.img || $i == *.mp4 || $i == *.m4v ]]; then
|
|
((count++))
|
|
|
|
lockPath="${i}.lock"
|
|
|
|
if [[ -f "${lockPath}" ]]; then
|
|
echo -e "${BLUE}Lockfile for $i exists. Skipping.${NC}"
|
|
continue
|
|
fi
|
|
|
|
if [[ $run == true ]]; then
|
|
touch "${lockPath}"
|
|
fi
|
|
|
|
echo
|
|
echo "${count}) Checking: "$i
|
|
|
|
if [[ ($audio != "" || $subtitle != "")
|
|
|| $(mediainfo --Inform="Video;%Format%" "$i") == *$codec*
|
|
|| $(mediainfo --Inform="Video;%Format%" "$i") == "HEVC"
|
|
|| $(mediainfo --Inform="Video;%Format%" "$i") == "xvid"
|
|
|| ($(mediainfo --Inform="Video;%Format%" "$i") == "AVC"
|
|
&& ($(mediainfo --Inform="Video;%Format_Profile%" "$i") == *"@L5"*))
|
|
]]; then
|
|
|
|
# Set audio options to defaults if required
|
|
if [[ $audio == "" ]]; then
|
|
audio="--audio-lang-list 'und' --all-audio"
|
|
fi
|
|
|
|
# Set subtitle options to defaults if required
|
|
if [[ $subtitle == "" ]]; then
|
|
subtitle="-s 'scan'"
|
|
fi
|
|
|
|
# Get file name minus extension
|
|
name=${i%.*}
|
|
|
|
# Set out directory if different from current
|
|
if [[ $out != "" ]]; then
|
|
name=${name##*/}
|
|
name=$out$name
|
|
fi
|
|
|
|
# Check for existing .mp4; ask for overwrite or set force overwrite.
|
|
if [[ -e $name$ext ]]; then
|
|
if [[ $force == false ]]; then
|
|
if [[ $skip == false ]]; then
|
|
|
|
read -p "'$name$ext' already exists. Do you wish to overwrite it?" -n 1 -r
|
|
echo
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
forceOverwrite=true
|
|
echo -e "${BLUE}Overwriting:${NC} "$name$ext
|
|
else
|
|
echo -e "${RED}Skipping (already exists):${NC} "$name$ext
|
|
removeLock "${lockPath}"
|
|
continue
|
|
fi
|
|
else
|
|
echo -e "${RED}Skipping (already exists):${NC} "$name$ext
|
|
removeLock "${lockPath}"
|
|
continue
|
|
fi
|
|
else
|
|
forceOverwrite=true
|
|
echo -e "${BLUE}Overwriting:${NC} "$name$ext
|
|
fi
|
|
fi
|
|
|
|
echo "Transcoding: "${i} to $name$ext
|
|
|
|
if [[ $run == true ]]; then
|
|
|
|
# Set file locations: in situ or separate workspace
|
|
if [[ $workspace == "" ]]; then
|
|
fileIn="${i}"
|
|
fileOut="${name}"
|
|
else
|
|
echo "Copying "$i" to "$workspace
|
|
cp "$i" "${workspace}"
|
|
fileIn=$workspace${i##*/}
|
|
fileOut=${fileIn%.*}
|
|
fi
|
|
|
|
# Modified from http://pastebin.com/9JnS23fK
|
|
#HandBrakeCLI -i "${fileIn}" -o "${fileOut}""_processing""${ext}" --preset="${qualityPreset}" -O ${subtitle} ${audio}
|
|
"$handbrake" -i "${fileIn}" -o "${fileOut}""_processing""${ext}" --preset="${qualityPreset}" -O ${subtitle} ${audio}
|
|
|
|
# if HandBrake did not exit gracefully, continue with next iteration
|
|
if [[ $? -ne 0 ]]; then
|
|
removeLock "${lockPath}"
|
|
continue
|
|
else
|
|
# Delete original files
|
|
if [[ $del == true ]]; then
|
|
rm -f "${i}"
|
|
elif [[ $forceOverwrite == true ]]; then
|
|
rm -f "${name}""${ext}"
|
|
fi
|
|
|
|
mv "${fileOut}""_processing""${ext}" "${fileOut}""${ext}"
|
|
chmod 666 "${fileOut}""${ext}"
|
|
|
|
# Move files from workspace back to original locations
|
|
if [[ $workspace != "" ]]; then
|
|
echo "Copying from workspace ""${fileOut}${ext}"" to ""$(dirname "${name}${ext}")"
|
|
cp "${fileOut}${ext}" "$(dirname "${name}${ext}")"
|
|
rm -f "${fileIn}"
|
|
rm -f "${fileOut}""${ext}"
|
|
fi
|
|
echo -e "${GREEN}Transcoded:${NC} "$name$ext
|
|
fi
|
|
|
|
else
|
|
echo -e "${GREEN}Transcoded (DRY RUN):${NC} "$name$ext
|
|
fi
|
|
else
|
|
currentFormat=$(mediainfo --Inform="Video;%Format%" "$i")
|
|
currentProfile=$(mediainfo --Inform="Video;%Format_Profile%" "$i")
|
|
echo -e "${RED}Skipping (video format ${currentFormat} ${currentProfile} will already play in Plex)${NC}"
|
|
fi
|
|
|
|
removeLock "${lockPath}"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
exit 0
|