271 lines
9.8 KiB
Bash
Executable File
271 lines
9.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
###############################################################################
|
|
#
|
|
# Script to recursively search a directory and batch convert all files of a given
|
|
# file type into another file type via HandBrake conversion.
|
|
#
|
|
# To run in your environment set the variables:
|
|
# hbcli - Path to your HandBrakeCLI
|
|
#
|
|
# source_dir - Starting directory for recursive search
|
|
#
|
|
# input_file_type - Input file type to search for
|
|
#
|
|
# output_file_type - Output file type to convert into
|
|
#
|
|
#
|
|
# Change log:
|
|
# 2012-01-08: Initial release. Tested on Mac OS X Lion.
|
|
#
|
|
###############################################################################
|
|
#clear
|
|
|
|
logFile=~/$(basename ${0}).log
|
|
|
|
echo -e "\n"
|
|
echo -e "==> Préparation de l'environnement...\n"|tee $logFile
|
|
|
|
echo ""
|
|
|
|
if [ -f "$1" ]; then
|
|
echo -e "Le paramètre est un fichier : $1\n" |tee -a $logFile
|
|
type="file"
|
|
input_file=$1
|
|
shift
|
|
else
|
|
echo -e "Le paramètre n'est pas un fichier\n" |tee -a $logFile
|
|
fi
|
|
|
|
if [ -d "$1" ]; then
|
|
echo -e "Le paramètre est un dossier : $1\n" |tee -a $logFile
|
|
cd $1
|
|
shift
|
|
else
|
|
echo -e "Le paramètre n'est pas un dossier\n" |tee -a $logFile
|
|
fi
|
|
|
|
# Vérifie que deux paramètres ont été renseignés
|
|
|
|
param1=${1:-mkv}
|
|
param2=${2:-26}
|
|
|
|
echo -e "$(basename ${0}) $param1 $param2\n" |tee -a $logFile
|
|
|
|
date_en_cours=$(date +"%Y%m%dT%H%M%S")
|
|
source_dir=$(pwd)
|
|
input_file_type=${param1}
|
|
output_file_type="new${param2}.mkv"
|
|
declare -a mesFichiers
|
|
listFileName=~/rsbConvert_${date_en_cours}.sh
|
|
|
|
|
|
echo -e "Dossier en cours : " |tee -a $logFile
|
|
echo -e " $source_dir\n" |tee -a $logFile
|
|
|
|
|
|
# Construction d'un tableau des noms de fichiers
|
|
i=0
|
|
|
|
echo -e "==> Type de liste : \n" |tee -a $logFile
|
|
|
|
if [ "$type" = "file" ]; then
|
|
echo -e "$source_dir/$input_file\n"|tee -a $logFile
|
|
echo -e "$source_dir/$input_file"> ~/fichiersATraiter_${date_en_cours}_$$.lst
|
|
else
|
|
echo -e "find -L \"$source_dir\" -type f -iname \"*.$input_file_type\"\n" |tee -a $logFile
|
|
find -L "$source_dir" -type f -iname "*.$input_file_type" > ~/fichiersATraiter_${date_en_cours}_$$.lst
|
|
fi
|
|
|
|
|
|
echo -e "==> Traitement de la liste : \n" |tee -a $logFile
|
|
|
|
while read -e aLine
|
|
do
|
|
echo "[NFO] $aLine"|tee -a $logFile
|
|
if [ ${#aLine} -ge 2 ]; then
|
|
echo " a traiter."|tee -a $logFile
|
|
mesFichiers[$i]=$aLine
|
|
i=$(($i+1))
|
|
fi
|
|
|
|
done < ~/fichiersATraiter_${date_en_cours}_$$.lst
|
|
|
|
rm ~/fichiersATraiter_${date_en_cours}_$$.lst
|
|
|
|
echo -e "\n"|tee -a $logFile
|
|
echo -e "==> Traitement des vidéos en cours...\n"|tee -a $logFile
|
|
|
|
|
|
|
|
|
|
for in_file in "${mesFichiers[@]}"
|
|
do # Liste tous les éléments du tableau.
|
|
|
|
echo "Traitement de : $in_file"|tee -a $logFile
|
|
|
|
if [ ${#in_file} -ge 2 ]; then
|
|
|
|
echo -e "\n________________________________________________________________________________"|tee -a $logFile
|
|
echo -e "\n ==> Processing…"|tee -a $logFile
|
|
echo -e "\n [NFO] Input $in_file"|tee -a $logFile
|
|
|
|
# Replace the file type
|
|
out_file=$(echo "$in_file"|sed "s/\(.*\.\)$input_file_type/\1$output_file_type/g")
|
|
|
|
echo -e "\n [NFO] Output $out_file\n"|tee -a $logFile
|
|
|
|
if [ "$in_file" != "$out_file" ]; then
|
|
|
|
# ---------------- RESOLUTION DE SORTIE --------------
|
|
|
|
echo -e "==> RESOLUTION, calcul en cours ...\n"
|
|
# Obtenez la résolution de la vidéo d'entrée en utilisant FFmpeg
|
|
read width height < <(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 "$in_file" | tr ',' ' ')
|
|
|
|
echo -e " RESOLUTION de la vidéo en entrée : \"${width} x ${height}\"\n"|tee -a $logFile
|
|
|
|
# Vérifiez si la résolution est inférieure ou égale à 1080p
|
|
if [[ "$width" -le 1920 && "$height" -le 1080 ]]; then
|
|
# Si la résolution est inférieure ou égale à 1080p, utilisez la résolution d'entrée pour la sortie
|
|
vf_option="scale=${width}:${height}"
|
|
else
|
|
# Si la résolution est supérieure à 1080p, utilisez une résolution de sortie de 1080p
|
|
# Obtenez la résolution de la vidéo d'entrée en utilisant FFmpeg
|
|
vf_option="scale='min(1920\,iw)':'-1'"
|
|
fi
|
|
|
|
echo -e " RESOLUTION de sortie \"${vf_option}\"\n"|tee -a $logFile
|
|
|
|
|
|
# -------------- DETECTION DES BADNES NOIRES ------------------
|
|
|
|
echo -e "==> DETECTION DES BANDES NOIRES, calcul en cours ...\n"
|
|
# Get cropSize en fonction de la résoltuion
|
|
# Calculer la valeur de cropSize en fonction de la résolution d'entrée
|
|
if (( $width > 1920 || $height > 1080 )); then
|
|
if (( $width > 1920 )); then
|
|
echo -e " calcule du scale car vidéo trop grande avec un width de ${width}.\n"|tee -a $logFile
|
|
scale=$(echo "scale=2;1920/$width*100" | bc)
|
|
else
|
|
scale=100
|
|
fi
|
|
cropSize="crop="$(echo "scale=0;$width*$scale/100" | bc)":"$(echo "scale=0;$height*$scale/100" | bc)":0:0"
|
|
else
|
|
cropSize=$(ffmpeg -i "$in_file" -ss 00:02:00 -vframes 1 -vf cropdetect -f null - 2>&1 | awk '/crop/ { print $NF }' | tail -1)
|
|
fi
|
|
# cropSize=$(ffmpeg -i "$in_file" -ss 00:02:00 -vframes 1 -vf cropdetect -f null - 2>&1 | awk '/crop/ { print $NF }' | tail -1)
|
|
|
|
echo -e " CROP ${cropSize} avec un scale de ${scale}\n"|tee -a $logFile
|
|
|
|
|
|
# -------------- ESPACE COLORMETRIQUE ------------------
|
|
|
|
echo -e "==> ESPACE COLORMETRIQUE, calcul en cours ...\n"
|
|
|
|
# Détection automatique de l'espace colorimétrique de la vidéo d'entrée en utilisant FFprobe
|
|
read color_primaries color_trc colorspace < <(ffprobe -v error -select_streams v:0 -show_entries stream=color_primaries,color_trc,colorspace -of csv=p=0 "$in_file")
|
|
|
|
# Définition des paramètres de l'espace colorimétrique en fonction de la détection automatique
|
|
if [[ "$color_primaries" == "bt709" && "$color_trc" == "bt709" && "$colorspace" == "bt709" ]]; then
|
|
color_params=" -color_primaries 1 -color_trc 1 -colorspace 1"
|
|
else
|
|
color_params=""
|
|
fi
|
|
|
|
echo -e " COLOR_PARAMS ${color_params}\n"|tee -a $logFile
|
|
|
|
# --------------- DETECTION DU BITRATE et FRAMERATE -------------------
|
|
|
|
#bitrate=$(ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 "$in_file")
|
|
#framerate=$(ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of default=noprint_wrappers=1:nokey=1 "$in_file")
|
|
|
|
# Get video frame rate
|
|
framerate=$(ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of default=noprint_wrappers=1:nokey=1 "$in_file")
|
|
|
|
# Calculate target bitrate based on video resolution and frame rate
|
|
bitrate=$(echo "scale=0; $width*$height*$framerate*0.1*0.6" | bc)
|
|
|
|
# Calculate maxrate and bufsize based on target bitrate
|
|
maxrate=$(echo "scale=0; $bitrate*1.5/1" | bc)
|
|
bufsize=$(echo "scale=0; $maxrate*2" | bc)
|
|
|
|
#maxrate="10M"
|
|
#bufsize="20M"
|
|
echo -e " framerate : $framerate\n"|tee -a $logFile
|
|
echo -e " Bitrate : $bitrate\n"|tee -a $logFile
|
|
echo -e " Maxrate : $maxrate\n"|tee -a $logFile
|
|
echo -e " Bufsize : $bufsize\n"|tee -a $logFile
|
|
|
|
# --------------- DETECTION DE LA DUREE -------------------
|
|
|
|
echo -e "==> DUREE, calcul en cours ...\n"
|
|
|
|
# Get duration
|
|
duration=$(ffmpeg -i "$in_file" 2>&1 | grep Duration | cut -d ' ' -f 4 | sed s/,//)
|
|
echo -e " Duration : $duration\n"|tee -a $logFile
|
|
|
|
|
|
|
|
|
|
echo -e "\n ==> Demande de compression"|tee -a $logFile
|
|
|
|
cmd_exec="ffmpeg -y -i \"${in_file}\""
|
|
|
|
if [ ${#cropSize} -ge 2 ]; then
|
|
# compression réaliser avec un crop
|
|
vf_option="${vf_option},${cropSize}"
|
|
fi
|
|
|
|
# cmd_exec="${cmd_exec} -map 0:v -map 0:a? -map 0:s?"
|
|
cmd_exec="${cmd_exec} -map 0"
|
|
# cmd_exec="${cmd_exec} -c:a libvorbis -qscale:a 4"
|
|
cmd_exec="${cmd_exec} -c:a aac -b:a 128k -ac 2 -af loudnorm=I=-18:TP=-1:LRA=11:print_format=summary"
|
|
cmd_exec="${cmd_exec} -c:v libx264"
|
|
cmd_exec="${cmd_exec} -filter:v \"${vf_option}\""
|
|
cmd_exec="${cmd_exec} ${color_params}"
|
|
# cmd_exec="${cmd_exec} -preset veryfast"
|
|
md_exec="${cmd_exec} -threads $(nproc)"
|
|
cmd_exec="${cmd_exec} -preset slower"
|
|
cmd_exec="${cmd_exec} -bf 5"
|
|
cmd_exec="${cmd_exec} -crf ${param2} -b:v $bitrate -pix_fmt yuv420p -maxrate $maxrate -bufsize $bufsize"
|
|
# cmd_exec="${cmd_exec} -crf 23 -maxrate 3000k -bufsize 6000k -b:v 3000k -pix_fmt yuv420p"
|
|
cmd_exec="${cmd_exec} -profile:v high -level 4.2"
|
|
cmd_exec="${cmd_exec} -movflags +faststart"
|
|
cmd_exec="${cmd_exec} -tune fastdecode+zerolatency"
|
|
cmd_exec="${cmd_exec} -max_muxing_queue_size 1024 -ss 00:00:00 -t $duration"
|
|
cmd_exec="${cmd_exec} -c:s copy"
|
|
cmd_exec="${cmd_exec} \"${out_file}\""
|
|
|
|
|
|
echo ${cmd_exec}>> ${listFileName}
|
|
|
|
echo -e "\n ==> On indique le fichier traité et le résultat dans un log"|tee -a $logFile
|
|
cmd_exec="echo -e \"\\\"${in_file}\\\" > \\\"${out_file}\\\"\">> ~/rsbConvert.log"
|
|
echo ${cmd_exec}>> ${listFileName}
|
|
|
|
echo -e "\n ==> Finished $out_file"|tee -a $logFile
|
|
|
|
fi
|
|
fi
|
|
|
|
done
|
|
|
|
echo -e "rm ${listFileName}">> ${listFileName}
|
|
|
|
chmod +x ${listFileName}
|
|
|
|
#./rsbConvert.sh
|
|
|
|
echo -e "\n ==== DONE CONVERTING FILES ===="|tee -a $logFile
|
|
|
|
echo -e "\n\n fichier à appeler : ${listFileName}\n";
|
|
|
|
|
|
exit 0
|
|
|
|
|
|
|
|
|
|
|