|
@ -0,0 +1,241 @@ |
|
|
|
|
|
#!/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 |