Create ffencoder.sh
First version
This commit is contained in:
parent
8dd6a85f8b
commit
19c97a0fa5
273
ffencoder.sh
Normal file
273
ffencoder.sh
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script for mass video encoding with ffmpeg
|
||||||
|
|
||||||
|
DEF='\e[0m'; RED='\e[31m'; GRN='\e[32m'; WHT='\e[37m'; BLD='\e[1m';
|
||||||
|
|
||||||
|
ScriptName=$(echo "$0" | awk -F '/' '{print $NF;}')
|
||||||
|
ScriptDir=$(dirname $(readlink -e "$0"))
|
||||||
|
|
||||||
|
ExtRegex='.*\(mkv\|mp4\|wmv\|avi\)'
|
||||||
|
RateAbbr="ntsc|pal|qntsc|qpal|sntsc|spal|film|ntsc-film"
|
||||||
|
CopyACodec="FLAC|vorbis"
|
||||||
|
|
||||||
|
FFmpeg=$(which 'ffmpeg')
|
||||||
|
Wrapper=$(which 'x264-10bit')
|
||||||
|
|
||||||
|
Priority=""
|
||||||
|
Nice=""
|
||||||
|
Jobs=""
|
||||||
|
WriteLog=""
|
||||||
|
LogDir="Logs"
|
||||||
|
Log="/dev/null"
|
||||||
|
|
||||||
|
Resolution=""
|
||||||
|
OutputDir=""
|
||||||
|
InputDir=""
|
||||||
|
BitDepth=""
|
||||||
|
Bitrate=""
|
||||||
|
Audio=""
|
||||||
|
VCodec=""
|
||||||
|
Format=""
|
||||||
|
Fps=""
|
||||||
|
|
||||||
|
view_help ()
|
||||||
|
{
|
||||||
|
echo "Usage: ./$ScriptName [KEY]... [ARG]..."
|
||||||
|
echo "This is script for mass video encoding to libx264/mkv with custom bitdepth, bitrate, resolution and fps."
|
||||||
|
echo "-i, --input set the input directory (required)"
|
||||||
|
echo "-o, --output set output directory (required)"
|
||||||
|
echo "-d, --depth set bit depth (8 or 10)"
|
||||||
|
echo "-r, --resolution set resolution (<Width>x<Height>)"
|
||||||
|
echo "-f, --fps set fps (\"http://ffmpeg.org/ffmpeg-all.html#Video-rate\")"
|
||||||
|
echo "-b, --bitrate set bitrate (integer value with \"k\" or \"m\" postfix)"
|
||||||
|
echo "-p, --priority set priority (integer value from -19 to 20. Transferred to \"nice -n\")"
|
||||||
|
echo "-l, --log creates a directory with logs in output directory"
|
||||||
|
echo "-h, --help shows this page and exit"
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
check_args ()
|
||||||
|
{
|
||||||
|
local Errors=""
|
||||||
|
|
||||||
|
# InputDir
|
||||||
|
if [[ -z "$InputDir" ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} InputDir not set."; Errors="True"
|
||||||
|
elif [[ -d "$InputDir" ]]; then
|
||||||
|
InputDir=$(readlink -e "$InputDir")
|
||||||
|
if [[ $(find "$InputDir" -maxdepth 1 -type f -regex "$ExtRegex" | wc -l) == '0' ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} $InputDir does not contain any video files."; Errors="True"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} $Input not a directory."; Errors="True"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OutputDir
|
||||||
|
if [[ -z "$OutputDir" ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} OutputDir not set."; Errors="True"
|
||||||
|
elif [[ -d "$OutputDir" ]]; then
|
||||||
|
OutputDir=$(readlink -e "$OutputDir")
|
||||||
|
elif ! mkdir -p "$OutputDir"; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} Can't create ${OutputDir}!"; Errors="True"
|
||||||
|
else
|
||||||
|
OutputDir=$(readlink -e "$OutputDir")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# BitDepth
|
||||||
|
if [[ (! -z "$BitDepth") && ("$BitDepth" != '8' && "$BitDepth" != '10') ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} BitDepth must be '8' or '10', not \"${BitDepth}\"."; Errors="True"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Resolution
|
||||||
|
if ! echo "$Resolution" | grep -Po '^[0-9]+x[0-9]+$' &> /dev/null && [[ ! -z $Resolution ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} Unknown resolution format: \"$Resolution\".\n\tMust be: <widht>x<height>"; Errors="True"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fps
|
||||||
|
if ! echo "$Fps" | grep -Po "^([0-9]+(/[0-9]+)?|${RateAbbr})$" &> /dev/null && [[ ! -z $Fps ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} Unknown fps format: \"$Fps\".\n\tIt has to be a string in the format frame_rate_num/frame_rate_den, an integer number, a float number or a valid video frame rate abbreviation"; Errors="True"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Bitrate
|
||||||
|
if ! echo "$Bitrate" | grep -Po '^[0-9]+(k|m)?$' &> /dev/null && [[ ! -z $Bitrate ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} Unknown bitrate format: \"$Bitrate\".\n\tMust be integer value (with 'k' or 'm' postfix)."; Errors="True"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Priority
|
||||||
|
if [[ ! -z "$Priority" ]]; then
|
||||||
|
if ! echo "$Priority" | grep -P '[-0-9]{1,3}' &> /dev/null; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} Unknown priority: \"$Priority\".\n\tMust be integer value from -19 to 20."; Errors="True"
|
||||||
|
elif [[ "$Priority" -lt "-19" || "$Priority" -gt "20" ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} Priority must be from -19 to 20."; Errors="True"
|
||||||
|
else
|
||||||
|
Nice="nice -n $Priority"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Jobs
|
||||||
|
#if [[ ! -z "$Jobs" ]]; then
|
||||||
|
# if ! echo "$Jobs" | grep -P '^[0-9]+$' &> /dev/null; then
|
||||||
|
# echo -e "${BLD}${RED}Error:${DEF} Unknown jobs count: \"$Jobs\".\n\tMust be integer value from 1 to 99."; Errors="True"
|
||||||
|
# elif [[ "$Jobs" -lt "1" ]]; then
|
||||||
|
# echo -e "${BLD}${RED}Error:${DEF} Jobs count must be integer value from 1 to 99."; Errors="True"
|
||||||
|
# else
|
||||||
|
# Jobs="-threads $Jobs"
|
||||||
|
# fi
|
||||||
|
#fi
|
||||||
|
|
||||||
|
# VCodec/Format
|
||||||
|
VCodec="libx264"
|
||||||
|
Format="matroska"
|
||||||
|
|
||||||
|
if [[ ! -z $Errors ]]; then exit 3; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_exec ()
|
||||||
|
{
|
||||||
|
local Info="$1"
|
||||||
|
local Depth="8"
|
||||||
|
local Exec="$FFmpeg"
|
||||||
|
|
||||||
|
if [[ -z "$BitDepth" && ! -z $(echo "$Info" | grep -Po 'High 10') ]]; then
|
||||||
|
Depth='10'
|
||||||
|
else
|
||||||
|
Depth="$BitDepth"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$Depth" == "10" ]]; then
|
||||||
|
Exec="$Wrapper $Exec"
|
||||||
|
fi
|
||||||
|
echo "$Exec"
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_resolution ()
|
||||||
|
{
|
||||||
|
local Info="$1"
|
||||||
|
|
||||||
|
if [[ -z "$Resolution" ]]; then
|
||||||
|
echo "-s "$(echo "$Info" | sed -r 's/.+ ([0-9]+x[0-9]+)[, ].+/\1/g')
|
||||||
|
else
|
||||||
|
echo "-s $Resolution"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_fps ()
|
||||||
|
{
|
||||||
|
local Info="$1"
|
||||||
|
|
||||||
|
if [[ -z "$Fps" ]] && echo "$Info" | grep -P '[0-9\.] fps' &> /dev/null; then
|
||||||
|
Fps=$(echo "$Info" | sed -r 's/.+ ([0-9\.]+) fps.+/\1/g')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -z "$Fps" ]]; then
|
||||||
|
Fps="-r $Fps"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$Fps"
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_bitrate ()
|
||||||
|
{
|
||||||
|
local Info="$1"
|
||||||
|
|
||||||
|
if [[ -z "$Bitrate" ]]; then
|
||||||
|
echo "-b:v "$(echo "$Info" | sed -r 's/.+bitrate: ([0-9]+) ([kmg]?).+/\1\2/g')
|
||||||
|
else
|
||||||
|
echo "-b:v $Bitrate"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
auto_audio ()
|
||||||
|
{
|
||||||
|
local Info="$1"
|
||||||
|
local OnlyCopy=$(echo "$Info" | grep -Po '($CopyACodec)')
|
||||||
|
local ABitrate=$(echo "$Info" | sed -r 's/.+ ([0-9]+) kb\/s.*/\1/g')
|
||||||
|
|
||||||
|
if [[ $ABitrate -lt 128 ]]; then
|
||||||
|
ABitrate="128"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$OnlyCopy" ]]; then
|
||||||
|
echo "-acodec libvorbis -b:a ${ABitrate}k"
|
||||||
|
else
|
||||||
|
echo "-acodec copy"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check FFmpeg and Wrapper
|
||||||
|
if [[ -z "$FFmpeg" ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} ffmpeg not found."; exit 1
|
||||||
|
fi
|
||||||
|
if [[ -z "$Wrapper" ]]; then
|
||||||
|
echo -e "${BLD}${RED}Error:${DEF} 10bit wrapper not found."; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Processing arguments
|
||||||
|
while [[ $# -gt 0 ]]; do case $1 in
|
||||||
|
|
||||||
|
-i|--input ) InputDir="$2" ; shift; shift;;
|
||||||
|
-o|--output ) OutputDir="$2" ; shift; shift;;
|
||||||
|
-d|--depth ) BitDepth="$2" ; shift; shift;;
|
||||||
|
-r|--resolution ) Resolution="$2" ; shift; shift;;
|
||||||
|
-f|--fps ) Fps="$2" ; shift; shift;;
|
||||||
|
-b|--bitrate ) Bitrate="$2" ; shift; shift;;
|
||||||
|
-p|--priority ) Priority="$2" ; shift; shift;;
|
||||||
|
-l|--log ) WriteLog="True" ; shift;;
|
||||||
|
-h|--help ) view_help ; shift;;
|
||||||
|
# -j|--jobs ) Jobs="$2" ; shift; shift;;
|
||||||
|
# -a|--acodec ) ACodec="$2" ; shift; shift;;
|
||||||
|
# -v|--vcodec ) VCodec="$2" ; shift; shift;;
|
||||||
|
|
||||||
|
*) echo "Unknown argument: \"$1\""; exit 2;;
|
||||||
|
|
||||||
|
esac; done; check_args
|
||||||
|
|
||||||
|
LogDir="$OutputDir/$LogDir"
|
||||||
|
if [[ ! -z $WriteLog && ! -d "$LogDir" ]]; then
|
||||||
|
mkdir "$LogDir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Main
|
||||||
|
Index='1'
|
||||||
|
Count=$(find "$InputDir" -maxdepth 1 -type f -regex "$ExtRegex" | wc -l)
|
||||||
|
|
||||||
|
while IFS= read -r -d $'\n' InputFile <&3
|
||||||
|
do
|
||||||
|
InputFileName=$(echo "$InputFile" | awk -F '/' '{print $NF;}')
|
||||||
|
InputFileNameCrop=$(echo "$InputFileName" | sed -r 's/\.[a-Z0-9]+$//g')
|
||||||
|
|
||||||
|
printf "${BLD}[----] %#3d/%-3d${DEF} %s" "$Index" "$Count" "$InputFileNameCrop"
|
||||||
|
|
||||||
|
OutputFile="$OutputDir/$InputFileNameCrop.mkv"
|
||||||
|
|
||||||
|
if [[ ! -z $WriteLog ]]; then
|
||||||
|
Log="$LogDir/$InputFileNameCrop.log"
|
||||||
|
fi
|
||||||
|
|
||||||
|
InfoP1=$("$FFmpeg" -i "$InputFile" 2>&1 | grep 'Video:')
|
||||||
|
InfoP2=$("$FFmpeg" -i "$InputFile" 2>&1 | grep 'bitrate')
|
||||||
|
InfoP3=$("$FFmpeg" -i "$InputFile" 2>&1 | grep -P 'Stream #0:1.+Audio:')
|
||||||
|
|
||||||
|
Exec=$(auto_exec "$InfoP1")
|
||||||
|
|
||||||
|
# Uncomment for fast debug:
|
||||||
|
# VCodec="copy"
|
||||||
|
|
||||||
|
if $Nice $Jobs $Exec \
|
||||||
|
-i "$InputFile" \
|
||||||
|
-f "$Format" \
|
||||||
|
-vcodec "$VCodec" \
|
||||||
|
$(auto_audio "$InfoP3") \
|
||||||
|
$(auto_resolution "$InfoP1") \
|
||||||
|
$(auto_bitrate "$InfoP2") \
|
||||||
|
$(auto_fps "$InfoP3") \
|
||||||
|
-y "$OutputFile" &> "$Log"; then
|
||||||
|
printf "\r${BLD}[${GRN}DONE${DEF}${BLD}]\n"
|
||||||
|
else
|
||||||
|
printf "\r${BLD}[${RED}FAIL${DEF}${BLD}]\n"
|
||||||
|
#break
|
||||||
|
fi
|
||||||
|
((Index++))
|
||||||
|
done 3< <(find "$InputDir" -maxdepth 1 -type f -regex "$ExtRegex")
|
Loading…
Reference in New Issue
Block a user