l’Almanet doLys Gnu/Linux – Open Source – Entreprises › Forums › L’almanet doLys Open Source › [Tuto] Créer des gifs animés de qualité à partir d’une vidéo › Répondre à: [Tuto] Créer des gifs animés de qualité à partir d’une vidéo
juillet 8, 2017 à 11:15 am
#5688
kholo
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