Répondre à: [Tuto] Créer des gifs animés de qualité à partir d’une vidéo

#5688
Avatarkholo
Participant

salut,
bon j’y aurait mis le temps…

#!/bin/bash
# ----------------------------------------------
NOM_LOGICIEL="${0##*/}"
FONCTION="mise en script de cette page :
[Tuto] Créer des gifs animés de qualité à partir d’une vidéo
# ---------------------------------------------- le script créera un fichier de configuration pour les variables puis chargera une fenêtre de choix à partir d'une liste zenity # ---------------------------------------------- " DEPENDANCES_TODO=" DEPENDANCES : bash touch zenity tee ffmpeg # ---------------------------------------------- TODO : " VERSION="0.010" # NOTES DE VERSIONS # ---------------------------------------------- # kholo - cyril ury 07/2017 # # ---------------------------------------------- # ********************************************************************************* function _journal () { FICHIER_LOG="$NOM_LOGICIEL.log" if [ -f "$FICHIER_LOG" ]; then echo "" | tee "$FICHIER_LOG"; else touch "$FICHIER_LOG"; fi journal "ouverture - $(date)" journal "-------------------------------------------" } function journal () { echo -e "$@" | tee -a "$FICHIER_LOG" >/dev/null; } # echo "ouverture du journal" _journal # ********************************************************************************* # INITIALISATION DES VARIALES par des valeurs par défaut # Communs SOURCE="$HOME" DESTINATION="$HOME" # Mov2Mp4 # $SOURCE $VCODEC $DESTINATION # # Mp42Gifclassique # $SOURCE $RESOLUTION $DESTINATION # # Mp42Gif2classique # $DEBUT $DUREE $SOURCE $RESOLUTION $DESTINATION DEBUT="10" DUREE="5" # # Mp42Gifplus # $SOURCE $FPS $SCALE $FLAGS $PALETTE # $SOURCE $PALETTE $FILER_COMPLEX $DESTINATION # VCODEC="libx264" RESOLUTION="320x180" # VARIABLES # pour la partie 1 PALETTE="/tmp/palette.png" FPS=10 SCALE=320 FLAGS='lanczos' # pour la partie 2 FILER_COMPLEX="fps=$FPS,scale=$SCALE:-1:flags=$FLAGS[x];[x][1:v]paletteuse" # ********************************************************************************* # Fonctions générales Alias function msgbox () { zenity --info --text="$@" } # ********************************************************************************* # Etage pour le fichier Ini (conf) function parserLigneIni () { local ligne=$@ ; case $ligne in # xxxxx=*) xxxxxx="${ligne#*=}" ;; # =*) ="${ligne#*=}" ;; \#*) ;; NOM_LOGICIEL=*) NOM_LOGICIEL="${ligne#*=}" ;; VERSION=*) VERSION="${ligne#*=}" ;; SOURCE=*) SOURCE="${ligne#*=}" ;; DESTINATION=*) DESTINATION="${ligne#*=}" ;; RESOLUTION=*) RESOLUTION="${ligne#*=}" ;; DEBUT=*) DEBUT="${ligne#*=}" ;; DUREE=*) DUREE="${ligne#*=}" ;; VCODEC=*) VCODEC="${ligne#*=}" ;; PALETTE=*) PALETTE="${ligne#*=}" ;; FPS=*) FPS="${ligne#*=}" ;; SCALE=*) SCALE="${ligne#*=}" ;; FLAGS=*) FLAGS="${ligne#*=}" ;; FILER_COMPLEX=*) FILER_COMPLEX="${ligne#*=}" ;; " ") ;; *) journal "valeur ini inconnue ; \n$ligne" ;; esac } function chargerIni () { # [ -f "$FICHIER_INI" ] || \# while read ligne ; do # [ ! "${#ligne}" -eq 0 ] && [ ! "${ligne}" == " " ] && parserLigneIni "$ligne" ; parserLigneIni "$ligne" ; done < "$FICHIER_INI" ; } function sauverIni () { journal "function sauverIni" ; echo "# création automatique $0 # $(date) # vid2gif version $VERSION SOURCE=$SOURCE DESTINATION=$DESTINATION RESOLUTION=$RESOLUTION DEBUT=$DEBUT DUREE=$DUREE VCODEC=$VCODEC PALETTE=$PALETTE FPS=$FPS SCALE=$SCALE FLAGS=$FLAGS FILER_COMPLEX=$FILER_COMPLEX " | tee "$NOM_LOGICIEL.ini" >/dev/null ; [ $? -eq 0 ] && journal "sauvegarde effectuée" } # ********************************************************************************* function _initialisation () { journal "*******************initialisation*******************" ; journal "FICHIER_INI" ; FICHIER_INI="$NOM_LOGICIEL.ini" journal "le nom du fichier ini est : $FICHIER_INI" if [ -f $FICHIER_INI ] ; then journal "chargement du fichier ini" chargerIni ; else touch "$FICHIER_INI" fi } function _quitter () { journal "_quitter" # mettre ici tout ce qui sera nescessaire à la bonne fermeture # echo "$(sauverIni)" > "$NOM_LOGICIEL.ini" ; sauverIni ; exit 0 } # ********************************************************************************* # Fonctions pour définir les valeurs avec et pour Zenity function setRESOLUTION () { journal "set RESOLUTION" RESOLUTION_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="RESOLUTION :" \ --entry-text "$RESOLUTION")" ; case $? in 0) RESOLUTION="$RESOLUTION_new" ; echo "RESOLUTION=$RESOLUTION" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setDEBUT () { journal "set DEBUT" DEBUT_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="DEBUT :" \ --entry-text "$DEBUT")" ; case $? in 0) DEBUT="$DEBUT_new" ; echo "DEBUT=$DEBUT" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setDUREE () { journal "set DUREE" DUREE_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="DUREE :" \ --entry-text "$DUREE")" ; case $? in 0) DUREE="$DUREE_new" ; echo "DUREE=$DUREE" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setVCODEC () { journal "set VCODEC" VCODEC_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="VCODEC :" \ --entry-text "$VCODEC")" ; case $? in 0) VCODEC="$VCODEC_new" ; echo "VCODEC=$VCODEC" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setPALETTE () { journal "set PALETTE" PALETTE_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="PALETTE :" \ --entry-text "$PALETTE")" ; case $? in 0) PALETTE="$PALETTE_new" ; echo "PALETTE=$PALETTE" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setFPS () { journal "set FPS" FPS_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="FPS :" \ --entry-text "$FPS")" ; case $? in 0) FPS="$FPS_new" ; echo "FPS=$FPS" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setSCALE () { journal "set SCALE" SCALE_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="SCALE :" \ --entry-text "$SCALE")" ; case $? in 0) SCALE="$SCALE_new" ; echo "SCALE=$SCALE" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setFLAGS () { journal "set FLAGS" FLAGS_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="FLAGS :" \ --entry-text "$FLAGS")" ; case $? in 0) FLAGS="$FLAGS_new" ; echo "FLAGS=$FLAGS" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setFILER_COMPLEX () { journal "set FILER_COMPLEX" FILER_COMPLEX_new="$(zenity --entry \ --title="modifier la valeur de ..." \ --text="FILER_COMPLEX :" \ --entry-text "$FILER_COMPLEX")" ; case $? in 0) FILER_COMPLEX="$FILER_COMPLEX_new" ; echo "FILER_COMPLEX=$FILER_COMPLEX" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } # ********************************************************************************* function frm_principale () { journal "*******************frm_principale*******************" KA="SOURCE" KB="DESTINATION" KC="RESOLUTION" KD="DEBUT" KE="DUREE" KF="VCODEC" KG="PALETTE" KH="FPS" KI="SCALE" KJ="FLAGS" KK="FILER_COMPLEX" VA="$SOURCE" VB="$DESTINATION" VC="$RESOLUTION" VD="$DEBUT" VE="$DUREE" VF="$VCODEC" VG="$PALETTE" VH="$FPS" VI="$SCALE" VJ="$FLAGS" VK="$FILER_COMPLEX" LAQUESTION=" --------------------------------------------------------------------- Ce module crée une liste de choix Tout à faire - <b>pas encore codé</b>" tropLONG="ffmpeg -y -i SOURCE -vf fps=FPS,scale=SCALE:-1:flags=FLAGS,palettegen PALETTE ffmpeg -i SOURCE -i PALETTE -filter_complex FILER_COMPLEX DESTINATION" zenity --list --width=800 --height=600 --text="$LAQUESTION" \ --ok-label="Sélectionner" \ --cancel-label="quitter" \ --hide-column 1 --column "" --column "choix" --column "Valeur" \ 1 "$KA" "$VA" \ 2 "$KB" "$VB" \ 0 " -----------------" " ----------------------------------------" \ 3 "$KC" "$VC" \ 4 "$KD" "$VD" \ 5 "$KE" "$VE" \ 6 "$KF" "$VF" \ 7 "$KG" "$VG" \ 8 "$KH" "$VH" \ 9 "$KI" "$VI" \ 10 "$KJ" "$VJ" \ 11 "$KK" "$VK" \ 0 " -----------------" " ----------------------------------------" \ 100 "Mov2Mp4" "ffmpeg -i SOURCE -vcodec VCODEC DESTINATION" \ 101 "Mp42Gifclassique" "ffmpeg -i SOURCE -s RESOLUTION DESTINATION" \ 102 "Mp42Gif2classique" "ffmpeg -y -ss DEBUT -t DUREE -i SOURCE -s RESOLUTION DESTINATION" \ 103 "Mp42Gifplus" "$tropLONG" \ ; } function frm_principale_parser () { journal "*******************frm_principale_parser*******************" journal "frm_principale_parser : $1" case $1 in 1) setSource ;; 2) setDestination ;; 3) setRESOLUTION ;; 4) setDEBUT ;; 5) setDUREE ;; 6) setVCODEC ;; 7) setPALETTE ;; 8) setFPS ;; 9) setSCALE ;; 10) setFLAGS ;; 11) setFILER_COMPLEX ;; 100) Mov2Mp4 ;; 101) Mp42Gifclassique ;; 102) Mp42Gif2classique ;; 103) Mp42Gifplus ;; 0) ;; *) # POUR QUITTER PROPREMENT (sauver le ini !) QUITTER="1" _quitter ;; esac } # ********************************************************************************* # Choix et traitement des Sources et Destinations function setSource () { # on peut transformer cette partie pour des traitements par lots setFichiersSelectionnes } function setFichiersSelectionnes () { #sélectionner les images local SOURCE_new="$(zenity --file-selection \ --title="Séléctionnez des fichiers" \ --filename="$dossierImages/" \ --file-filter='Images (mp4, mov) | *.mp4 *.MP4 *.mov *.MOV' \ --file-filter='All files | *' \ )" ; # msgbox "$SOURCE_new" case $? in 0) SOURCE="$SOURCE_new" ; dossierImages="$(dirname "${SOURCE}")/" ; echo "SOURCE=$SOURCE" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } function setDestination () { # on peut transformer cette partie pour des traitements par lots setDESTINATION } function setDESTINATION () { # choisir un fichier de destination local DESTINATION_new="$(zenity --file-selection \ --title="Séléctionnez un fichier" \ --save --confirm-overwrite \ --filename="$DESTINATION" \ --file-filter='gif files (gif) | *.gif')" ; case $? in 0) DESTINATION="$DESTINATION_new" ; echo "DESTINATION=$DESTINATION" ;; 1) echo "annulé" ;; -1) echo "An unexpected error has occurred." ;; esac } # ********************************************************************************* # FONCTIONS SPECIFIQUES function Mov2Mp4 () { # Transformation d'un mov en mp4 unTEST="${SOURCE##*/}" # récupération du nom de fichier unTEST="${unTEST##*.}" # récupération de l'extension du fichier # unTEST="${unTEST,,}" # passage en minuscule pur bash if [ ! ${unTEST,,} == mov ] then msgbox "fonction Transformation d'un mov en mp4 \nle fichier : \n$SOURCE \nATTENTION LE FICHIER SOURCE DOIT ÊTRE un MOV !" else # ffmpeg -i /point/de/montage/source.MOV -vcodec libx264 /point/de/montage/source.mp4 ffmpeg -i "$SOURCE" -vcodec "$VCODEC" "$DESTINATION" fi } function Mp42Gifclassique () { # Création d’un GIF animé, méthode «classique» # A) gif contenant toute la vidéo # ffmpeg -i /point/de/montage/source.mp4 -s 320x180 /point/de/montage/final.gif ffmpeg -y -i "$SOURCE" -s "$RESOLUTION" "$DESTINATION" } function Mp42Gif2classique () { # B) gif d’une partie de la vidéo seulement # Dans ce cas de figure, # la taille du gif est arbitrairement fixée à 2 Mo maximum # et c’est donc la durée du gif qui va devoir s’adapter pour rester en-dessous de 2 Mo. # Si vous voulez que le gif démarre en même temps que la vidéo, vous remplacez 10 par 0 ; # DEBUT en secondes depuis le début de la vidéo originale # DUREE ffmpeg -y -ss "$DEBUT" -t "$DUREE" -i "$SOURCE" -s "$RESOLUTION" "$DESTINATION" } function Mp42Gifplus () { journal "Mp42Gifplus" journal "# étape 1 : génération d’une palette de couleurs" # exemple : ffmpeg -y -i /point/de/montage/source.mp4 -vf fps=10,scale=320:-1:flags=lanczos,palettegen /point/de/montage/palette.png ffmpeg -y -i "$SOURCE" -vf fps="$FPS",scale="$SCALE":-1:flags="$FLAGS",palettegen "$PALETTE" && { journal "# étape 1 : ok" journal "# étape 2 : génération du GIF animé «amélioré»" # ffmpeg -i /point/de/montage/source.mp4 -i /point/de/montage/palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" /point/de/montage/final.gif ffmpeg -y -i "$SOURCE" -i "$PALETTE" -filter_complex "$FILER_COMPLEX" "$DESTINATION" } && { journal "# étape 2 : ok" journal "# étape 3 : supprimer la palette" rm -f $PALETTE } && { journal "# étape 3 : ok" } } # ********************************************************************************* function _main () { journal "_main" menuchoice=$(frm_principale); frm_principale_parser ${menuchoice%|*} # pour corriger le 1|1 if [ $QUITTER!="1" ] ; then # on boucle _main tant que quitter est différent de 1 _main fi } #-initialisation _initialisation ; # Programme principale _main exit 0