2018-09-17 23:21:33 +00:00
#!/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"
2018-09-18 22:58:13 +00:00
CopyACodec = "FLAC|vorbis|flac"
2018-09-17 23:21:33 +00:00
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 "
2018-09-18 22:58:13 +00:00
local Arg = "-acodec"
local Codec = "codec"
local Bitrate = ""
2018-09-17 23:21:33 +00:00
2018-09-18 22:58:13 +00:00
if ! echo " $Info " | grep -Po " ( $CopyACodec ) " ; then
Codec = "libvorbis"
Bitrate = $( echo " $Info " | sed -r 's/.+ ([0-9]+) kb\/s.*/\1/g' | grep -Po '[0-9]+ kb/s' )
if ! [ [ -z $Bitrate ] ] ; then
if [ [ $Bitrate -lt 128 ] ] ; then
Bitrate = "128"
fi
Bitrate = " -b:a ${ Bitrate } k "
fi
2018-09-17 23:21:33 +00:00
fi
2018-09-18 22:58:13 +00:00
echo " $Arg $Codec $Bitrate "
2018-09-17 23:21:33 +00:00
}
# 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"
2018-09-18 22:58:13 +00:00
# For metadata:
# -metadata:s:v language="jpn" -metadata:s:a language="jpn" \
2018-09-17 23:21:33 +00:00
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 " )