FFmpeg wrapper to encode upon some conditions.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
7.0 KiB
Raw

#!/bin/bash
function displayHelp {
echo -e "Encode If Needed is a warper for FFmpeg to encode upon some conditions."
echo -e "USAGE: ein [OPTION] [INPUT]"
echo -e "DESCRIPTION:"
echo -e "By default, FFmpeg encode a file regardless of the fact that the"
echo -e "original and selected codec are the same. Although it may be be a"
echo -e "desired outcome, it can lead to unnecessary operations losing time"
echo -e "and quality."
echo -e "This script allow the user to specified a desired codec for audio"
echo -e "and video, only if either of those are not present an encoding will be"
echo -e "triggered."
echo -e "Example if the desired codecs are aac/h264 and the source file is wmav2"
echo -e "/h264 then the file will be encoded with aac and the h264 stream copied."
echo -e "Warning, by default no output is set, use the \"-d\" option or specify"
echo -e "the output file with \"-o\"."
echo -e "Errors generated by FFmpeg will be put in [INPUT].error.txt"
echo -e "[INPUT] can be one or multiple file(s) or directory(ies)."
echo -e "OPTION:"
echo -e "-a\tDesited audio codec like aac."
echo -e "-v\tDesited video codec like aac."
echo -e "-b\tArgument pass to FFmpeg if the audio codec specified by \"-a\""
echo -e "\tdon't match."
echo -e "-b\tArgument pass to FFmpeg if the video codec specified by \"-a\""
echo -e "\tdon't match."
echo -e "-d\tOptional output directory for the encoded file(s)."
echo -e "\tThe original filename will be used."
echo -e "\tMake sure the directory exist and that you have write access."
echo -e "-e\tUsed with \"-d\" to specified the container output file."
echo -e "\tBy default mkv will be used."
echo -e "-k\tOptional directory for original files kept \"as is\"."
echo -e "-f\tOptional directory for original files processed."
echo -e "-q\tReduce the verbosity."
echo -e "-h\tDisplay this help."
echo -e "EXAMPLE:"
echo -e "\t-a aac -b \"-c:a aac -b:a 48k\" \\"
echo -e "\t-v h264 -u \"-c:v libx264 -crf 23\" \\"
echo -e "\t-d /tmp/ \\"
echo -e "\t[FILE]"
echo -e "Will result in the encoding of the file(s) [FILE] if either their audio"
echo -e "codec is not \"aac\" or their video codec is not \"h264\". The result"
echo -e "encoded file(s) (if created) will have the same name as the original(s)"
echo -e "and be placed in the \"/tmp\" folder."
}
#"codec" will always matching thus allowing to specified only audio or video codec
audioCodecDesired="codec"
videoCodecDesired="codec"
audioParameter=""
videoParameter=""
outputDirectory=""
outputExtension="mkv"
goodAsIsDirectory=""
processedDirectory=""
optionalParameter=""
verbose=1
fileCount=0
errorCount=0
directoryCount=0
unencodedCount=0
no_args=1
while getopts a:v:b:u:d:e:o:k:f:qh option
do
case $option in
(a)
audioCodecDesired=$OPTARG;;
(v)
videoCodecDesired=$OPTARG;;
(b)
audioParameter=$OPTARG;;
(u)
videoParameter=$OPTARG;;
(d)
outputDirectory=$OPTARG;;
(e)
outputExtension=$OPTARG;;
(k)
goodAsIsDirectory=$OPTARG;;
(f)
processedDirectory=$OPTARG;;
(o)
optionalParameter=$OPTARG;;
(q)
verbose=0;;
(h)
(*)
displayHelp
exit;;
esac
no_args=0
done
shift $((OPTIND -1))
function processFile {
basename=$(basename "$@")
verbose $basename
errorFile="$basename.error.txt"
#Retrieve audio and video codec for the first stream of each
aCodec=$(ffprobe -select_streams a:0 -show_entries stream=codec_name -i "$@" -v error|head -n 2|tail -n 1)
vCodec=$(ffprobe -select_streams v:0 -show_entries stream=codec_name -i "$@" -v error|head -n 2|tail -n 1)
prefix="codec_name="
verboseAudio=$(echo -e "\t"$aCodec | sed -e "s/$prefix/Audio /")
verboseVideo=$(echo -e "\t"$vCodec | sed -e "s/$prefix/Video /")
encode=0
ffmpegCmd=""
if echo $aCodec|grep --quiet $audioCodecDesired; then
ffmpegCmd=$ffmpegCmd" -c:a copy"
verboseAudio=$verboseAudio" -> copy"
else
ffmpegCmd=$ffmpegCmd" "$audioParameter
encode=1
verboseAudio=$verboseAudio" -> "$audioCodecDesired
fi
if echo $vCodec|grep --quiet $videoCodecDesired; then
ffmpegCmd=$ffmpegCmd" -c:v copy"
verboseVideo=$verboseVideo" -> copy"
else
ffmpegCmd=$ffmpegCmd" "$videoParameter
encode=1
verboseVideo=$verboseVideo" -> "$videoCodecDesired
fi
verbose "$verboseAudio"
verbose "$verboseVideo"
if [[ $encode == 1 ]]; then
#Add optional arguments passed by user
if [ ! -z "$optionalParameter" ]; then
ffmpegCmd="$ffmpegCmd $optionalParameter"
fi
#Add directory "-d" if selected
if [ ! -z "$outputDirectory" ]; then
ffmpegCmd="$ffmpegCmd $outputDirectory/${basename%.*}.$outputExtension"
fi
verbose "\tffmpeg arguments:"$ffmpegCmd
FFREPORT=file="$errorFile":level=24
ffmpeg -hide_banner -i "$@" $(echo "$ffmpegCmd")
if [ -f "$errorFile" ]; then
errorCount=$((errorCount+1))
fi
# 2> "$basename".error.txt
if [ ! -z "$processedDirectory" ]; then
mv "$@" "$processedDirectory/" -v
if [ -f "$errorFile" ]; then
mv "$errorFile" "$processedDirectory/" -v
fi
fi
else
verbose "\tKeep original source."
unencodedCount=$((unencodedCount+1))
if [ ! -z "$goodAsIsDirectory" ]; then
mv "$@" "$goodAsIsDirectory/" -v
fi
fi
}
#Process user input that could be a file, a directory or anything really.
function processInput {
verbose "Input \"$@\""
if [ -d "$@" ]; then
directoryCount=$((directoryCount+1))
for inputInDir in "$@"/*; do
processInput "$inputInDir"
done
fi
if [ -f "$@" ]; then
fileCount=$((fileCount+1))
processFile "$@"
fi
}
function verbose {
if [[ $verbose == 1 ]]; then
echo -e "$@"
fi
}
if [[ $no_args == 1 ]]; then
displayHelp
else
verbose "Configuration:"
verbose "\tAudio codec desired="$audioCodecDesired
verbose "\tVideo codec desired="$videoCodecDesired
verbose "\tAudio parameter="$audioParameter
verbose "\tVideo parameter="$videoParameter
verbose "\tOptional parameter="$optionalParameter
verbose "\tDirectory encoded file="$outputDirectory
verbose "\tEncoded file extension="$outputExtension
verbose "\tDirectory processed file="$processedDirectory
verbose "\tDirectory unmodified file="$goodAsIsDirectory
verbose "Number of inputs "$#
if
([ $audioCodecDesired = "codec" ] && [ $videoCodecDesired = "codec" ]) ||
([ -z "$audioParameter" ] && [ -z "$videoParameter" ])
then
echo "At least one codec must be choosed."
exit
fi
for input in "$@"; do
processInput "$input"
done
#Display statistics
message="Processed "$fileCount" file"
if [ $fileCount -gt 1 ]; then
message=$message"s"
fi
if [ $directoryCount -gt 0 ]; then
message=$message" in $directoryCount director"
if [ $directoryCount -gt 1 ]; then
message=$message"ies."
else
message=$message"y."
fi
fi
encodedCount=$((fileCount-unencodedCount))
if [ $encodedCount -gt 0 ]; then
message=$message"\n"$encodedCount" encoded."
fi
if [ $unencodedCount -gt 0 ]; then
message=$message"\n"$unencodedCount" kept \"as is\"."
fi
if [ $errorCount -gt 0 ]; then
message=$message"\n"$errorCount" error"
if [ $fileCount -gt 1 ]; then
message=$message"s"
fi
message=$message" reported by FFmpeg."
fi
verbose $message
fi