#!/bin/bash
# Ferme de rendu parallélisé pour Cinelerra GG
# Structure:
# fab-render.sh - Ce script est l'application principale
# fab-render.py - Tinypy script pour le rendu via avidemux
# Divers:
# number_of_nodes: Pour du h264, j'utilise un nombre de noeuds fille correspondant à
# 10% du nombre de threads du pc et ce, afin de garantir une température processeur sous les 90°
#
# number_of_pipes: number_of_nodes + 1 (cinelerra serveur) * number_of_jobs_per_node
destruction_of_the_renderfarm_and_working_directory () {
# Lister tous les processus cin actifs des port 1030 à 1130 et les détruits
for i in $(lsof -nP -i tcp:1030-$((1030 + 1130)) | grep LISTEN | grep cin | awk '{print $2}')
do
kill $i
done
rm -r "${WORKING_DIRECTORY}"
}
create_of_the_renderfarm_and_pipe_files () {
# Création des répertoires
mkdir -p "${WORKING_DIRECTORY}" "${WORKING_DIRECTORY}"/pipes "${WORKING_DIRECTORY}"/renderFarm
# Créer noeuds cinelerraGG qui servirons de client
for n in $(seq 1030 $((1030 + number_of_nodes)))
do
cin -d $n
done
# Création des pipes
for n in $(seq -w 000 $((000 + number_of_pipes + 1)))
do
mknod "${WORKING_DIRECTORY}"/pipes/piper$n.yuv p
done
}
check_missing_packages () {
missing_packages=""
for requirement in ${1} ; do
[[ ! -a /usr/bin/${requirement} ]] && missing_packages="${missing_packages}\t-${requirement}\n"
done
i=0
msg[++i]="Paquets nécessaires à l'application:\n\n$missing_packages"
msg[++i]="\n\nA installer obligatoirement avant de continuer."
if [[ $missing_packages != "" ]]; then
zenity --error \
--width=200 \
--title "Erreur de dépendance" \
--text="${msg[*]}"
exit
fi
unset i msg
}
check_and_video_rendering () {
msg[++i]="\n\t\t\t\t\t\t\tRendu de la partie vidéo"
msg[++i]="\n\nMoi, votre ordinateur, je viens de:"
msg[++i]="\n\t- Créer, configurer et démarrer les noeuds cinelerra GG."
msg[++i]="\n\t- Créer les pipes nécessaires."
msg[++i]="\n\t- Créer les répertoires filles du répertoire $WORKING_DIRECTORY."
msg[++i]="\n\n\nDe votre côté, veuillez vous assurer que:"
msg[++i]="\n\n1. La porte frontale du boitier est bien ouverte afin d'améliorer le"
msg[++i]="\n refroidissement du Pc."
msg[++i]="\n\n2. Le proxy est désactivé."
msg[++i]="\n\n3. Menu /Configuration/Format\n\t- Image/seconde:\t\t\t\t\t\t\t\t\t50.0"
msg[++i]="\n\t- Largeur:\t\t\t\t\t\t\t\t\t\t\t1920"
msg[++i]="\n\t- Hauteur:\t\t\t\t\t\t\t\t\t\t\t1080"
msg[++i]="\n\t- Le modèle couleur:\t\t\t\t\t\t\t\tYuv-8 bit ou du YUVA 8 bit."
msg[++i]="\n\n4. Menu /Configuration/Préférences/Performances"
msg[++i]="\n\t- CPI SMP du projet:\t\t\t\t\t\t\t\t$number_of_threads"
msg[++i]="\n\t- Utiliser une grappe de calcul pour le rendu:\tcoché"
msg[++i]="\n\t- Délais d'attente du watchdog du client:\t\t60"
msg[++i]="\n\t- Nombre de travaux à créer:\t\t\t\t\t\t$number_of_pipes"
msg[++i]="\n\t- Noeuds déclarés\t\tNom d'hôte:\t\t\tlocalhost"
msg[++i]="\n\t\t\t\t\t\t\t\tPort: \t\t\t\t\t1030->$((1030 + number_of_nodes))"
msg[++i]="\n\n5. Menu /fichier/rendu"
msg[++i]="\n\t- Fichier-type :\t\t\t\t\t\t\t\t\tFFMPEG - yuv"
msg[++i]="\n\t- Fichier de destination pour le rendu:\t\t\t$WORKING_DIRECTORY/pipes/piper000.yuv"
msg[++i]="\n\t- Préréglage vidéo :\t\tCompression:\t\t\traw.yuv"
msg[++i]="\n\t\t\t\t\t\t\t\tDébit binaire:\t\t\t0"
msg[++i]="\n\t\t\t\t\t\t\t\tQualité:\t\t\t\t-1"
msg[++i]="\n\t\t\t\t\t\t\t\tPixels:\t\t\t\t\tyuv420p"
msg[++i]="\n\n\nAprès ces vérifications, lancer le rendu puis passer à l'étape suivante."
zenity --info --width=600 --title="FAB-RENDER" --text="${msg[*]}"
cd "${WORKING_DIRECTORY}"/pipes
(ls piper*.yuv | parallel \
ffmpeg -f rawvideo \
-pixel_format yuv420p \
-video_size 1920x1080 \
-r 50 \
-i {} \
-c:v libx264 \
-preset slow \
-crf 20 \
-vf scale=1280:-1:flags=lanczos \
-ac 2 \
-c:a aac \
-b:a 224k \
"${WORKING_DIRECTORY}"/renderFarm/{.}.mkv ) | \
zenity --progress \
--title="FAB-RENDER" \
--text "Rendu vidéo en cours..." \
--auto-close \
--no-cancel \
--pulsate
unset i msg
}
concatenate_all_pipe_files () {
cd "${WORKING_DIRECTORY}"/renderFarm
ffmpeg -f concat \
-safe 0 \
-i <(for f in ./*.mkv; do echo "file '$PWD/$f'"; done) \
-c copy \
piperMux.mkv | \
zenity --progress \
--title="FAB-RENDER" \
--text "Concaténation des fichiers vidéo en cours..." \
--auto-close \
--no-cancel \
--pulsate
}
check_and_audio_rendering () {
msg[++i]="\n\t\t\t\t\t\t\t Rendu de la partie audio"
msg[++i]="\n\nMoi, votre ordinateur, je viens de réaliser la concaténation des fichiers vidéo précédemment traités par la ferme de rendu."
msg[++i]="\nCe fichier à été sauvé dans le répertoire $WORKING_DIRECTORY/renderFarm."
msg[++i]="\n\n\nDe votre côté, veuillez vous assurer que:"
msg[++i]="\n\n1. Menu /Configuration/Préférences/Performances"
msg[++i]="\n\t- Utiliser une grappe de calcul pour le rendu:\t\tDécoché"
msg[++i]="\n\n2. Menu /fichier/rendu"
msg[++i]="\n\t- Fichier-type :\t\t\t\t\t\t\t\t\t\tMicrosoft WAV"
msg[++i]="\n\t- Fichier de destination pour le rendu:\t\t\t\t$WORKING_DIRECTORY/pipes/piper000.wav"
msg[++i]="\n\t- Préréglage audio :\t\tCompression:\t\t\t\t16 Bits Linear"
msg[++i]="\n\t\t\t\t\t\t\t\tTramage:\t\t\t\t\tDécoché"
msg[++i]="\n\n\nAprès ces vérifications, lancer le rendu et attendre sa fin avant de passer à l'étape suivante."
zenity --info --width=610 --title="FAB-RENDER" --text="${msg[*]}"
unset i msg
}
mixing_video_and_audio () {
i=0
msg[++i]="\n\t\t\t\t\t Mixage de la video et de l'audio"
msg[++i]="\n\n\nMoi, votre ordinateur, je vais réaliser le mixage des fichiers vidéo et audio avec les caractéristiques suivante:"
msg[++i]="\n\n\t-Vidéo\t\t\t\t\tCodec:\t\t\t\tCopie"
msg[++i]="\n\t-Audio\t\t\t\t\tCodec: \t\t\tAAC (FDK)"
msg[++i]="\n\t\t\t\t\t\t\tDébit: \t\t\t\t224 Kb"
msg[++i]="\n\t-Fichier de sortie\t\t\t\t\t\t\t ${WORKING_DIRECTORY}/final.mkv"
zenity --info --width=600 --title="FAB-RENDER" --text="${msg[*]}"
# Via avidemux
sleep 2
avidemux --load "${WORKING_DIRECTORY}"/renderFarm/piperMux.mkv \
--run "${DIRECTORY_OF_THIS_SCRIPT}"/fab-render.py \
--save "${WORKING_DIRECTORY}"/final_via_avidemux.mkv \
--quit | \
zenity --progress \
--title="FAB-RENDER" \
--text "Mixage audio/vidéo en cours de traitement..." \
--auto-close \
--no-cancel \
--pulsate
# et/ou via ffmpeg
sleep 2
ffmpeg -i "${WORKING_DIRECTORY}"/renderFarm/piperMux.mkv \
-i "${WORKING_DIRECTORY}"/pipes/piper000.wav \
-c:v copy \
-c:a libfdk_aac \
-b:a 224k \
-shortest \
"${WORKING_DIRECTORY}"/final_via_ffmpeg\(en_test\).mkv | \
zenity --progress \
--title="FAB-RENDER" \
--text "Mixage audio/vidéo en cours de traitement..." \
--auto-close \
--no-cancel \
--pulsate
unset i msg
}
opening_the_final_rendering_directory () {
nautilus "$WORKING_DIRECTORY"/ &
msg[++i]="\n\t\t\t\t\t\t\tNettoyage"
msg[++i]="\n\n\nMoi, votre ordinateur, je viens d'ouvrir pour vous le contenu du répertoire"
msg[++i]="\n$WORKING_DIRECTORY, vous y trouverez le fichier final.mkv."
msg[++i]="\n\n\nDe votre côté, assurez-vous que ce fichier correspond à vos besoins."
msg[++i]="\nSi tel est bien le cas, il y a lieu d'en faire une copie afin de le sauvegarder."
msg[++i]="\n\n\nEn effet, dès votre validation je vais faire un petit peu de ménage, à savoir:"
msg[++i]="\n\t- Tuer les noeuds CinelerraGG créés précédemment."
msg[++i]="\n\t- Supprimer du disque le répertoire $WORKING_DIRECTORY et son contenu."
msg[++i]="\n\n\nValider pour acter le nettoyage."
zenity --info --width=600 --title="FAB-RENDER" --text="${msg[*]}"
unset i msg
}
main () {
check_missing_packages "zenity bc ffmpeg avidemux"
# Constantes
readonly WORKING_DIRECTORY="/tmp/fab-render"
readonly DIRECTORY_OF_THIS_SCRIPT=$(dirname $0)
# Variables
number_of_threads=$(cat /proc/cpuinfo | grep processor | wc -l)
number_of_nodes=$(echo "$number_of_threads / 10" | bc)
number_of_jobs_per_node=4
number_of_pipes=$(echo "($number_of_nodes + 1 ) * $number_of_jobs_per_node" | bc)
destruction_of_the_renderfarm_and_working_directory # Destruction préventive
create_of_the_renderfarm_and_pipe_files
check_and_video_rendering
concatenate_all_pipe_files
check_and_audio_rendering
mixing_video_and_audio
opening_the_final_rendering_directory
destruction_of_the_renderfarm_and_working_directory
}
main