Files
shell-scripting-templates/bin/convertMedia
2015-04-10 14:34:18 -04:00

768 lines
28 KiB
Bash
Executable File

#!/usr/bin/env bash
# ##################################################
# My Generic BASH script template
#
version="1.0.0" # Sets version variable for this script
#
scriptTemplateVersion="1.1.1" # Version of scriptTemplate.sh that this script is based on
#
#
# HISTORY:
#
# * 2015-03-31 - v1.0.0 - First creation
# * 2015-04-07 - v1.1.0 - Added support for music files
# ##################################################
# Source Scripting Utilities
# -----------------------------------
# If these can't be found, update the path to the file
# -----------------------------------
scriptPath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ -f "${scriptPath}/../lib/utils.sh" ]; then
source "${scriptPath}/../lib/utils.sh"
else
echo "Please find the file util.sh and add a reference to it in this script. Exiting."
exit 1
fi
# trapCleanup Function
# -----------------------------------
# Any actions that should be taken if the script is prematurely
# exited. Always call this function at the top of your script.
# -----------------------------------
function trapCleanup() {
echo ""
if is_dir "${tmpDir}"; then
rm -r "${tmpDir}"
fi
die "Exit trapped." # Edit this if you like.
}
# Set Flags
# -----------------------------------
# Flags which can be overridden by user input.
# Default values are below
# -----------------------------------
quiet=0
printLog=0
verbose=0
force=0
strict=0
debug=0
safeRun=0
downsize720=0
deleteOriginal=0
XLD=0
args=()
# Set Temp Directory
# -----------------------------------
# Create temp directory with three random numbers and the process ID
# in the name. This directory is removed automatically at exit.
# -----------------------------------
tmpDir="/tmp/${scriptName}.$RANDOM.$RANDOM.$RANDOM.$$"
(umask 077 && mkdir "${tmpDir}") || {
die "Could not create temporary directory! Exiting."
}
# Logging
# -----------------------------------
# Log is only used when the '-l' flag is set.
#
# To never save a logfile change variable to '/dev/null'
# Save to Desktop use: $HOME/Desktop/${scriptBasename}.log
# Save to standard user log location use: $HOME/Library/Logs/${scriptBasename}.log
# -----------------------------------
logFile="$HOME/Library/Logs/${scriptBasename}.log"
function pauseScript() {
seek_confirmation "Ready to continue?"
if is_confirmed; then
info "Continuing"
fi
}
function mainScript() {
############## Begin Script Here ###################
####################################################
# Constants
dependencies=(ffmpeg gifsicle jq)
videoTypes=(mp4 mov avi mkv wmv flv ogg m4p m4v 3gp divx h264)
audioTypes=(mp3 avi m4a aiff aac m4p wav wma flac)
# If a user specifies a single file type extension, respect it.
if [ -n "${MEDIATYPE}" ]; then
if [[ "${videoTypes[*]}" =~ "${MEDIATYPE}" ]]; then
videoTypes=($MEDIATYPE) # Reset the video type array to user-input, if specified
fi
if [[ "${audioTypes[*]}" =~ "${MEDIATYPE}" ]]; then
audioTypes=($MEDIATYPE) # Reset the audio type array to user-input, if specified
fi
fi
function checkDependencies() {
for i in "${dependencies[@]}"; do
if type_not_exists "${i}"; then
die "Can not proceed without '${i}'. Please install it before rerunning this script."
fi
done
}
function breakLoop() {
# Break the for loop when a user specifies a file from the CLI.
# Basically, this ensures that we only run the loop once for a single file.
if [[ -n "${userFile}" ]]; then
break
fi
}
function outputDir() {
if [[ -n "${saveDir}" ]]; then
if [[ -e "${saveDir}" && ! -d "${saveDir}" ]]; then
die "${saveDir} exists but is not a directory"
fi
if [[ ! -d "${saveDir}" ]]; then
seek_confirmation "${saveDir} does not exist. Create?"
if is_confirmed; then
mkdir "${saveDir}" && verbose "mkdir ${saveDir}"
else
die "Can't run without a place to save the files."
fi
fi
# remove trailing slash if included. Add back to ensure it's always there.
outputDir="${saveDir%/}/" && verbose "outputDir=${saveDir%/}/"
fi
}
function identifyUserFile() {
if [[ -n "${args}" ]]; then
userFile="${args}"
fi
if [[ -n "${userFile}" ]]; then
#test -f "${f}" # Ensure that what we've found is a file
extension="${userFile##*.}" # Grab file extension of input file
if [[ "${videoTypes[*]}" =~ "${extension}" ]]; then
userVideoFile="${userFile}"
fi
if [[ "${audioTypes[*]}" =~ "${extension}" ]]; then
userAudioFile="${userFile}"
fi
fi
}
function userFormat() {
# Reads user input for format (-o, --output)
# Override defaults with CLI
if [ -n "$userOutput" ]; then
outputFormat="${userOutput,,}" && verbose "outputFormat=${outputFormat}"
fi
}
function doConvert() {
# Set the output name, format, and directory
# ###############################################
# Set output filename
output="$(basename "${f%.*}").$outputFormat" && verbose "output="${output}""
# Add users output save directory if used
if [[ -n "${outputDir}" ]]; then
output="${outputDir}${output}" && verbose "output=${outputDir}${output}"
fi
# Confirm we're not overwriting an existing file
if [[ "${safeRun}" -ne "1" ]]; then
if [ -e "${output}" ]; then
# rename the new file to '.new'
output="$(basename "${f%.*}").new."${outputFormat}"" && verbose "Adding '.new' to the new file name"
if [[ -n "${outputDir}" ]]; then
output="${outputDir}${output}" && verbose "output=${outputDir}${output}"
fi
fi
fi
# Respect the 'Quiet' flag
if [[ "${quiet}" == "1" ]]; then
ffquiet="-loglevel quiet"
fi
# # Respect the 'logfile' flag
# if [[ "${printLog}" == "1" ]]; then
# ffmpegLog=">> ${logFile}"
# fi
# Invoke the conversion
# ##################################
# Use XLD for audio file conversion if available
if [[ "$XLD" == "1" ]]; then
verbose "Running XLD commands for audio. No FFMPEG"
# Respect --safe flag.
if [[ "${safeRun}" == "1" ]]; then
notice "xld -o "${output}" ${audioConvertCommand} "${f}""
else
verbose "xld -o "${output}" ${audioConvertCommand} "${f}""
xld -o "${output}" ${audioConvertCommand} "${f}"
fi
else # Use ffmpeg when XLD is set to 0
# Respect --safe flag.
if [[ "${safeRun}" == "1" ]]; then
notice "ffmpeg -i "${f}" ${videoResize} ${videoCommand} ${videoAudioCommand} ${audioConvertCommand} "${output}" ${ffquiet}"
else
verbose "ffmpeg -i "${f}" ${videoResize} ${videoCommand} ${videoAudioCommand} ${audioConvertCommand} "${output}" ${ffquiet}"
ffmpeg -i "${f}" ${videoResize} ${videoCommand} ${videoAudioCommand} ${audioConvertCommand} "${output}" ${ffquiet}
# delete original if requested
if [[ "${deleteOriginal}" == "1" ]]; then
rm -f "${f}" && verbose "Deleting "${f}""
fi
fi
fi
}
convertVideo() {
for vt in "${videoTypes[@]}"; do
for f in *."${vt}"; do
if [[ -n "${userVideoFile}" ]]; then
# Override the file search if user specifies a specific file from CLI.
f="${userVideoFile}"
fi
test -f "${f}" || continue # Ensure that what we've found is a file
extension="${f##*.}" # Grab file extension of input file
informationFile="${tmpDir}/${f}.json"
# JSON METADATA FOR EACH ASSET
######################################################################
verbose "Reading JSON and writing to TMP"
# Output a JSON file for each video asset being parsed.
ffprobe -v quiet -print_format json -show_format -show_streams "${f}" >> "${informationFile}"
# uncomment the line below for debugging. It will write a json file for each file in the source directory
# ffprobe -v quiet -print_format json -show_format -show_streams "${f}" >> "${f}.json"
# Read the necessary information from the JSON
format="$(jq -r ".format.format_long_name" "${informationFile}")"
formatName="$(jq -r ".format.format_name" "${informationFile}")"
if [ $(jq -r ".streams[0].codec_type" "${informationFile}") == "video" ]; then
videoHeight="$(jq -r ".streams[0].height" "${informationFile}")"
videoWidth="$(jq -r ".streams[0].width" "${informationFile}")"
videoCodec="$(jq -r '.streams[0].codec_name' "${informationFile}")"
videoCodecLong="$(jq -r ".streams[0].codec_long_name" "${informationFile}")"
elif [ $(jq -r ".streams[1].codec_type" "${informationFile}") == "video" ]; then
videoHeight="$(jq -r ".streams[1].height" "${informationFile}")"
videoWidth="$(jq -r ".streams[1].width" "${informationFile}")"
videoCodec="$(jq -r '.streams[1].codec_name' "${informationFile}")"
videoCodecLong="$(jq -r ".streams[1].codec_long_name" "${informationFile}")"
else
warning "Missing video information for '"$f"'. Inspecting with 'ffprobe'."
ffprobe -v quiet -print_format json -show_format -show_streams "${f}"
safeExit
fi
if [ $(jq -r ".streams[0].codec_type" "${informationFile}") == "audio" ]; then
audioCodec="$(jq -r '.streams[0].codec_name' "${informationFile}")"
audioCodecLong="$(jq -r ".streams[0].codec_long_name" "${informationFile}")"
audioSampleRate="$(jq -r ".streams[0].sample_rate" "${informationFile}")"
audioBitRate="$(jq -r ".streams[0].bit_rate" "${informationFile}")"
elif [ $(jq -r ".streams[1].codec_type" "${informationFile}") == "audio" ]; then
audioCodec="$(jq -r '.streams[1].codec_name' "${informationFile}")"
audioCodecLong="$(jq -r ".streams[1].codec_long_name" "${informationFile}")"
audioSampleRate="$(jq -r ".streams[1].sample_rate" "${informationFile}")"
audioBitRate="$(jq -r ".streams[1].bit_rate" "${informationFile}")"
else
warning "Missing audio information for '"$f"'. Inspecting with 'ffprobe'."
ffprobe -v quiet -print_format json -show_format -show_streams "${f}"
safeExit
fi
# SET OUTPUT FORMAT
# Default to 'mp4' for everything.
# TODO - think through additional defaults
##########################################################
# if you wanted a default target format for a specific input format,
# you would put it here.
case "${format}" in
'Matroska / WebM') outputFormat='mp4' ;;
*) outputFormat='mp4' ;;
esac
# SET AUDIO INFORMATION
# Copy audio in compatible formats. Re-encode audio when needed
################################################################
# Pick the best aac audio encoder
if $(ffmpeg -version | grep enable-libfdk-aac >/dev/null); then
aacEncoder="libfdk_aac" && verbose "aac encoder set to libfdk_aac"
else
aacencoder="libfaac" && verbose "aac encoder set to libfaac"
fi
supportedAudioCodecs=(aac ac3 eac3)
if [[ "${supportedAudioCodecs[*]}" =~ "${audioCodec}" ]]; then
videoAudioCommand="-c:a copy" && verbose "videoAudioCommand set to -c:a copy"
else
videoAudioCommand="-c:a ${aacEncoder} -b:a 160k" && verbose "videoAudioCommand set to -c:a ${aacEncoder} -b:a 160k"
fi
# SET VIDEO INFORMATION
# Copy video in compatible formats. Re-encode audio when needed.
# Set resizing options
################################################################
# Is input video a known preset size?
if [[ "$videoWidth" == "1920" && "$videoHeight" == "1080" ]] || [[ "$videoWidth" == "1920" && "$videoHeight" == "816" ]]; then
videoPreset="1080p" && verbose "Input video has preset: 1080p"
fi
if [[ "$videoWidth" == "1280" && "$videoHeight" == "720" ]] || [[ "$videoWidth" == "1280" && "$videoHeight" == "544" ]]; then
videoPreset="720p" && verbose "Input video has preset: 720p"
fi
if [[ "$videoWidth" == "720" && "$videoHeight" == "576" ]]; then
videoPreset="DVPAL" && verbose "Input video has preset: DVPAL"
fi
# Enable resizing of videos
# #############################
# Fail if user sets more than one value
if [[ -n "${videoSize}" ]] && [[ -n "${height}" || -n "${width}" ]]; then
die "We can't set a 'height', 'width', and a 'size' at the same time."
fi
# if user sets both a height and width, run that as a videoSize variable
if [[ -n "${width}" ]] && [[ -n "${height}" ]]; then
videoSize="${width}x${height}" && verbose "videoSize=${width}x${height}"
unset width
unset height
fi
# downsize720
# Commonly used function to downsize 1080p to 720p
if [[ "${downsize720}" == "1" ]]; then
if [[ "${videoPreset}" == "1080p" ]]; then
videoSize="hd720" && verbose "videoSize=hd720"
else
warning "Skipping ${f}. It's not 1080p"
breakLoop
continue
fi
fi
# Do something when a user specifies a size
if [[ -n "${videoSize}" ]]; then
# Don't resize videos to their same size
if [[ "${videoSize}" == "hd720" ]] || [[ "${videoSize}" == "720" || "${videoSize}" == "1280x720" ]]; then
if [[ "$videoPreset" == "720p" ]]; then
notice ""${f}" is already 720p. Skipping...."
breakLoop
continue
fi
elif [[ "${videoSize}" == "hd1080" || "${videoSize}" == "1080" || "${videoSize}" == "1920x1080" ]]; then
if [[ "$videoPreset" == "1080p" ]]; then
notice ""${f}" is already 1080p. Skipping...."
breakLoop
continue
fi
fi
# Confirm if user wants to upscale their video
if [[ "${videoSize}" == "hd1080" || "${videoSize}" == "1080" ]]; then
userWidth="1920"
userHeight="1080"
elif [[ "${videoSize}" == "hd720" ]] || [[ "${videoSize}" == "720" ]]; then
userWidth="1280"
userHeight="720"
else
# break user's video size into a height and width
userWidth=$(echo ${videoSize} | cut -f1 -dx)
userHeight=$(echo ${videoSize} | cut -f2 -dx)
if [ "${userWidth}" -gt "${videoWidth}" ] || [ "${userHeight}" -gt "${videoHeight}" ]; then
seek_confirmation "Upscale "${f}" to "${videoSize}"? It is already "${videoWidth}"x"${videoHeight}"."
if is_not_confirmed; then
breakLoop
continue
fi
fi
fi
# Finally, set the resize variable
videoResize="-vf scale=${videoSize}" && verbose "videoResize='-vf scale=${videoSize}'"
fi
# Scaling variables
# ####################################
if is_not_empty "$height"; then
if [ "${height}" -gt "${videoHeight}" ]; then
seek_confirmation "Upscale "${f}" to height "${height}"? It is already "${videoWidth}"x"${videoHeight}"."
if is_not_confirmed; then
breakLoop
continue
fi
fi
videoResize="-vf scale=-1:${height}" && verbose "videoResize='-vf scale=-1:${height}'"
fi
if is_not_empty "$width"; then
if [ "${width}" -gt "${videoWidth}" ]; then
seek_confirmation "Upscale "${f}" to width "${width}"? It is already "${videoWidth}"x"${videoHeight}"."
if is_not_confirmed; then
breakLoop
continue
fi
fi
videoResize="-vf scale=${width}:-1" && verbose "videoResize='-vf scale=${width}:-1'"
fi
# Copy h264 when possible
# Save precious time by not re-encoding files that are already H264.
# ###########################
if [[ "${videoCodec}" == "h264" ]] && [[ -z "${videoResize}" ]]; then
videoCommand="-c:v copy" && verbose "videoCommand='-c:v copy'"
else
videoCommand="-c:v libx264 -crf 18 -preset slow" && verbose "videoCommand'-c:v libx264 -crf 18 -preset slow'"
fi
# Do the conversion
# ##########################
# Don't convert to self if no other options set
if [[ -z $height && -z $width && -z $videoSize && $downsize720 == "0" && "$outputFormat" == "$extension" ]]; then
warning "Can't convert a '"${extension}"' to itself. Skipping all '"${extension}"' files."
break
fi
doConvert # Invoke FFMpeg
# Unset variables
unset videoCodec
unset videoCodecLong
unset format
unset formatName
unset videoHeight
unset videoWidth
unset videoPreset
unset audioCodec
unset audioCodecLong
unset audioSampleRate
unset audioBitRate
breakLoop
done
breakLoop
done
}
convertMusic() {
for mt in "${audioTypes[@]}"; do
for f in *."${mt}"; do
if [[ -n "${userAudioFile}" ]]; then # TODO: Rewrite user video files and write function to detect user video or music
# Override the file search if user specifies a specific file from CLI.
f="${userAudioFile}"
fi
test -f "${f}" || continue # Ensure that what we've found is a file
extension="${f##*.}" # Grab file extension of input file
informationFile="${tmpDir}/${f}.json"
# For audio files, ensure that the user specifies an output format
if [[ -z ${userOutput} ]]; then
die "Please specify an output audio format using '-o, --output'"
fi
# JSON METADATA FOR EACH ASSET
######################################################################
verbose "Reading audio data and writing JSON to tmp"
# Output a JSON file for each video asset being parsed.
ffprobe -v quiet -print_format json -show_format -show_streams "${f}" >> "${informationFile}"
# uncomment the line below for debugging. It will write a json file for each file in the source directory
# ffprobe -v quiet -print_format json -show_format -show_streams "${f}" >> "${f}.json"
# Read the necessary information from the JSON
format="$(jq -r ".format.format_long_name" "${informationFile}")"
formatName="$(jq -r ".format.format_name" "${informationFile}")"
formatBit_Rate="$(jq -r ".format.bit_rate" "${informationFile}")"
if [ $(jq -r ".streams[0].codec_type" "${informationFile}") == "audio" ]; then
audioCodec="$(jq -r '.streams[0].codec_name' "${informationFile}")"
audioCodecLong="$(jq -r ".streams[0].codec_long_name" "${informationFile}")"
audioSampleRate="$(jq -r ".streams[0].sample_rate" "${informationFile}")"
audioBitRate="$(jq -r ".streams[0].bit_rate" "${informationFile}")"
elif [ $(jq -r ".streams[1].codec_type" "${informationFile}") == "audio" ]; then
audioCodec="$(jq -r '.streams[1].codec_name' "${informationFile}")"
audioCodecLong="$(jq -r ".streams[1].codec_long_name" "${informationFile}")"
audioSampleRate="$(jq -r ".streams[1].sample_rate" "${informationFile}")"
audioBitRate="$(jq -r ".streams[1].bit_rate" "${informationFile}")"
elif [ $(jq -r ".streams[2].codec_type" "${informationFile}") == "audio" ]; then
audioCodec="$(jq -r '.streams[2].codec_name' "${informationFile}")"
audioCodecLong="$(jq -r ".streams[2].codec_long_name" "${informationFile}")"
audioSampleRate="$(jq -r ".streams[2].sample_rate" "${informationFile}")"
audioBitRate="$(jq -r ".streams[2].bit_rate" "${informationFile}")"
else
warning "Missing audio information for '"$f"'. Inspect with 'ffprobe'."
ffprobe -v quiet -print_format json -show_format -show_streams "${f}"
safeExit
fi
# note on XLD: If you have XLD installed and configured, lossless audio conversion
# will be run using built-in XLD profiles. You can disable this by
# changing ensuring that XLD=0 in sections below.
#
# #############################################################
# Build the Conversion Command
# ########################################
# FLAC TO ALAC
if [[ "${userOutput,,}" == "alac" ]]; then
if type_exists "xlds"; then
XLD=1
# audioConvertCommand="--profile FLACtoALAC"
audioConvertCommand="-f alac" && verbose "Using XLD. audioConvertCommand = -f alac"
else
audioConvertCommand="-acodec alac" && verbose "Using ffmpeg. audioConvertCommand = -acodec alac"
outputFormat="m4a"
fi
elif [[ "${userOutput,,}" == "flac" ]]; then
if type_exists "xlds"; then
XLD=1
audioConvertCommand="-f flac" && verbose "Using XLD. audioConvertCommand = -f flac"
else
audioConvertCommand="-c:a flac" && verbose "Using ffmpeg. audioConvertCommand = -c:a flac"
fi
elif [[ "${userOutput,,}" == "aac" || "${userOutput,,}" == "m4a" ]]; then
# Pick the best aac audio encoder
if $(ffmpeg -version | grep enable-libfdk-aac >/dev/null); then
# set variable bit rate to '5', the highest
aacEncoder='libfdk_aac -vbr 5' && verbose "aacEncoder = libfdk_aac -vbr 5"
else
aacEncoder='libfaac -q:a 400' && verbose "aacEncoder = libfaac -q:a 400"
fi
if type_exists "xlds"; then
XLD=1
audioConvertCommand="-f aac" && verbose "using xld. audioConvertCommand = -f aac "
else
audioConvertCommand="-acodec ${aacEncoder}" && verbose "using ffmpeg. audioConvertCommand = -acodec ${aacEncoder}"
fi
elif [[ "${userOutput,,}" == "mp3" ]]; then
# Can we convert to mp3? Do we have an ffmpeg encoder?
if $(ffmpeg -version | grep enable-libmp3lame >/dev/null); then
mp3Encoder='libmp3lame' && verbose "mp3Encoder = libmp3lame"
else
warning "No workable ffmpeg mp3 encoder. Skipping ${f}..."
breakLoop
continue
fi
# Take user specified bitrate
if [ -n "$bitrate" ]; then
bitrate="${bitrate%k}k" # Ensure 'k' is at the end of any bitrate sent to ffmpeg
ffmpegBitrate="-b:a $bitrate" && verbose "bitrate = ${bitrate}"
audioConvertCommand="-acodec ${mp3Encoder} ${ffmpegBitrate}" && verbose "audioConvertCommand = -acodec ${mp3Encoder} ${ffmpegBitrate}"
else
audioConvertCommand="-acodec ${mp3Encoder} -qscale:a 0" && verbose "audioConvertCommand = -acodec ${mp3Encoder} -qscale:a 0"
fi
else
die "Unknown audio conversion format: ${outputFormat}"
fi
# Do the conversion
# ##########################
doConvert # Run the conversion function
# Unset variables
unset format
unset formatName
unset audioCodec
unset audioCodecLong
unset audioSampleRate
unset audioBitRate
breakLoop
done
breakLoop
done
}
# Run the functions
checkDependencies
identifyUserFile
userFormat
outputDir
convertVideo
convertMusic
####################################################
############### End Script Here ####################
}
############## Begin Options and Usage ###################
# Print usage
usage() {
echo -n "${scriptName} ${version} [OPTION]... [ARGUMENT]...
This is a master FFMPEG media conversion script. It will convert audio and video
into many different formats. It was written to eliminate the need to remember archaic
FFMPEG commands.
Default behavior is to parse through directories of files and take actions on multiple
files at a time. You can easily specify a specific file to act on if needed.
General Options:
-h, --help Display this help and exit
-d, --debug Runs script in BASH debug mode ('set -x')
--force Skip all user interaction. Implied 'Yes' to all actions.
-l, --log Print log to file
-q, --quiet Quiet (no output)
-v, --verbose Output more information. (Items echoed to 'verbose')
--safe Runs the script without actually invoking FFMPEG. Will simply print
the FFMPEG commands to the terminal
--version Output version information and exit
File Options:
-f, --file Specify a specific file to take actions on.
-i, --input Specify the specific media type to search for and take action
on. ('mov', 'mp4', 'mp3')
-o, --output Specify the output format for the file(s) to be converted to.
('mkv', 'mp4', 'm4a')
--delete Delete the original file after conversion.
--saveDir Specify a folder for the converted files to be saved to. Defaults to
the directory the script is invoked in.
Video Specific Options:
--size Set the size of the target file. Can be one of 'hd1080', 'hd720',
or 'HeightxWidth' (ie. 1920x1080)
--height Set a height in pixels to scale the target file.
--width Set a width in pixels to scale the target file.
--downsize720 Searches for 1080p videos and downsizes them to 720p. No need
for other scaling options. Used to reduce the size of video collections
when quality is not the primary need.
Audio Specific Options:
--bitrate Set a bit rate for audio conversions.
"
}
# Iterate over options breaking -ab into -a -b when needed and --foo=bar into
# --foo bar
optstring=h
unset options
while (($#)); do
case $1 in
# If option is of type -ab
-[!-]?*)
# Loop over each character starting with the second
for ((i=1; i < ${#1}; i++)); do
c=${1:i:1}
# Add current char to options
options+=("-$c")
# If option takes a required argument, and it's not the last char make
# the rest of the string its argument
if [[ $optstring = *"$c:"* && ${1:i+1} ]]; then
options+=("${1:i+1}")
break
fi
done
;;
# If option is of type --foo=bar
--?*=*) options+=("${1%%=*}" "${1#*=}") ;;
# add --endopts for --
--) options+=(--endopts) ;;
# Otherwise, nothing special
*) options+=("$1") ;;
esac
shift
done
set -- "${options[@]}"
unset options
# Print help if no arguments were passed.
# Uncomment to force arguments when invoking the script
[[ $# -eq 0 ]] && set -- "--help"
# Read the options and set stuff
while [[ $1 = -?* ]]; do
case $1 in
-f|--file) shift; userFile="$1" ;;
-i|--input) shift; MEDIATYPE="$1" ;;
-o|--output) shift; userOutput="$1" ;;
--safe) safeRun=1 ;;
--size) shift; videoSize="$1" ;;
--height) shift; height="$1" ;;
--width) shift; width="$1" ;;
--downsize720) downsize720=1 ;;
--delete) deleteOriginal=1 ;;
--saveDir) shift; saveDir="$1" ;;
--bitrate) shift; bitrate="$1" ;;
-h|--help) usage >&2; safeExit ;;
--force) force=1 ;;
--version) echo "$(basename $0) $version"; safeExit ;;
-v|--verbose) verbose=1 ;;
-l|--log) printLog=1 ;;
-q|--quiet) quiet=1 ;;
-d|--debug) debug=1;;
--endopts) shift; break ;;
*) die "invalid option: '$1'." ;;
esac
shift
done
# Store the remaining part as arguments.
args+=("$@")
############## End Options and Usage ###################
# ############# ############# #############
# ## TIME TO RUN THE SCRIPT ##
# ## ##
# ## You shouldn't need to edit anything ##
# ## beneath this line ##
# ## ##
# ############# ############# #############
# Trap bad exits with your cleanup function
trap trapCleanup EXIT INT TERM
# Exit on error. Append '||true' when you run the script if you expect an error.
set -o errexit
# Run in debug mode, if set
if [ "${debug}" == "1" ]; then
set -x
fi
# Exit on empty variable
if [ "${strict}" == "1" ]; then
set -o nounset
fi
# Bash will remember & return the highest exitcode in a chain of pipes.
# This way you can catch the error in case mysqldump fails in `mysqldump |gzip`, for example.
set -o pipefail
mainScript # Run your script
safeExit # Exit cleanly