#!/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:a eac3 -b:a 256k -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 4500k -bufsize 6000k -b:v 3000k -pix_fmt yuv420p" # cmd_exec="${cmd_exec} -profile:v high -level 4.2" cmd_exec="${cmd_exec} -profile:v main -level 4.1 -tune film" 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 "touch \"${out_file}.process\"">> ${listFileName} echo ${cmd_exec}>> ${listFileName} echo "rm \"${out_file}.process\"">> ${listFileName} echo "touch \"${out_file}.processed\"">> ${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