#!/usr/bin/env bash
#
# Small script to encode to H.265/HEVC video using FFmpeg and libx265.
# Author: Grozdan "microchip" Nikolov <neutrino8@opensuse.org>
# Version: 2.9.8
# Date: 2016-11-10
#
# ffhevc is free software ; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation ; either version 2 of the License, or
# (at your option) any later version.
#
# ffhevc is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY ; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program ; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

green() { echo -e "\e[1;32m$1\e[0;39;49m"; }
brown() { echo -e "\e[0;33m$1\e[0;39;49m"; }
error() { echo -e "\e[1;31m$1\e[0;39;49m"; }

version="2.9.8"

CFG="$HOME/.ffhevc"
cfgversion="29"

genconfig_func() {
cat<<EOF>>"$CFG"
################# Config for ffhevc #################

# Version: $cfgversion - do not modify this line!

# Editor used for the -e option
EDITOR="vi"

# Output directory
# Can be overwritten at exec
# time if a path is provided
OUTDIR="$HOME"

# Container format extension
# Leave empty to ask each time
CONFMT="mkv"

# Nice value (0-19)
NICE="19"

# CRF value (0-51)
# Leave empty to ask each time
CRF="20"

# Automatically crop the input?
AUTOCROP="y"

# Enable software scaling support?
SCALE="y"

# Leave empty to ask each time or
# set a default software scaler
#
# fast_bilinear
# bilinear
# bicubic
# neighbor
# area
# bicublin
# gauss
# sinc
# lanczos
# spline
#
SCALER=""

# Support NTSC <-> PAL or
# NTSC <-> NTSC FPS conversion?
VID_FPS_CONVERT="y"

# Video filters
VID_DENOISE="y"
VID_DEBLOCK="y"
VID_ROTATE="y"
VID_DEINTERLACE="y"

# Audio filters
AUD_NORMALIZE="y"
AUD_VOLUME="y"
AUD_RESAMPLE="y"

# Max amount of audio tracks to support
# Any non-zero value will do. Set it
# to "auto" to ask for as many as
# detected audio tracks
MAX_AUD_TRACKS="2"

# Set to "n" to disable subtitles
# Note: not all containers support
# all types of subs!
SUBS="y"

# Max amount of subtitles to support
# Any non-zero value will do. Set it
# to "auto" to ask for as many as
# detected subtitles
MAX_SUBS="2"

# Copy original metadata from input?
METADATA="n"

# Copy chapters from input?
CHAPS="y"

# libx265 parameters. Modify, if needed,
# to fit your needs
# merange is calculated as: ctu size - 4 - 2 (- 1 if me=hex is used)
X265PARAMS="ref=4:me=star:bframes=6:rd=5:subme=6:merange=58:strong-intra-smoothing=1:ctu=64:sao=0:cu-lossless=1:cutree=1:rskip=1:max-merge=3:rc-lookahead=60:aq-mode=1:aq-strength=1.1:rdoq-level=1:psy-rdoq=5.5:psy-rd=3.0:limit-modes=1:limit-refs=1:rd-refine=1:deblock=-2,-2:weightb=1:weightp=1:rect=1:amp=0:wpp=1:pmode=0:pme=0:b-intra=1:b-adapt=2:b-pyramid=1:tskip-fast=0:fast-intra=0:early-skip=0:min-keyint=24:keyint=240"

# Leave empty to auto-detect ffmpeg/ffprobe or
# set your custom ones (eg, /path/to/bin/ffmpeg)
FFMPEG=""
FFPROBE=""

# Add a custom comment to your encodes
# Leave empty to disable/ask each time
COMMENT="Encoded with the help of ffhevc"

#####################################################
EOF
}

while getopts ":v :m: :c: :p: :t: :e :r :h" opt; do
	case "$opt" in
		v)
		echo "$version"
		exit 0
		;;
		m)
		case "$OPTARG" in
			[1-2]p|crf) true ;;
			*)
			error "-> Invalid mode!"
			error "-> Use: $(basename $0) -h"
			exit 1
			;;
		esac
		mode="$OPTARG"
		;;
		c)
		if [ ! -f "$OPTARG" ]; then
			error "-> No such file!"
			exit 1
		fi
		PRSTFILE="$OPTARG"
		;;
		p)
		case "$OPTARG" in
			ultrafast|superfast|veryfast|faster|fast|medium|slow|slower|veryslow|placebo) true ;;
			*)
			error "-> Invalid preset!"
			error "-> Use: $(basename $0) -h"
			exit 1
			;;
		esac
		vpreset="-preset:v $OPTARG"
		;;
		t)
		case "$OPTARG" in
			psnr|ssim|grain|zerolatency|fastdecode) true ;;
			*)
			error "-> Invalid tune profile!"
			error "-> Use: $(basename $0) -h"
			exit 1
			;;
		esac
		vtune="-tune:v $OPTARG"
		;;
		e)
		test ! -f "$CFG" && genconfig_func
		source "$CFG"
		$EDITOR "$CFG"
		exit 0
		;;
		r)
		rm -f "$CFG"
		genconfig_func
		green "-> Configuration file has been reset!"
		exit 0
		;;
		h)
		echo
		brown " -m <mode>"
		echo "      Specify a pass mode. If this option is not used, the script"
		echo "      defaults to crf mode. Valid pass modes are:"
		echo "          1p  (1-pass mode)"
		echo "          2p  (2-pass mode)"
		echo "          crf (constant rate factor mode)"
		echo
		brown " -c /path/to/file/preset.txt"
		echo "      Load a custom preset file. An example 'preset.txt' file"
		echo "      is included with the ffhevc package. This option can also"
		echo "      be used to load a custom configuration file instead of a"
		echo "      preset."
		echo
		brown " -p <preset>"
		echo "      Use a built-in x265 preset. Choose from the following:"
		echo "          ultrafast"
		echo "          superfast"
		echo "          veryfast"
		echo "          faster"
		echo "          fast"
		echo "          medium"
		echo "          slow"
		echo "          slower"
		echo "          veryslow"
		echo "          placebo"
		echo
		brown " -t <tune>"
		echo "      Use a built-in x265 tune profile. Choose from the following:"
		echo "          psnr"
		echo "          ssim"
		echo "          grain"
		echo "          zerolatency"
		echo "          fastdecode"
		echo
		brown " -e"
		echo "      Edit the configuration file."
		echo
		brown " -r"
		echo "      Reset the configuration file to its defaults."
		echo
		brown " -v"
		echo "      Display version and exit."
		echo
		brown " -h"
		echo "      Display this help and exit."
		echo
		exit 0
		;;
		\?)
		error "-> Invalid option!"
		error "-> Use: $(basename $0) -h"
		exit 1
		;;
		:)
		error "-> Option -$OPTARG requires an argument!"
		error "-> Use: $(basename $0) -h"
		exit 1
		;;
	esac
done

if [ ! -z "$PRSTFILE" ]; then
	if [ ! -z "$(grep '^X265PARAMS' "$PRSTFILE")" ]; then
		if [ ! -z "$vpreset" -o ! -z "$vtune" ]; then
			echo
			error "-> x265 presets/tune profiles are mutually exclusive with custom presets!"
			echo
			error "-> If you want to use a custom configuration file, don't add or comment"
			error "   out the X265PARAMS variable in it. Then you can use the built-in"
			error "   presets/tuning with that file."
			echo
			exit 1
		fi
	fi
fi

brown "  __  __ _"      
brown " / _|/ _| |__   _____   _____"
brown "| |_| |_| '_ \ / _ \ \ / / __|"
brown "|  _|  _| | | |  __/\ V / (__"
brown "|_| |_| |_| |_|\___| \_/ \___|"
brown "v$version by microchip"
echo

if [ -f "$CFG" ]; then
	cver=$(grep '^# Version' "$CFG" | awk '{print $3}')
	if [ "$cver" != "$cfgversion" ]; then
		mv -f "$CFG" "$CFG.old"
		genconfig_func
		error "Important notice! The configuration file of $(basename $0) located in"
		error "'$CFG' has been updated to the latest version!"
		echo
		error "If you have made any prior changes to the configuration file,"
		error "please commit those changes again and restart $(basename $0)!"
		error "If no changes were made, just restart $(basename $0) to get rid of"
		error "this notice."
		echo
		exit 0
	else
		source "$CFG"
	fi
else
	genconfig_func
	green "-> Config file generated in '$CFG'"
	green "-> Please set things up in there, if needed"
	echo
	source "$CFG"
fi

test ! -z "$PRSTFILE" && source "$PRSTFILE"

if [ ! -z "$FFMPEG" ]; then
	if [ ! -x "$FFMPEG" ]; then
		error "-> ffmpeg is missing from your system!"
		error "-> Check the config in '$CFG'"
		exit 1
	fi
else
	FFMPEG="$(which ffmpeg 2>/dev/null)"
	if [ ! -x "$FFMPEG" ]; then
		error "-> ffmpeg is missing from your system!"
		exit 1
	fi
fi

if [ ! -z "$FFPROBE" ]; then
	if [ ! -x "$FFPROBE" ]; then
		error "-> ffprobe is missing from your system!"
		error "-> Check the config in '$CFG'"
		exit 1
	fi
else
	FFPROBE="$(which ffprobe 2>/dev/null)"
	if [ ! -x "$FFPROBE" ]; then
		error "-> ffprobe is missing from your system!"
		exit 1
	fi
fi

printf "Specify the Input File: "
read -e input
if [ ! -f "$input" ]; then
	error "-> No such file!"
	exit 1
fi

printf "Specify a Name for the Output: "
read -e output
if [ -z "$output" ]; then
	error "-> You have to provide a name for the output!"
	exit 1
else
	if [ ! -z "$(echo "$output" | grep '/')" ]; then
		mkdir -p "$(dirname "$output")" 2>/dev/null
		if [ $? != 0 ]; then
			error "-> Could not create output directory!"
			exit 1
		fi
		OUTPUT="$output"
	else
		OUTPUT="$OUTDIR/$output"
	fi
	# Check if output dir is writable
	WRITE="$(dirname "$OUTPUT")/.ff_writable$$"
	touch "$WRITE" 2>/dev/null
	if [ $? != 0 ]; then
		error "-> Specified output directory is not writable by user '$(id -un)'"
		exit 1
	else
		rm -f "$WRITE"
	fi
	
	if [ -z "$CONFMT" ]; then
		printf "Which Container Format to use? [default is mkv]: "
		read confmt
		test -z "$confmt" && CONFMT="mkv" || CONFMT="$confmt"
	fi
	
	CONFMT="$(echo "$CONFMT" | tr '[:upper:]' '[:lower:]')"
	
	OUTPUT="$OUTPUT.$CONFMT"
	
	if [ -x "$(which realpath 2>/dev/null)" ]; then
		if [ "$(realpath -s "$input")" = "$(realpath -s "$OUTPUT")" ]; then
			error "-> Input file matches output file!"
			exit 1
		fi
	fi
	
	if [ -e "$OUTPUT" ]; then
		echo
		error "-> Renaming existing file to '$OUTPUT.old'"
		echo
		mv -f "$OUTPUT" "$OUTPUT.old"
	fi
	
	case "$CONFMT" in
		mp4|mov)		movflags="-movflags +faststart" ;;
		mkv|m2ts|mts|ts) 	true ;;
		*)
		error "-> HEVC video not supported by chosen container!"
		error "-> Supported containers are: mkv, mp4, mov, m2ts, mts and ts"
		error "-> Check your config file, if needed, in '$CFG'"
		exit 1
		;;
	esac
	
	printf "Output to Additional Container Formats? [y/N]: "
	read acf
	if [ "$acf" = "y" -o "$acf" = "Y" ]; then
		printf "Specify the Container Formats [example: mp4,mov,m2ts - press 'Enter' to skip]: "
		read econ
		test ! -z "$econ" && extracon="$(echo "$econ" | sed 's|,| |g' | tr '[:upper:]' '[:lower:]')"
		if [ ! -z "$extracon" ]; then
			container_func() {
				case "$1" in
					mp4|mov)
					green "-> Note: additional container $i supports the following audio codecs:"
					;;
				esac
				case "$1" in
					mp4) green "-> ac3|eac3|dts|aac|fdk-aac|mp3|vorbis|copy|nosound" ;;
					mov) green "-> ac3|eac3|dts|aac|fdk-aac|mp3|vorbis|flac|copy|nosound" ;;
					other)
					error "-> HEVC video not supported by the $i container!"
					error "-> Supported containers are: mkv, mp4, mov, m2ts, mts and ts"
					echo
					exit 1
					;;
				esac
			}
			
			for i in $extracon; do
				if [ "$i" = "$CONFMT" ]; then
					error "-> Additional container matches the main output container!"
					exit 1
				fi
				echo
				case "$i" in
					mkv|m2ts|ts)	green "-> Note: additional container $i supports all the audio codecs" ;;
					mp4)		container_func mp4 ;;
					mov)		container_func mov ;;
					*)		container_func other ;;
				esac
			done
			echo
		fi
	fi
	
	METATITLE="-metadata title=\"$(basename "${OUTPUT%.*}")\" -metadata:s:v:0 title=\"$(basename "${OUTPUT%.*}")\""
fi

printf "Specify a Genre for the Content [press 'Enter' to skip]: "
read genre
test ! -z "$genre" && METAGENRE="-metadata genre=\"$genre\""

printf "Specify the Year of the Content [press 'Enter' to skip]: "
read year
test ! -z "$year" && METAYEAR="-metadata year=\"$year\""

if [ -z "$COMMENT" ]; then
	printf "Specify a Comment [press 'Enter' to skip]: "
	read comment
	test ! -z "$comment" && COMMENT="$comment"
fi

if [ "$CONFMT" = "mkv" ]; then
	printf "Specify a Cover Image in JPG/PNG format [press 'Enter' to skip]: "
	read -e cover
	if [ ! -z "$cover" ]; then
		if [ ! -f "$cover" ]; then
			error "-> No such file: $cover"
			exit 1
		else
			case "$(basename "${cover##*.}" | tr '[:upper:]' '[:lower:]')" in
				jpeg|jpg)	img="jpeg" ;;
				png)		img="png" ;;
				*)
				error "-> Image format not supported!"
				exit 1
				;;
			esac
			METACOVER="-attach \"$cover\" -metadata:s:t mimetype=\"image/$img\""
		fi
	fi
fi

case "$mode" in
	[1-2]p)
	printf "Specify the desired Video Bitrate in kbps [default is 5000]: "
	read vbtr
	test -z "$vbtr" && vbitrate="5000" || vbitrate="$vbtr"
	;;
	*|"")
	if [ -z "$CRF" ]; then
		printf "Specify a CRF Value for the Encoding [0-51 - default is 20]: "
		read crf
		test -z "$crf" && CRF="20" || CRF="$crf"
	fi
	;;
esac

if [ "$VID_DENOISE" = "y" ]; then
	printf "Denoise the Input File? [y/N]: "
	read dn
	if [ "$dn" = "y" -o "$dn" = "Y" ]; then
		echo
		brown " Video Denoisers"
		brown " ~~~~~~~~~~~~~~~"
		echo " 0 -> hqdn3d        (3D spatial & temporal denoiser)"
		echo " 1 -> vaguedenoiser (spatial wavelet denoiser)"
		echo " 2 -> atadenoise    (adaptive temporal denoiser)"
		echo
		printf "Which Denoiser to use? [default is 0]: "
		read dfilter
		case "$dfilter" in
			0|"")
			printf "Specify the hqdn3d denoise values [default is 3:2:4]: "
			read dvalues
			test -z "$dvalues" && dv="3:2:4" || dv="$dvalues"
			denoise="hqdn3d=$dv,"
			;;
			1)
			printf "Specify the vaguedenoiser strength [0.0-5.0 - default is 0.8]: "
			read dvalues
			test -z "$dvalues" && dv="0.8" || dv="$dvalues"
			denoise="vaguedenoiser=threshold=$dv:method=soft:nsteps=4,"
			;;
			2)
			printf "Specify Threshold A and B for 1st plane [0-0.3:0-5 - default is 0.08:0.1]: "
			read t_1
			test -z "$t_1" && ata_1="0a=0.08:0b=0.1:" || ata_1="0a=$(echo "$t_1" | awk -F: '{print $1}'):0b=$(echo "$t_1" | awk -F: '{print $2}'):"
			printf "Specify Threshold A and B for 2nd plane [0-0.3:0-5 - default is 0.08:0.1]: "
			read t_2
			test -z "$t_2" && ata_2="1a=0.08:1b=0.1:" || ata_2="1a=$(echo "$t_2" | awk -F: '{print $1}'):1b=$(echo "$t_2" | awk -F: '{print $2}'):"
			printf "Specify Threshold A and B for 3rd plane [0-0.3:0-5 - default is 0.08:0.1]: "
			read t_3
			test -z "$t_3" && ata_3="2a=0.08:2b=0.1" || ata_3="2a=$(echo "$t_3" | awk -F: '{print $1}'):2b=$(echo "$t_3" | awk -F: '{print $2}')"
			denoise="atadenoise=$ata_1$ata_2$ata_3,"
			;;
			*)
			error "-> Invalid denoiser option!"
			exit 1
			;;
		esac
	fi
fi

if [ "$VID_DEBLOCK" = "y" ]; then
	printf "Deblock the Input File? [y/N]: "
	read db
	if [ "$db" = "y" -o "$db" = "Y" ]; then
		echo
		brown " Deblock Filters"
		brown " ~~~~~~~~~~~~~~~"
		echo " 0 -> spp"
		echo " 1 -> fspp"
		echo " 2 -> uspp"
		echo " 3 -> pp7"
		echo
		printf "Specify the Deblock Filter [default is 3]: "
		read dbfilter
		case "$dbfilter" in
			0)
			printf "Specify the Deblock Parameters [quality(0-6):qp - default is 3:11]: "
			read dp
			test -z "$dp" && dparam="3:11" || dparam="$dp"
			deblock="spp=quality=$(echo "$dparam" | awk -F: '{print $1}'):qp=$(echo "$dparam" | awk -F: '{print $2}'),"
			;;
			1)
			printf "Specify the Deblock Parameters [strength(-15-32):qp - default is 6:11]: "
			read dp
			test -z "$dp" && dparam="6:11" || dparam="$dp"
			deblock="fspp=strength=$(echo "$dparam" | awk -F: '{print $1}'):qp=$(echo "$dparam" | awk -F: '{print $2}'),"
			;;
			2)
			printf "Specify the Deblock Parameters [quality(0-8):qp - default is 3:11]: "
			read dp
			test -z "$dp" && dparam="3:11" || dparam="$dp"
			deblock="uspp=quality=$(echo "$dparam" | awk -F: '{print $1}'):qp=$(echo "$dparam" | awk -F: '{print $2}'),"
			;;
			3|"")
			printf "Specify the Deblock Quantization Parameter [default is 11]: "
			read dp
			test -z "$dp" && dparam="11" || dparam="$dp"
			deblock="pp7=qp=$dparam,"
			;;
			*)
			error "-> Invalid option!"
			exit 1
			;;
		esac
	fi
fi

# Used by mc/bobbing deinterlace and FPS conversion
video_fps_func() {
	GETFPS="$($FFPROBE -i "$input" -select_streams v:0 -show_entries stream=r_frame_rate 2>&1 | sed -n 's|^r_frame_rate=||p')"
}

# Used by mc/bobbing deinterlace and interlace-aware encoding
video_field_parity_func() {
	echo
	green "-> Detecting Field Parity..."
	FPAR="$($FFPROBE -i "$input" -show_streams -select_streams v:0 -show_frames -read_intervals %+7 2>&1 | sed -n 's|^field_order=||p' | tail -1)"
	case "$FPAR" in
		t*|T*)	fp="tff"; fparity="Top Field First (TFF)" ;;
		b*|B*)	fp="bff"; fparity="Bottom Field First (BFF)" ;;
		p*|P*)	fp="progressive"; fparity="Progressive" ;;
		""|*)	fp="???"; fparity="???" ;;
	esac
	green "-> Detected $fparity Parity"
	if [ "$fp" = "progressive" ]; then
		error "-> The video stream appears to be progressive"
		error "   but this may be a misdetection!"
	elif [ "$fp" = "???" ]; then
		error "-> Could not detect the Field Parity!"
	fi
	echo
	case "$fp" in
		bff)	defpar="bff" ;;
		*)	defpar="tff" ;;
	esac
}

if [ "$VID_DEINTERLACE" = "y" ]; then
	printf "Deinterlace the Input File? [y/N]: "
	read deint
	if [ "$deint" = "y" -o "$deint" = "Y" ]; then
		video_deinterlace_func() {
			printf "Use Motion-Compensation Deinterlacing? [y/N]: "
			read mcd
			if [ "$mcd" = "y" -o "$mcd" = "Y" ]; then
				video_field_parity_func
				printf "Specify the Field Parity of the Input File [tff/bff - default is $defpar]: "
				read par
				test -z "$par" && fpar="$defpar" || fpar="$par"
			fi
			case "$1" in
				ofps)	test ! -z "$fpar" && deinterlace="yadif=1,mcdeint=mode=medium:parity=$fpar:qp=10,framestep=step=2," || deinterlace="yadif=0," ;;
				bob)	test ! -z "$fpar" && deinterlace="yadif=1,mcdeint=mode=medium:parity=$fpar:qp=10," || deinterlace="yadif=1," ;;
			esac
		}
		echo
		brown " Deinterlace Methods"
		brown " ~~~~~~~~~~~~~~~~~~~"
		echo " 0 -> Deinterlace at original FPS"
		echo " 1 -> Bobbing (deinterlace at double FPS)"
		echo
		printf "Specify the Deinterlace Method [default is 0]: "
		read dmethod
		case "$dmethod" in
			0|"") video_deinterlace_func ofps ;;
			1)
			echo
			green "-> Detecting FPS value..."
			sleep 1
			video_fps_func
			if [ ! -z "$GETFPS" ]; then
				FPS1="$(echo "$GETFPS" | awk -F/ '{print $1}')"
				FPS2="$(echo "$GETFPS" | awk -F/ '{print $2}')"
				OFPS="$(($FPS1*2))/$FPS2"
				green "-> Detected: $FPS1/$FPS2 FPS"
				green "-> Setting output FPS to: $OFPS"
				ofps="-r $OFPS"
			else
				error "-> Could not detect the FPS value!"
			fi
			echo
			video_deinterlace_func bob
			bob="1"
			;;
			*)
			error "-> Invalid option!"
			exit 1
			;;
		esac
	fi
fi

if [ "$VID_ROTATE" = "y" ]; then
	printf "Rotate the Video? [y/N]: "
	read rot
	if [ "$rot" = "y" -o "$rot" = "Y" ]; then
		echo
		brown " Video Rotation"
		brown " ~~~~~~~~~~~~~~"
		echo " 0 -> 90° Counter Clockwise and Vertical Flip"
		echo " 1 -> 90° Clockwise"
		echo " 2 -> 90° Counter Clockwise"
		echo " 3 -> 90° Clockwise and Vertical Flip"
		echo " 4 -> 180°"
		echo
		printf "Specify the Transpose filter option [default is 0]: "
		read trans
		case "$trans" in
			0|"")	rotate="transpose=0," ;;
			1)	rotate="transpose=1," ;;
			2)	rotate="transpose=2," ;;
			3)	rotate="transpose=3," ;;
			4)	rotate="transpose=1,transpose=1," ;;
			*)
			error "-> Invalid option!"
			exit 1
			;;
		esac
	fi
fi

if [ -z "$deinterlace" ]; then
	printf "Enable Interlace-aware Encoding? [y/N]: "
	read intaw
	if [ "$intaw" = "y" -o "$intaw" = "Y" ]; then
		video_field_parity_func
		printf "Specify the Field Parity of the Input File [tff/bff - default is $defpar]: "
		read parity
		test -z "$parity" && interlaced=":interlaced=$defpar" || interlaced=":interlaced=$parity"
		X265PARAMS="$X265PARAMS$interlaced"
	fi
fi

if [ "$AUTOCROP" = "y" ]; then
	echo
	green "-> Detecting crop values..."
	VDUR="$($FFPROBE -i "$input" -select_streams v:0 -show_format 2>&1 | sed -n 's|^duration=||p' | awk -F. '{print $1}')"
	CROPVAL="$($FFMPEG -ss $(($VDUR/2)) -i "$input" -map 0:0 -vf cropdetect=24:4 -frames:v 1000 -f null - 2>&1 | awk '/crop/ {print $NF}' | awk -F= '{print $2}' | tail -1)"
	if [ ! -z "$CROPVAL" ]; then
		green "-> Found crop values: $CROPVAL"
	else
		error "-> Could not find the crop values!"
		CDEF="???"
	fi
	echo
	printf "Specify the Crop Values [default is $CROPVAL$CDEF]: "
	read cropval
	test -z "$cropval" && crop="crop=$CROPVAL," || crop="crop=$cropval,"
else
	printf "Specify the Crop Values [press 'Enter' to skip]: "
	read cropval
	test ! -z "$cropval" && crop="crop=$cropval,"
fi

if [ "$SCALE" = "y" ]; then
	printf "Specify the Desired Resolution [WxH - press 'Enter' to skip]: "
	read res
	if [ ! -z "$res" ]; then
		test -z "$interlaced" && scale="scale=$res," || scale="scale=$res:interl=1,"
		if [ -z "$SCALER" ]; then
			echo
			brown " Software Scalers"
			brown " ~~~~~~~~~~~~~~~~"
			echo " 0 -> Fast Bilinear"
			echo " 1 -> Bilinear"
			echo " 2 -> Bicubic"
			echo " 3 -> Neighbor"
			echo " 4 -> Area"
			echo " 5 -> Luma Bicubic/Chroma Bilinear"
			echo " 6 -> Gaussian"
			echo " 7 -> Sinc"
			echo " 8 -> Lanczos"
			echo " 9 -> Natural Bicubic Spline"
			echo
			printf "Sepcify the Software Scaler [default is 9]: "
			read swscaler
			case "$swscaler" in
				0)	scaler="fast_bilinear" ;;
				1)	scaler="bilinear" ;;
				2)	scaler="bicubic" ;;
				3)	scaler="neighbor" ;;
				4)	scaler="area" ;;
				5)	scaler="bicublin" ;;
				6)	scaler="gauss" ;;
				7)	scaler="sinc" ;;
				8)	scaler="lanczos" ;;
				9|"")	scaler="spline" ;;
				*)
				error "-> Invalid option!"
				exit 1
				;;
			esac
			sws="-sws_flags $scaler"
		else
			sws="-sws_flags $SCALER"
		fi
	fi
fi

printf "Define the Color Primaries? [y/N]: "
read cprim
if [ "$cprim" = "y" -o "$cprim" = "Y" ]; then
	echo
	brown " Color Primaries"
	brown " ~~~~~~~~~~~~~~~"
	echo " 0 -> smpte170m (NTSC DVD)"
	echo " 1 -> bt470bg (PAL DVD)"
	echo " 2 -> bt709 (HD/Full HD)"
	echo " 3 -> bt2020nc & bt2020-10 (4K/UHD)"
	echo " 4 -> bt2020nc & bt2020-12 (4K/UHD)"
	echo " 5 -> bt2020c & bt2020-10 (4K/UHD)"
	echo " 6 -> bt2020c & bt2020-12 (4K/UHD)"
	echo " 7 -> Undefined"
	echo
	printf "Specify the Color Primaries [default is 7]: "
	read colprim
	case "$colprim" in
		0)	matrix="smpte170m"; prim="smpte170m"; transfer="smpte170m" ;;
		1)	matrix="bt470bg"; prim="bt470bg"; transfer="bt470bg" ;;
		2)	matrix="bt709"; prim="bt709"; transfer="bt709" ;;
		3)	matrix="bt2020nc"; prim="bt2020"; transfer="bt2020-10" ;;
		4)	matrix="bt2020nc"; prim="bt2020"; transfer="bt2020-12" ;;
		5)	matrix="bt2020c"; prim="bt2020"; transfer="bt2020-10" ;;
		6)	matrix="bt2020c"; prim="bt2020"; transfer="bt2020-12" ;;
		7|"")	matrix="undef"; prim="undef"; transfer="undef" ;;
		*)
		error "-> Invalid option!"
		exit 1
		;;
	esac
	colorprim=":colormatrix=$matrix:colorprim=$prim:transfer=$transfer"
fi

if [ "$VID_FPS_CONVERT" = "y" ]; then
	# Not supported with interlaced encoding
	# and deinterlacing with a bobber
	if [ -z "$interlaced" -a -z "$bob" ]; then
		printf "Do an NTSC <-> PAL or NTSC <-> NTSC FPS conversion? [y/N]: "
		read fpscon
		if [ "$fpscon" = "y" -o "$fpscon" = "Y" ]; then
			echo
			green "-> Detecting FPS value..."
			sleep 1
			video_fps_func
			if [ ! -z "$GETFPS" ]; then
				green "-> Detected $GETFPS FPS"
			else
				error "-> Could not detect the FPS value!"
			fi
			case "$GETFPS" in
				24/1|25/1|24000/1001|30000/1001) true ;;
				""|*)
				echo
				error "-> Detected FPS is not supported yet!"
				error "-> Supported FPS are: 24/1, 25/1, 24000/1001 and 30000/1001"
				echo
				printf "Specify the FPS value of the Input File [no default!]: "
				read infps
				case "$infps" in
					24/1|25/1|24000/1001|30000/1001) true ;;
					""|*)
					error "-> No value or unsupported value given!"
					exit 1
					;;
				esac
				;;
			esac
			echo
			brown " FPS Conversion Filters"
			brown " ~~~~~~~~~~~~~~~~~~~~~~"
			echo " 0 -> fps (converts by duplicating/dropping of frames)"
			echo " 1 -> setpts + atempo (converts by PTS + audio speedup/down)"
			echo
			printf "Specify the FPS conversion method [default is 0]: "
			read fcm
			case "$fcm" in
				0|1|"") true ;;
				*)
				error "-> Invalid option!"
				exit 1
				;;
			esac
			echo
			brown " NTSC <-> PAL and NTSC <-> NTSC FPS Conversion"
			brown " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
			echo " 0 --> 23.976 FPS (24000/1001) to 24 FPS"
			echo " 1 --> 23.976 FPS (24000/1001) to 25 FPS"
			echo " 2 --> 23.976 FPS (24000/1001) to 29.970 FPS"
			echo
			echo " 3 --> 24 FPS to 23.976 FPS (24000/1001)"
			echo " 4 --> 24 FPS to 25 FPS"
			echo " 5 --> 24 FPS to 29.970 FPS (30000/1001)"
			echo
			echo " 6 --> 25 FPS to 23.976 FPS (24000/1001)"
			echo " 7 --> 25 FPS to 24 FPS"
			echo " 8 --> 25 FPS to 29.970 FPS (30000/1001)"
			echo
			echo " 9 --> 29.970 FPS (30000/1001) to 23.976 FPS (24000/1001)"
			echo " 10 -> 29.970 FPS (30000/1001) to 24 FPS"
			echo " 11 -> 29.970 FPS (30000/1001) to 25 FPS"
			echo
			printf "Specify the FPS Conversion option [press 'Enter' to skip]: "
			read fpsopt
			case "$fpsopt" in
				0)
				case "$fcm" in
					0|"")	fps="fps=fps=24," ;;
					1)	setpts="setpts=23976/24000*PTS,"; atempo="atempo=1.001001001," ;;
				esac
				ofps="-r 24/1"
				;;
				1)
				case "$fcm" in
					0|"")	fps="fps=fps=25," ;;
					1)	setpts="setpts=23976/25000*PTS,"; atempo="atempo=1.04270937604270937604," ;;
				esac
				ofps="-r 25/1"
				;;
				2)
				case "$fcm" in
					0|"")	fps="fps=fps=30000/1001," ;;
					1)	setpts="setpts=23976/29970*PTS,"; atempo="atempo=1.25," ;;
				esac
				ofps="-r 30000/1001"
				;;
				3)
				case "$fcm" in
					0|"")	fps="fps=fps=24000/1001," ;;
					1)	setpts="setpts=24000/23976*PTS,"; atempo="atempo=0.999," ;;
				esac
				ofps="-r 24000/1001"
				;;
				4)
				case "$fcm" in
					0|"")	fps="fps=fps=25," ;;
					1)	setpts="setpts=24000/25000*PTS,"; atempo="atempo=1.04166666667," ;;
				esac
				ofps="-r 25/1"
				;;
				5)
				case "$fcm" in
					0|"")	fps="fps=fps=30000/1001," ;;
					1)	setpts="setpts=24000/29970*PTS,"; atempo="atempo=1.24875," ;;
				esac
				ofps="-r 30000/1001"
				;;
				6)
				case "$fcm" in
					0|"")	fps="fps=fps=24000/1001," ;;
					1)	setpts="setpts=25000/23976*PTS,"; atempo="atempo=0.95904," ;;
				esac
				ofps="-r 24000/1001"
				;;
				7)
				case "$fcm" in
					0|"")	fps="fps=fps=24," ;;
					1)	setpts="setpts=25000/24000*PTS,"; atempo="atempo=0.96," ;;
				esac
				ofps="-r 24/1"
				;;
				8)
				case "$fcm" in
					0|"")	fps="fps=fps=30000/1001," ;;
					1)	setpts="setpts=25000/29970*PTS,"; atempo="atempo=1.1988," ;;
				esac
				ofps="-r 30000/1001"
				;;
				9)
				case "$fcm" in
					0|"")	fps="fps=fps=24000/1001," ;;
					1)	setpts="setpts=29970/23976*PTS,"; atempo="atempo=0.8," ;;
				esac
				ofps="-r 24000/1001"
				;;
				10)
				case "$fcm" in
					0|"")	fps="fps=fps=24," ;;
					1)	setpts="setpts=29970/24000*PTS,"; atempo="atempo=0.800800800801," ;;
				esac
				ofps="-r 24/1"
				;;
				11)
				case "$fcm" in
					0|"")	fps="fps=fps=25," ;;
					1)	setpts="setpts=29970/25000*PTS,"; atempo="atempo=0.83416750083416750083," ;;
				esac
				ofps="-r 25/1"
				;;
				"")
				true
				;;
				*)
				error "-> Invalid option!"
				exit 1
				;;
			esac
		fi
	fi
fi

################ Subs stuff #################

if [ "$SUBS" = "y" ]; then
	echo
	green "-> Detecting subtitles..."
	sleep 1
	SUBSDETECT="$($FFPROBE -i "$input" 2>&1 | grep 'Stream #' | grep 'Subtitle' | sed 's|    ||g')"
	if [ ! -z "$SUBSDETECT" ]; then
		SUBT="$(echo "$SUBSDETECT" | wc -l)"
		echo
		green "$SUBSDETECT"
		echo
		error "-> Note: not all containers support all types of subs!"
	else
		error "-> Could not detect any subtitles!"
		SUBT="0"
	fi
	echo
	if [ "$MAX_SUBS" = "auto" ]; then
		test "$SUBT" = "0" && MAX_SUBS="1" || MAX_SUBS="$SUBT"
	fi
	for i in $(eval echo "{1..$MAX_SUBS}"); do
		submapval[i]="$(($i-1))"
		printf "Sub $i: Specify a Subtitle to Copy (example: 0:2) [press 'Enter' to skip]: "
		read subnr[i]
		if [ ! -z "${subnr[i]}" ]; then
			printf "Sub $i: Specify the 3-letter Language Code for Metadata [press 'Enter' to skip]: "
			read slang[i]
			if [ ! -z "${slang[i]}" ]; then
				sublang[i]="-metadata:s:s:${submapval[i]} language=${slang[i]}"
			fi
			subcopy[i]="-map ${subnr[i]} -c:s:${submapval[i]} copy ${sublang[i]}"
			# Workaround for an ffmpeg disposition issue
			# where in some cases it sets subsequent tracks
			# as default.
			test "$i" = "1" && sdis="default" || sdis="none"
			subdis[i]="-disposition:s:${submapval[i]} $sdis"
		fi
	done
fi

test -z "${subcopy[*]}" && NOSUBS="-sn"

################ Audio stuff ################

echo
green "-> Detecting audio tracks..."
echo
sleep 1
AUDTRKS="$($FFPROBE -i "$input" 2>&1 | grep 'Stream #' | grep 'Audio' | sed 's|    ||g')"
if [ ! -z "$AUDTRKS" ]; then
	green "$AUDTRKS"
	ATRKS="$(echo "$AUDTRKS" | wc -l)"
else
	error "-> Could not detect any audio tracks!"
	ATRKS="0"
fi
echo

if [ "$MAX_AUD_TRACKS" = "auto" ]; then
	test "$ATRKS" = "0" && MAX_AUD_TRACKS="1" || MAX_AUD_TRACKS="$ATRKS"
fi

for i in $(eval echo "{1..$MAX_AUD_TRACKS}"); do
	audmapval[i]="$(($i-1))"
	if [ "$i" = "1" -a "$ATRKS" != "0" ]; then
		defaudtrk="default is 0:1"
	else
		defaudtrk="press 'Enter' to skip"
	fi
	printf "Track $i: Specify the Audio Track to Encode or Copy [$defaudtrk]: "
	read astream[i]
	if [ -z "${astream[1]}" -a "$ATRKS" != "0" ]; then
		astream[1]="0:1"
	fi
	if [ ! -z "${astream[i]}" ]; then
		printf "Track $i: Specify the 3-letter Language Code for Metadata [press 'Enter' to skip]: "
		read alang[i]
		if [ ! -z "${alang[i]}" ]; then
			audlang[i]="-metadata:s:a:${audmapval[i]} language=${alang[i]}"
		fi
	fi
done

test -z "$(echo "${astream[*]}" | sed 's| ||g')" && audparams[1]="-an"

if [ "${audparams[1]}" != "-an" ]; then
	echo
	brown " Available Audio Codecs"
	brown " ~~~~~~~~~~~~~~~~~~~~~~"
	echo " AC3 -----> Channels Support: 6 (codec max)"
	echo " EAC3 ----> Channels Support: 6 (encoder max)"
	echo " DTS -----> Channels Support: 6 (codec max)"
	echo " AAC -----> Channels Support: 8 (ffmpeg max)"
	echo " FDK-AAC -> Channels Support: 8 (ffmpeg max)"
	echo " Opus ----> Channels Support: 8 (ffmpeg max)"
	echo " Vorbis --> Channels Support: 8 (ffmpeg max)"
	echo " MP3 -----> Channels Support: 2 (codec max)"
	echo " TrueHD --> Channels Support: 6 (encoder max)"
	echo " FLAC ----> Channels Support: 8 (codec max)"
	echo " PCM -----> Channels Support: 8 (ffmpeg max)"
	echo " COPY ----> Channels Support: depends on audio codec"
	echo " NOSOUND -> Channels Support: N/A"
fi

for i in $(eval echo "{1..$MAX_AUD_TRACKS}"); do
	if [ ! -z "${astream[i]}" ]; then
		echo
		audmap[i]="-map ${astream[i]}"
		
		# Workaround for an ffmpeg disposition issue
		# where in some cases it flags subsequent
		# tracks as default.
		test "$i" = "1" && adis="default" || adis="none"
		auddis[i]="-disposition:a:${audmapval[i]} $adis"
		
		printf "Track $i: Specify the Audio Codec [default is AC3]: "
		read acodec[i]
		acodec[i]="$(echo "${acodec[i]}" | tr '[:upper:]' '[:lower:]')"
		case "${acodec[i]}" in
			ac3|"")
			acdc[i]="ac3"
			ameta[i]="AC-3"
			abropts[i]="192/384/448/640"
			abrdef[i]="640"
			;;
			eac3)
			acdc[i]="eac3"
			ameta[i]="E-AC-3"
			abropts[i]="32-6144"
			abrdef[i]="768"
			;;
			truehd)
			strict="-strict -2"
			acdc[i]="truehd"
			ameta[i]="TrueHD"
			abropts[i]="1000-18000"
			abrdef[i]="5000"
			skiptfs="1"
			;;
			dts)
			strict="-strict -2"
			acdc[i]="dca"
			ameta[i]="DTS"
			abropts[i]="754/1509"
			abrdef[i]="1509"
			;;
			aac)
			acdc[i]="aac"
			ameta[i]="LC-AAC"
			abropts[i]="32-512"
			abrdef[i]="448"
			;;
			fdk*)
			acdc[i]="libfdk_aac"
			abropts[i]="8-512"
			abrdef[i]="448"
			;;
			mp3)
			acdc[i]="libmp3lame"
			ameta[i]="MP3"
			abropts[i]="32-320"
			abrdef[i]="320"
			;;
			opus)
			acdc[i]="libopus"
			ameta[i]="Opus"
			abropts[i]="6-512"
			abrdef[i]="384"
			;;
			vorbis)
			acdc[i]="libvorbis"
			ameta[i]="Vorbis"
			abropts[i]="6-500"
			abrdef[i]="448"
			;;
			flac)
			acdc[i]="flac"
			ameta[i]="FLAC"
			abropts[i]="0-8"
			abrdef[i]="5"
			skiptfs="1"
			;;
			pcm)
			ameta[i]="PCM"
			skiptfs="1"
			;;
			copy)
			acdc[i]="copy"
			# FPS conversion is incompatible with audio stream copy for
			# obvious reasons. We can't speed up or slow down audio that's
			# being copied. Audio filters have no effect on stream copy.
			# We only clear the video filter and fps here. No need to
			# also clear the audio filter since it never reaches the
			# below $afilters filter chain.
			# Exception is the 'fps' filter, which seems to work fine
			# with audio copy and doesn't introduce any A/V desync,
			# according to my testing
			if [ ! -z "$setpts" ]; then
				skipsetpts="1"
				setpts=
				ofps=
			fi
			;;
			nosound)
			audparams[1]="-an"
			abitrate[1]="0"
			# nosound takes precedence so
			# clear any audio options given
			if [ $i -ge 2 ]; then
				for t in $(eval echo "{2..$MAX_AUD_TRACKS}"); do
					audparams[t]=
					auddis[t]=
				done
			fi
			break
			;;
			*)
			error "-> Unsupported audio codec: ${acodec[i]}"
			exit 1
			;;
		esac
		
		conerror_func() {
			if [ ! -z "$extracon" ]; then
				error "-> Additional container $c does not support ${acodec[i]} audio!"
			else
				error "-> The $c container does not support ${acodec[i]} audio!"
				error "-> Check your config file, if needed, in '$CFG'"
			fi
			error "-> See: https://en.wikipedia.org/wiki/Comparison_of_video_container_formats"
			exit 1
		}
		
		# mkv/m2ts/mts/ts are missing from the list since they
		# support all the audio codecs supported by the script
		for c in $CONFMT $extracon; do
			case "$c" in
				mp4)
				case "${acodec[i]}" in
					pcm|opus|flac|truehd) conerror_func ;;
				esac
				;;
				mov)
				case "${acodec[i]}" in
					pcm|opus|truehd) conerror_func ;;
				esac
				;;
			esac
		done
		
		if [ "${acodec[i]}" != "copy" ]; then
			case "${acodec[i]}" in
				fdk*)
				printf "Track $i: Which AAC Profile to Use? [LC/HE/HEv2 - default is LC]: "
				read aprof[i]
				case "${aprof[i]}" in
					lc|LC|"")	ameta[i]="LC-AAC"; aacprof[i]="aac_low" ;;
					he|HE)		ameta[i]="HE-AACv1"; aacprof[i]="aac_he" ;;
					hev2|HEv2|HEV2)	ameta[i]="HE-AACv2"; aacprof[i]="aac_he_v2" ;;
					*)
					error "- Invalid AAC profile!"
					exit 1
					;;
				esac
				audprofile[i]="-profile:a:${audmapval[i]} ${aacprof[i]} -afterburner:a:${audmapval[i]} 1"
				;;
				flac)
				printf "Track $i: Specify the FLAC Compression Level [${abropts[i]} - default is ${abrdef[i]}]: "
				read abr[i]
				test -z "${abr[i]}" && acomplevel[i]="${abrdef[i]}" || acomplevel[i]="${abr[i]}"
				audcomplevel[i]="-compression_level:a:${audmapval[i]} ${acomplevel[i]}"
				abtrmeta[i]="@ CL ${acomplevel[i]}"
				;;
				pcm)
				printf "Track $i: Which PCM Bit Depth to use? [16/24/32 - default is 24]: "
				read pcmbd[i]
				case "${pcmbd[i]}" in
					16)	acdc[i]="pcm_s16le"; abtrmeta[i]="(16 bit)" ;;
					24|"")	acdc[i]="pcm_s24le"; abtrmeta[i]="(24 bit)" ;;
					32)	acdc[i]="pcm_s32le"; abtrmeta[i]="(32 bit)" ;;
					*)
					error "-> Unsupported PCM Bit Depth!"
					exit 1
					;;
				esac
				;;
			esac
			
			case "${acodec[i]}" in
				ac3|eac3|truehd|dts|aac|fdk*|mp3|vorbis|opus|"")
				printf "Track $i: Specify the Audio Bitrate in kbps [${abropts[i]} - default is ${abrdef[i]}]: "
				read abr[i]
				test -z "${abr[i]}" && abitrate[i]="${abrdef[i]}k" || abitrate[i]="${abr[i]}k"
				audbtr[i]="-b:a:${audmapval[i]} ${abitrate[i]}"
				abtrmeta[i]="@ $(echo "${abitrate[i]}" | sed 's|k||') kbps"
				;;
			esac
			
			case "${acodec[i]}" in
				ac3|eac3|"")			chanrange[i]="1-6"; defchan[i]="6" ;;
				aac|opus|vorbis|flac|pcm)	chanrange[i]="1-8"; defchan[i]="8" ;;
				mp3)				chanrange[i]="1-2"; defchan[i]="2" ;;
				truehd)				chanrange[i]="2/5/6"; defchan[i]="6" ;;
				dts)				chanrange[i]="1/2/4/5/6"; defchan[i]="6" ;;
				fdk*)
				case "${aacprof[i]}" in
					aac_low|aac_he)		chanrange[i]="1-8"; defchan[i]="8" ;;
					*)			chanrange[i]="1-2"; defchan[i]="2" ;;
				esac
				;;
			esac
			
			printf "Track $i: How many Channels to Encode? [${chanrange[i]} - default is ${defchan[i]}]: "
			read achan[i]
			test -z "${achan[i]}" && ach[i]="${defchan[i]}" || ach[i]="${achan[i]}"
			case "${ach[i]}" in
				1)	chlayout[i]="mono"; achmeta[i]="Mono" ;;
				2)	chlayout[i]="stereo"; achmeta[i]="Stereo" ;;
				3)	chlayout[i]="3.0"; achmeta[i]="3.0" ;;
				4)	achmeta[i]="4.0"; test "${acdc[i]}" = "dca" && chlayout[i]="quad(side)" || chlayout[i]="quad" ;;
				5)	achmeta[i]="5.0"; test "${acdc[i]}" = "dca" && chlayout[i]="5.0(side)" || chlayout[i]="5.0" ;;
				6)	achmeta[i]="5.1"; test "${acdc[i]}" = "dca" && chlayout[i]="5.1(side)" || chlayout[i]="5.1" ;;
				7)	chlayout[i]="6.1"; achmeta[i]="6.1" ;;
				8)	chlayout[i]="7.1"; achmeta[i]="7.1" ;;
				*)
				error "-> ${ach[i]} channels not supported!"
				exit 1
				;;
			esac
			
			case "${acodec[i]}" in
				ac3|eac3|"")
				case "${ach[i]}" in
					[1-6]) true ;;
					*)
					case "${acodec[i]}" in
						ac3|"")	error "-> AC-3 supports only 1-6 channels!" ;;
						eac3)	error "-> E-AC-3 encoder in ffmpeg supports only 1-6 channels!" ;;
					esac
					exit 1
					;;
				esac
				;;
				truehd)
				case "${ach[i]}" in
					2|5|6) true ;;
					*)
					error "-> TrueHD encoder in ffmpeg supports only 2, 5 and 6 channels!"
					exit 1
					;;
				esac
				;;
				dts)
				case "${ach[i]}" in
					1|2|4|5|6) true ;;
					*)
					error "-> DTS encoder in ffmpeg supports only 1, 2, 4, 5 and 6 channels!"
					exit 1
					;;
				esac
				;;
				fdk*)
				case "${aacprof[i]}" in
					aac_he_v2)
					case "${ach[i]}" in
						1|2) true ;;
						*)
						error "-> HE-AACv2 supports only 1-2 channels!"
						exit 1
						;;
					esac
					;;
				esac
				;;
				mp3)
				case "${ach[i]}" in
					1|2) true ;;
					*)
					error "-> MP3 supports only 1-2 channels!"
					exit 1
					;;
				esac
				;;
			esac
			
			audmeta[i]="-metadata:s:a:${audmapval[i]} title=\"${ameta[i]} ${achmeta[i]} ${abtrmeta[i]}\""
			audchan[i]="-ac:a:${audmapval[i]} ${ach[i]} -channel_layout:a:${audmapval[i]} \"${chlayout[i]}\""
			
			if [ "$AUD_NORMALIZE" = "y" ]; then
				printf "Track $i: Normalize the Audio Volume? [y/N]: "
				read anorm[i]
				if [ "${anorm[i]}" = "y" -o "${anorm[i]}" = "Y" ]; then
					anormalize[i]="dynaudnorm=n=0,"
				fi
			fi
			
			if [ "$AUD_VOLUME" = "y" ]; then
				printf "Track $i: Set the Audio Volume? [y/N]: "
				read setavol[i]
				if [ "${setavol[i]}" = "y" -o "${setavol[i]}" = "Y" ]; then
					printf "Track $i: Specify the Audio Volume filter value in dB [-100-100 - default is 4.0]: "
					read avol[i]
					test -z "${avol[i]}" && audvol[i]="4" || audvol[i]="${avol[i]}"
					avolume[i]="volume=${audvol[i]}dB,"
				fi
			fi
			
			if [ "$AUD_RESAMPLE" = "y" ]; then
				printf "Track $i: Resample the Audio? [y/N]: "
				read ares[i]
				if [ "${ares[i]}" = "y" -o "${ares[i]}" = "Y" ]; then
					echo
					green "-> Track $i: detecting audio sample rate..."
					sleep 1
					aid[i]="$(($(echo "${astream[i]}" | awk -F: '{print $2}')-1))"
					ASR[i]="$($FFPROBE -i "$input" -show_streams -select_streams a:${aid[i]} 2>&1 | sed -n 's|^sample_rate=||p')"
					if [ ! -z "${ASR[i]}" ]; then
						green "-> Track $i: detected ${ASR[i]} Hz"
					else
						error "-> Track $i: could not detect the audio sample rate!"
					fi
					echo
					brown " Supported Sample Rates"
					brown " ~~~~~~~~~~~~~~~~~~~~~~"
					case "${acodec[i]}" in
						ac3|eac3|"")
						echo " 0 -> 32000 Hz"
						echo " 1 -> 44100 Hz"
						echo " 2 -> 48000 Hz"
						echo
						printf "Track $i: Specify the Audio Sample Rate option [default is 2]: "
						read arate[i]
						case "${arate[i]}" in
							0)	audhz[i]="32000" ;;
							1)	audhz[i]="44100" ;;
							2|"")	audhz[i]="48000" ;;
							*)
							error "-> Invalid option!"
							exit 1
							;;
						esac
						;;
						mp3|dts)
						echo " 0 -> 8000 Hz     5 -> 24000 Hz"
						echo " 1 -> 11025 Hz    6 -> 32000 Hz"
						echo " 2 -> 12000 Hz    7 -> 44100 Hz"
						echo " 3 -> 16000 Hz    8 -> 48000 Hz"
						echo " 4 -> 22050 Hz"
						echo
						printf "Track $i: Specify the Audio Sample Rate option [default is 8]: "
						read arate[i]
						case "${arate[i]}" in
							0)	audhz[i]="8000" ;;
							1)	audhz[i]="11025" ;;
							2)	audhz[i]="12000" ;;
							3)	audhz[i]="16000" ;;
							4)	audhz[i]="22050" ;;
							5)	audhz[i]="24000" ;;
							6)	audhz[i]="32000" ;;
							7)	audhz[i]="44100" ;;
							8|"")	audhz[i]="48000" ;;
							*)
							error "-> Invalid option!"
							exit 1
							;;
						esac
						;;
						aac|fdk*)
						echo " 0 -> 7350 Hz     5 -> 22050 Hz    10 -> 64000 Hz"
						echo " 1 -> 8000 Hz     6 -> 24000 Hz    11 -> 88200 Hz"
						echo " 2 -> 11025 Hz    7 -> 32000 Hz    12 -> 96000 Hz"
						echo " 3 -> 12000 Hz    8 -> 44100 Hz"
						echo " 4 -> 16000 Hz    9 -> 48000 Hz"
						echo
						printf "Track $i: Specify the Audio Sample Rate option [default is 9]: "
						read arate[i]
						case "${arate[i]}" in
							0)	audhz[i]="7350" ;;
							1)	audhz[i]="8000" ;;
							2)	audhz[i]="11025" ;;
							3)	audhz[i]="12000" ;;
							4)	audhz[i]="16000" ;;
							5)	audhz[i]="22050" ;;
							6)	audhz[i]="24000" ;;
							7)	audhz[i]="32000" ;;
							8)	audhz[i]="44100" ;;
							9|"")	audhz[i]="48000" ;;
							10)	audhz[i]="64000" ;;
							11)	audhz[i]="88200" ;;
							12)	audhz[i]="96000" ;;
							*)
							error "-> Invalid option!"
							exit 1
							;;
						esac
						;;
						flac)
						echo " 0 -> 8000 Hz      4 -> 32000 Hz     8 -> 96000 Hz"
						echo " 1 -> 16000 Hz     5 -> 44100 Hz     9 -> 176400 Hz"
						echo " 2 -> 22050 Hz     6 -> 48000 Hz     10 -> 192000 Hz"
						echo " 3 -> 24000 Hz     7 -> 88200 Hz"
						echo
						printf "Track $i: Specify the Audio Sample Rate option [default is 6]: "
						read arate[i]
						case "${arate[i]}" in
							0)	audhz[i]="8000" ;;
							1)	audhz[i]="16000" ;;
							2)	audhz[i]="22050" ;;
							3)	audhz[i]="24000" ;;
							4)	audhz[i]="32000" ;;
							5)	audhz[i]="44100" ;;
							6|"")	audhz[i]="48000" ;;
							7)	audhz[i]="88200" ;;
							8)	audhz[i]="96000" ;;
							9)	audhz[i]="176400" ;;
							10)	audhz[i]="192000" ;;
							*)
							error "-> Invalid option!"
							exit 1
							;;
						esac
						;;
						opus)
						echo " 0 -> 8000 Hz"
						echo " 1 -> 12000 Hz"
						echo " 2 -> 16000 Hz"
						echo " 3 -> 24000 Hz "
						echo " 4 -> 48000 Hz"
						echo
						printf "Track $i: Specify the Audio Sample Rate option [default is 4]: "
						read arate[i]
						case "${arate[i]}" in
							0)	audhz[i]="8000" ;;
							1)	audhz[i]="12000" ;;
							2)	audhz[i]="16000" ;;
							3)	audhz[i]="24000" ;;
							4|"")	audhz[i]="48000" ;;
							*)
							error "-> Invalid option!"
							exit 1
							;;
						esac
						;;
						truehd)
						echo " 0 -> 44100 Hz     3 -> 96000 Hz "
						echo " 1 -> 48000 Hz     4 -> 176400 Hz"
						echo " 2 -> 88200 Hz     5 -> 192000 Hz"
						echo
						printf "Track $i: Specify the Audio Sample Rate option [default is 1]: "
						read arate[i]
						case "${arate[i]}" in
							0)	audhz[i]="44100" ;;
							1|"")	audhz[i]="48000" ;;
							2)	audhz[i]="88200" ;;
							3)	audhz[i]="96000" ;;
							4)	audhz[i]="176400" ;;
							5)	audhz[i]="192000" ;;
							*)
							error "-> Invalid option!"
							exit 1
							;;
						esac
						;;
						vorbis|pcm)
						echo " 0 -> 8000 Hz     5 -> 24000 Hz    10 -> 88200 Hz"
						echo " 1 -> 11025 Hz    6 -> 32000 Hz    11 -> 96000 Hz"
						echo " 2 -> 12000 Hz    7 -> 44100 Hz    12 -> 176400 Hz"
						echo " 3 -> 16000 Hz    8 -> 48000 Hz    13 -> 192000 Hz"
						echo " 4 -> 22050 Hz    9 -> 64000 Hz"
						echo
						printf "Track $i: Specify the Audio Sample Rate option [default is 8]: "
						read arate[i]
						case "${arate[i]}" in
							0)	audhz[i]="8000" ;;
							1)	audhz[i]="11025" ;;
							2)	audhz[i]="12000" ;;
							3)	audhz[i]="16000" ;;
							4)	audhz[i]="22050" ;;
							5)	audhz[i]="24000" ;;
							6)	audhz[i]="32000" ;;
							7)	audhz[i]="44100" ;;
							8|"")	audhz[i]="48000" ;;
							9)	audhz[i]="64000" ;;
							10)	audhz[i]="88200" ;;
							11)	audhz[i]="96000" ;;
							12)	audhz[i]="176400" ;;
							13)	audhz[i]="192000" ;;
							*)
							error "-> Invalid option!"
							exit 1
							;;
						esac
						;;
					esac
					aresample[i]="aresample=${audhz[i]},"
				fi
			fi
			
			afilters[i]="$(echo "${aresample[i]}${anormalize[i]}${avolume[i]}$atempo" | sed 's|,$||')"
			
			test ! -z "${afilters[i]}" && audfilters[i]="-filter:a:${audmapval[i]} ${afilters[i]}"

		fi
		
		audparams[i]="${audmap[i]} -c:a:${audmapval[i]} ${acdc[i]} ${audprofile[i]} ${audcomplevel[i]} ${audbtr[i]} ${audchan[i]} ${audfilters[i]} ${audlang[i]} ${audmeta[i]}"
	fi
done

if [ ! -z "$skipsetpts" ]; then
	echo
	error "-> FPS conversion with the 'setpts' and 'atempo' filters has"
	error "   been disabled as it is incompatible with audio stream copy!"
fi

case "$mode" in
	[1-2]p)
	# Haven't found a reliable way to make it work with
	# FLAC and PCM audio so just skip this if one of
	# these audio codecs is chosen. Patch welcome
	# In case of TrueHD, while we support setting the
	# bitrate, that codec is variable in nature and
	# the actual bitrate can wildly fluctuate, which
	# will result in miscalculation for the target
	# size by an unknown amount
	if [ -z "$skiptfs" ]; then
		echo
		printf "Set a Target File Size? [y/N]: "
		read tfs
		if [ "$tfs" = "y" -o "$tfs" = "Y" ]; then
			printf "Specify the Target File Size in MiB [default is 5120]: "
			read tsize
			test -z "$tsize" && target="5120" || target="$tsize"
			VLENGTH="$($FFPROBE -i "$input" -select_streams v:0 -show_format 2>&1 | sed -n 's|^duration=||p' | awk -F. '{print $1}')"
			if [ -z "$VLENGTH" ]; then
				echo
				error "-> Could not detect video length!"
				error "-> Skipping bitrate calculation!"
			else
				# Audio copy, get bitrate
				for i in $(eval echo "{1..$MAX_AUD_TRACKS}"); do
					if [ "${acodec[i]}" = "copy" ]; then
						aid[i]="$(($(echo "${astream[i]}" | awk -F: '{print $2}')-1))"
						abtr[i]="$($FFPROBE -i "$input" -show_streams -select_streams a:${aid[i]} 2>&1 | sed -n 's|^bit_rate=||p')"
						case "${abtr[i]}" in
							[1-9]*)	abitrate[i]="$((${abtr[i]}/1000))" ;;
							""|*)	abitrate[i]="0" ;;
						esac
					fi
				done
				AUDBTR="$(($(echo "${abitrate[*]}" | sed 's|k||g; s| |+|g')))"
				VBITRATE="$((($target*8192/$VLENGTH)-$AUDBTR))"
				echo
				green "-> Video length is: $(($VLENGTH/60)) minutes or $VLENGTH seconds"
				green "-> Total audio bitrate is: $AUDBTR kbps"
				green "-> Estimated video bitrate for $target MiB: $VBITRATE kbps"
				echo
				printf "Specify the Video Bitrate in kbps [default is $VBITRATE]: "
				read vb
				test -z "$vb" && vbitrate="$VBITRATE" || vbitrate="$vb"
			fi
		fi
	fi
	;;
esac

test "$METADATA" = "n" && MDATA="-map_metadata -1"

test "$CHAPS" = "n" && CHPS="-map_chapters -1"

vidfilters="$(echo "$deinterlace$crop$deblock$denoise$scale$rotate$setpts$fps" | sed 's|,$||')"

test ! -z "$vidfilters" && vfilters="-vf $vidfilters"

test ! -z "$vpreset" && X265PARAMS="$colorprim$interlaced $vpreset" || X265PARAMS=":$X265PARAMS$colorprim"

test ! -z "$COMMENT" && METACOMMENT="-metadata comment=\"$COMMENT\""

# Small counter :)
counter_func() {
	for i in 5 4 3 2 1 0; do
		sleep 1 && echo -n "$i "
	done
}

# Set counter color
color_func() {
	BLUE="\033[01;34m"
	NORMAL="\e[0;0m"
	case "$1" in
		blue) printf "$BLUE" ;;
		normal) echo -ne "$NORMAL" ;;
	esac
}

case "$mode" in
	1p)	pass="1-pass" ;;
	2p)	pass="2-pass" ;;
	crf|"")	pass="CRF"; mode="crf" ;;
esac

echo
green "-> Starting to encode in $pass mode..."
green "-> Outputting to: $OUTPUT"
echo
color_func blue && printf "Starting to encode in: " && counter_func
color_func normal && echo

OUTFILE="$(dirname "$OUTPUT")/$(basename "${OUTPUT%.*}" | sed 's| |_|g')"

encoder_func() {
	case "$1" in
		1p|crf)
		test "$mode" = "1p" && pmode="bitrate=$vbitrate" || pmode="crf=$CRF"
		OPTS1="-map 0:0 -disposition:v:0 default $ofps $NOSUBS $MDATA $CHPS $METATITLE $METAGENRE $METAYEAR $METACOMMENT $vfilters $sws"
		OPTS2="${audparams[*]} ${auddis[*]} ${subcopy[*]} ${subdis[*]} $strict $movflags $METACOVER \"$OUTPUT\""
		;;
		2p)
		passone="stats=\"$OUTFILE.log\":pass=1:bitrate=$vbitrate"
		passtwo="stats=\"$OUTFILE.log\":pass=2:bitrate=$vbitrate"
		OPTS1="-map 0:0"
		OPTS2="-an -f null -y /dev/null"
		OPTS3="-map 0:0 -disposition:v:0 default $ofps $NOSUBS $MDATA $CHPS $METATITLE $METAGENRE $METAYEAR $METACOMMENT $vfilters $sws"
		OPTS4="${audparams[*]} ${auddis[*]} ${subcopy[*]} ${subdis[*]} $strict $movflags $METACOVER \"$OUTPUT\""
		;;
	esac
	echo "nice -n $NICE $FFMPEG -i \"$input\" $OPTS1 -c:v libx265 -x265-params $pmode$passone$X265PARAMS $vtune $OPTS2"
	case "$1" in
		2p)
		echo
		echo "nice -n $NICE $FFMPEG -i \"$input\" $OPTS3 -c:v libx265 -x265-params $passtwo$X265PARAMS $vtune $OPTS4"
		;;
	esac
}

echo "#!/usr/bin/env bash" > "$OUTFILE.sh"
echo "" >> "$OUTFILE.sh"
encoder_func $mode >> "$OUTFILE.sh"
echo "" >> "$OUTFILE.sh"
if [ ! -z "$extracon" ]; then
	echo "grn() { echo -e \"\e[1;32m\$1\e[0;39;49m\"; }" >> "$OUTFILE.sh"
	echo "red() { echo -e \"\e[1;31m\$1\e[0;39;49m\"; }" >> "$OUTFILE.sh"
	for i in $extracon; do
		echo "" >> "$OUTFILE.sh"
		echo "echo" >> "$OUTFILE.sh"
		echo "grn \"-> Converting to $i...\"" >> "$OUTFILE.sh"
		echo "" >> "$OUTFILE.sh"
		echo "$FFMPEG -i \"$OUTPUT\" -map 0 -c copy \"${OUTPUT%.*}.$i\" >/dev/null 2>&1" >> "$OUTFILE.sh"
		echo "test \"\$?\" = \"0\" && grn \"-> Done\" || red \"-> Failed!\"" >> "$OUTFILE.sh"
	done
	echo "echo" >> "$OUTFILE.sh"
fi
chmod +x "$OUTFILE.sh"

source "$OUTFILE.sh"
