Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Pour en savoir un peu plus sur l'équipe du forum.

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#1 Le 08/07/2017, à 12:27

kholo

[TUTO] script bash conversion vidéos mov et mp4 vers gif

bonjour à tous,
voici un script pour
Convertir des vidéos ou parties vidéos mov et mp4 en gif
ce script est issu d'une discussion sur Dolys

DEPENDANCES : bash, touch, zenity, tee, ffmpeg ... et pis c'est tout !

Installation pour un utilisateur :
créer un dossier bin personnel :

mkdir $HOME/bin

y mettre le script

touch $HOME/bin/vid2gif

le rendre exécutable

chmod +x $HOME/bin/vid2gif

éditer et coller le script suivant avec gedit (ou nano ou vi, vim, leafpad,...)

gedit $HOME/bin/vid2gif
#!/bin/bash
# ----------------------------------------------
NOM_LOGICIEL="${0##*/}"
FONCTION="mise en script de cette page :
https://dolys.fr/forums/topic/creer-des-gifs-animes-de-qualite-a-partir-dune-video/

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.012"
# 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="$FONCTION"

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 \
	--title="vid2gif - $NOM_LOGICIEL - version $VERSION" \
	--text="$LAQUESTION" \
	--ok-label="Sélectionner" \
	--cancel-label="quitter" \
	--hide-column 1 --column "" --column "choix" --column "Valeur" \
	1 "$KA" "$VA" \
	2 "$KB" "$VB" \
	0 " -----------------" "	-----------------AIDE ICI-----------------" \
	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 " -----------------" "	-----------------AIDE ICI-----------------" \
	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) AfficherAide;;
		
		*) # POUR QUITTER PROPREMENT (sauver le ini !)
			QUITTER="1"
			_quitter ;;
	esac
}
function AfficherAide () {
# $FONCTION
TEXTE_AIDE="Convertir des vidéos ou parties vidéos mov et mp4 en gif
-------------------------------------------------------
ce script est issu d'une discussion sur Dolys
https://dolys.fr/forums/topic/creer-des-gifs-animes-de-qualite-a-partir-dune-video

-------------------------------------------------------
DEPENDANCES : bash, touch, zenity, tee, ffmpeg... et pis c'est tout !

-------------------------------------------------------
Installation pour un utilisateur :
créer un dossier bin personnel :
mkdir $HOME/bin
y mettre le script
touch $HOME/bin/vid2gif
le rendre exécutable
chmod +x $HOME/bin/vid2gif
éditer et coller le script suivant avec gedit (ou nano ou vi, vim, leafpad,...)
gedit $HOME/bin/vid2gif

Attention
si vous avez dû créer le dossier bin car il n'existait pas, 
mkdir $HOME/bin 
n'a pas renvoyé d'erreur (puisque le dossier n'existait pas !)
il faudra relancer l'utilisateur pour que ce dossier bin soit ajouté au PATH automatiquement
... dans le doute déconnectez puis reconnectez votre session

-------------------------------------------------------
Pour lancer le script 
dans un terminal
vid2gif

TODO en GUI :
il faut créer un lanceur ou un lien.

-------------------------------------------------------
Pour utiliser le tableau zenity
pour modifier une des valeurs du tableau, double cliquez sur la ligne à modifier
choisissez une valeur et valider... ou annuler pour récupérer la valeur précédente.

Choisissez un fichier mov et une destination gif
lancez l'option Mov2Mp4
ou
Choisissez un mp4 et choisissez une des options Mp42Gifclassique, Mp42Gif2classique ou Mp42Gifplus

NB pour faire des tests et comparer des options, pensez à changer le nom du fichier DESTINATION (le gif)
TODO :
zenity demande en cas d'écrasement d'un fichier, c'est à supprimer et à ajouter en fonction dans le script."

echo "${TEXTE_AIDE}" | zenity --width=800 --height=600 --text-info="${@}"
# zenity --info --text="${TEXTE_AIDE}"
# zenity --text-info="${TEXTE_AIDE}"


	}
# *********************************************************************************
# 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 gestionExtGIF () {
	# Ajout éventuel d'une extension en gif
	local leFichier="$@"
	local unTEST

	unTEST="${leFichier##*/}" # récupération du nom de fichier seul
	unTEST="${unTEST##*.}" # récupération de l'extension du fichier
	# unTEST="${unTEST,,}" # passage en minuscule pur bash
	if [ ! ${unTEST,,} == gif ] 
	then
		echo "$leFichier".gif
	else 
		echo "$leFichier"
	fi
	}
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" ;
		DESTINATION="$(gestionExtGIF "$DESTINATION_new")" ;
		journal "DESTINATION=$DESTINATION" ;;
	1) journal "annulé" ;;
	-1) journal "An unexpected error has occurred." ;;
esac
}

# *********************************************************************************
# FONCTIONS SPECIFIQUES
function Mov2Mp4 () {
	# Transformation d'un mov en mp4
	local unTEST
	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

Attention
si vous avez dû créer le dossier bin car il n'existait pas,

mkdir $HOME/bin

n'a pas renvoyé d'erreur (puisque le dossier n'existait pas !)
il faudra relancer l'utilisateur pour que ce dossier bin soit ajouté au PATH automatiquement
... dans le doute déconnectez puis reconnectez votre session

Pour lancer le script
dans un terminal

vid2gif

TODO en GUI :
il faut créer un lanceur ou un lien.

Pour utiliser le tableau zenity
pour modifier une des valeurs du tableau, double cliquez sur la ligne à modifier
choisissez une valeur et valider... ou annuler pour récupérer la valeur précédente.

Choisissez un fichier mov et une destination gif
lancez l'option Mov2Mp4
ou
Choisissez un mp4 et choisissez une des options Mp42Gifclassique, Mp42Gif2classique ou Mp42Gifplus

NB pour faire des tests et comparer des options, pensez à changer le nom du fichier DESTINATION (le gif)
TODO :
zenity demande en cas d'écrasement d'un fichier, c'est à supprimer et à ajouter en fonction dans le script.

Dernière modification par kholo (Le 09/07/2017, à 05:40)

Hors ligne

#2 Le 10/07/2017, à 22:15

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@kholo
Je reprends la réponse que je t'ai faite sur le site dolys.fr de notre ami nam1962 :
Alors là, chapeau bas !
Bravo à toi pour ton travail, je suis épaté.
Là, je suis au travail et je n’ai pas de PC sous Linux pour tester mais je serai de repos ce mercredi et je pourrai alors tester tranquillement chez moi ton script. Je sens qu’il va me plaire… encore merci !
Je te tiens au courant de mes essais dès que faits. big_smile


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#3 Le 11/07/2017, à 08:06

Anonyme68

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

Bonjour,

sympa le travail, par contre je te propose quelques améliorations.

Déjà tu nommes touch comme dépendance, et tu te sert du programme que pour créer des fichiers vides d'après ce que j'ai pu lire.

Bash à déjà une fonctionnalité pour faire ça.

touch monfichiervide

=

> monfichiervide

tee c'est pareil je suppose

echo -e "$@" | tee -a "$FICHIER_LOG" >/dev/null;

c'est équivalent de :

echo -e "$@" >> "$FICHIER_LOG"

ensuite en Bash, on est pas tenu de finir les lignes avec ";", je trouve ça plus propre sans.

Voilà smile Je pense que je te copierai tes fonctions de gestion de fichiers ini quand je referai un script, je trouve ça sympa.


846/2381 jeux linux sur Steam

Vous avez plein d'ISO d'ubuntu ? Une bonne bande passante ? Aimer partager ? Essayer mon script

Hors ligne

#4 Le 12/07/2017, à 12:46

kholo

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

bon d'abord merci Anonyme68,
j'ai pris tes conseils en considération, on les verra sous peu dans le post #1
NB je ne sais pas si on peut virer tous les tee... j'expliquerais dans un prochain post...
@tous :
en attendant, j'ai avancé sur une autre part du script et ça donne ça wink

Hors ligne

#5 Le 13/07/2017, à 16:59

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@kholo
J'ai testé ton script et tout fonctionne bien avec le tableau Zenity (Merci ! big_smile ) à la seule exception de l'option Mov2Mp4 pour laquelle j'obtiens invariablement le message d'erreur ci-dessous (j'ai essayé avec plusieurs fichiers MOV) :

jlfh0816 @ voyager1404  ~
└─ $ ▶ vid2gif

ffmpeg version 3.3.1 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
  configuration: --extra-libs=-ldl --prefix=/opt/ffmpeg --mandir=/usr/share/man --enable-avresample --disable-debug --enable-nonfree --enable-gpl --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb --disable-decoder=amrnb --disable-decoder=amrwb --enable-libpulse --enable-libfreetype --enable-gnutls --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-libvorbis --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libspeex --enable-libass --enable-avisynth --enable-libsoxr --enable-libxvid --enable-libvidstab --enable-libwavpack --enable-nvenc
  libavutil      55. 58.100 / 55. 58.100
  libavcodec     57. 89.100 / 57. 89.100
  libavformat    57. 71.100 / 57. 71.100
  libavdevice    57.  6.100 / 57.  6.100
  libavfilter     6. 82.100 /  6. 82.100
  libavresample   3.  5.  0 /  3.  5.  0
  libswscale      4.  6.100 /  4.  6.100
  libswresample   2.  7.100 /  2.  7.100
  libpostproc    54.  5.100 / 54.  5.100
Guessed Channel Layout for Input Stream #0.1 : stereo
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/jlfh0816/Vidéos/dreamscenes/003.MOV':
  Metadata:
    major_brand     : qt  
    minor_version   : 537331968
    compatible_brands: qt  niko
    creation_time   : 2016-09-25T09:34:02.000000Z
  Duration: 00:01:04.32, start: 0.000000, bitrate: 22185 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, smpte170m/bt709/bt470m), 1920x1080, 20610 kb/s, 50 fps, 50 tbr, 50k tbn, 100 tbc (default)
    Metadata:
      creation_time   : 2016-09-25T09:34:02.000000Z
    Stream #0:1(eng): Audio: pcm_s16le (sowt / 0x74776F73), 48000 Hz, stereo, s16, 1536 kb/s (default)
    Metadata:
      creation_time   : 2016-09-25T09:34:02.000000Z
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
Press [q] to stop, [?] for help
No pixel format specified, yuvj420p for H.264 encoding chosen.
Use -pix_fmt yuv420p for compatibility with outdated media players.
[libx264 @ 0x3fd3400] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
[libx264 @ 0x3fd3400] profile High, level 4.2
[gif @ 0x3fd4f20] GIF muxer supports only a single video GIF stream.
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Error initializing output stream 0:0 -- 
Conversion failed!

Est-ce que tu obtiens la même erreur chez toi ?

En tout cas, merci pour les 3 options Mp42gif..., elles fonctionnent toutes très bien. Je vais maintenant voir s'il est possible de faire un lanceur pour chacune d'entre elles ou si on doit se contenter d'un lanceur unique vid2gif qui lance le tableau Zenity.

Bon week-end à toi ... et encore merci de ton superbe travail !


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#6 Le 13/07/2017, à 17:32

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@kholo
J'ai oublié de te dire que les 3 options Mp42gif... fonctionnent avec le même succès si j'indique comme source un fichier Mov ou un fichier Mp4 ... Donc, grâce à ton script, je peux transformer directement un fichier Mov en un gif animé  (pas besoin de passer par la conversion intermédiaire de Mov vers Mp4) ! C'est formidable !


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#7 Le 13/07/2017, à 17:46

erresse

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

Désolé de venir juste évoquer un bémol... wink
J'ai testé le script sur de petits films de quelques secondes, d'abord en .mov, mais la fonction Mov2Mp4 n'a pas fonctionné chez moi.
Ensuite, après conversion de mon film de .mov en .mp4, j'ai bien obtenu des images .gif avec les 3 autres fonctions, mais... pour un film de 2,5Mo, j'ai produit des .gif de 5Mo et plus.
C'est normal qu'une image animée soit deux fois plus volumineuse qu'un film ???


Plus de 50 ans d'informatique, ça en fait des lignes de commandes en console, mais on n'avait pas le choix...
Excellente raison pour, aujourd'hui qu'on le peut, utiliser au maximum les INTERFACES GRAPHIQUES !
Important : Une fois résolu, pensez à clore votre sujet en ajoutant [Résolu] devant le titre du 1er message, et un bref récapitulatif de la solution à la fin de celui-ci. Merci.

Hors ligne

#8 Le 13/07/2017, à 18:01

Anonyme68

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

erresse a écrit :

C'est normal qu'une image animée soit deux fois plus volumineuse qu'un film ???

Au cas où, un film est déjà une image animé big_smile avec des fois du son synchronisé. Ensuite les formats ont fait de sacrés progrès depuis que le GIF est sorti (il y a 30 ans), ça me paraît donc pas aberrant.

Tu peux obtenir un bon ratio sur un GIF si il y a qu'une partie qui bouge sur la vidéo. Il y a que la différence avec l'image d'avant qui a besoin d'être enregistré.


846/2381 jeux linux sur Steam

Vous avez plein d'ISO d'ubuntu ? Une bonne bande passante ? Aimer partager ? Essayer mon script

Hors ligne

#9 Le 13/07/2017, à 18:19

erresse

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

Anonyme68 a écrit :

Tu peux obtenir un bon ratio sur un GIF si il y a qu'une partie qui bouge sur la vidéo. Il y a que la différence avec l'image d'avant qui a besoin d'être enregistré.

En ouvrant l'image obtenue dans Gimp, il me dit que l'animation GIF est déjà optimisée (il semblerait que le script ait déjà créé l'image avec l'optimisation)... après, bien sûr, tout dépend de ce qui bouge dans la vidéo, je le conçois bien.
Utiliser une image animée peut être intéressant dans certains cas, lorsqu'on ne peut pas mettre une vidéo (par exemple l'avatar de kholo dans le forum), mais sinon, le film est quand même mieux, au moins est-il sonore en plus d'être plus léger.
tongue


Plus de 50 ans d'informatique, ça en fait des lignes de commandes en console, mais on n'avait pas le choix...
Excellente raison pour, aujourd'hui qu'on le peut, utiliser au maximum les INTERFACES GRAPHIQUES !
Important : Une fois résolu, pensez à clore votre sujet en ajoutant [Résolu] devant le titre du 1er message, et un bref récapitulatif de la solution à la fin de celui-ci. Merci.

Hors ligne

#10 Le 14/07/2017, à 08:23

kholo

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

bonjour les gens,
merci pour vos retours,
hier, j'ai surtout avancé sur la partie barre de progression et getopts (à venir) !

comme dit plus haut, j'ai pu voir lors de mes essais qu'on pouvait faire du mov -> gif directement
je pense que ma fonction mov2mp4 est à mettre dans un script de conversion plus spécifique...

HS a écrit :

tjs pour mov2mp4 j'ai vu pendant mes recherches que DESTINATION n'a pas spécialement lieu d'être
puisqu'on peut prendre le nom du fichier et changer l'extension

DESTINATION="${SOURCE%.*}.mp4"
ffmpeg -y -i "${SOURCE}" -vcodec "${VCODEC}" "${DESTINATION}" ...

... pour les tee, finalement, c'est bon, y en a plus besoin

j'ai pointé quelques bugs comme la gestion des début et fin dans Mp42Gif2classique où durée + fin ne doit pas dépasser la durée totale du film !
je met ça dans la TODO list (et d'autres bricoles !)

jlfh0816 a écrit :

Je vais maintenant voir s'il est possible de faire un lanceur pour chacune d'entre elles ou si on doit se contenter d'un lanceur unique vid2gif qui lance le tableau Zenity.

je vais ajouter un étage pour la gestion des arguments (je me suis enfin mis à getopts, mais je rame un peu...)

voici une version plus sympa mais qui rester à tester...
ma TODO list :

txtTODO="# ----------------------------------------------
# gestion des arguments et des appels en LdC getopts
# ouverture et enregistrement de confs
# TMP_LOG et TMP_TOUT à passer en FIFO
# Mp42Gifplus à finir (palette; progress barre vide , msgbox donne fini au lieu de palette )
# mov2mp4 à supprimer de ce script (inutile)
# -> du coup revoir la gestion des extensions dans zenity --file-selection
# aide à finir...
# infos dans le log à améliorer
# Mp42Gifplus ; finir de séparer la création de la palette
# function _journal () { ...
# function _main () { # function main () {
# faire une fonction pour l'initialisation
# voir QUITTER=1 et _quitter ; doit pouvoir être plus propre (comme cette tournure !)
# 
# gestion des erreurs
# refonte du code ; normalisation (variable en maj, fonctions en min, underscores....)
# 
# GUI ; séparations de la gestion des fonctions pour n'avoir que les options utiles à chaque fonction
# GUI ; 0  ----------------- AIDE ICI -----------------		Paramètres ; pas bien placé 
# ajour de fonctionnalités
# localisation ;°)
"

je la met ici pour décorticage mais il reste encore du boulot

vid2gif-gui(0.019)
NB : pas de gestion des fichiers temporaires (à supprimer à la main)
(j'ai pas ce problème, mon /tmp est en RAM wink )
TMP_LOG="/tmp/$nomlogiciel.log"
TMP_TOUT="/tmp/affichetout.txt"

#!/bin/bash
# ----------------------------------------------
NOM_LOGICIEL="${0##*/}"
FONCTION="mise en script de cette page :
https://dolys.fr/forums/topic/creer-des-gifs-animes-de-qualite-a-partir-dune-video/

le script créera un fichier de configuration pour les variables
puis chargera une fenêtre de choix à partir d'une liste zenity"

txtTODO="# ----------------------------------------------
# gestion des arguments et des appels en LdC getopts
# ouverture et enregistrement de confs
# TMP_LOG et TMP_TOUT à passer en FIFO
# Mp42Gifplus à finir (palette; progress barre vide , msgbox donne fini au lieu de palette )
# mov2mp4 à supprimer de ce script (inutile)
# -> du coup revoir la gestion des extensions dans zenity --file-selection
# aide à finir...
# infos dans le log à améliorer
# Mp42Gifplus ; finir de séparer la création de la palette
# function _journal () { ...
# function _main () { # function main () {
# faire une fonction pour l'initialisation
# voir QUITTER=1 et _quitter ; doit pouvoir être plus propre (comme cette tournure !)
# 
# gestion des erreurs
# refonte du code ; normalisation (variable en maj, fonctions en min, underscores....)
# 
# GUI ; séparations de la gestion des fonctions pour n'avoir que les options utiles à chaque fonction
# GUI ; 0  ----------------- AIDE ICI -----------------		Paramètres ; pas bien placé 
# ajour de fonctionnalités
# localisation ;°)
"

VERSION="0.019"
# NOTES DE VERSIONS
# ----------------------------------------------
# kholo - cyril ury 07/2017
# ...
# 0.019
# ajout progress barre (du coup plein d'autres trucs)
# horodatage des logs, gestion de certaines erreurs 
# en parallèle de la gestion du "annuler" des barre de progression
# infos ajoutées pour lecteurs du forum ;°)
# TODO list bien remplie !
# 0.016
# reprise des variables ${variable} 
# ${QUITTER} devient variable numérique # -> if [ ${QUITTER} -eq 0 ] ; then
# 0.015
# mise en pratique des préconisations de Anonyme68
# https://forum.ubuntu-fr.org/viewtopic.php?pid=21760381#p21760381
# 0.014
# première mise en ligne
# ----------------------------------------------

# nautilus "$PWD"
# exit

# durée d'exécution pour horodatage du log
# START=$(date +%s.%N)
# command
# END=$(date +%s.%N)
# DIFF=$(echo "$END - $START" | bc)
# echo $DIFF
START=$(date +%s.%N)

function testDependances () {
local programme

listDEPENDANCES="bash
zenity
ffmpeg"

IFS=$'\n' listDEPENDANCES=( "$listDEPENDANCES" )
for programme in ${listDEPENDANCES[@]}
do
	programmePath=$(which "$programme") >/dev/null
	file -b -i "$programmePath" >/dev/null
	if [ ! $? -eq 0 ] ; then printf "$programme " ; fi
done
}
OUT=$(testDependances)
if [ ! ${#OUT} -eq 0 ] 
then 
	echo -e "\t\t\t----"
	echo "un ou plusieurs programmes ne sont pas installés"
	echo "pour installer, tapez"
	echo "sudo apt install $OUT"
	exit 1
# else
	# echo -e "\t\t\t----"
fi

# exit 0

# ---------------------------------------------
function _journal () {
	FICHIER_LOG="${NOM_LOGICIEL}.log"

	# if [ -f "${FICHIER_LOG}" ]
	# then
		# #echo "" > "${FICHIER_LOG}"
		# > "${FICHIER_LOG}"
	# else
		# > "${FICHIER_LOG}"
	# fi

	# on vide le log ou on le crée si il n'existe pas
	> "${FICHIER_LOG}"
	journal "ouverture - $(date)"
	journal "\t\t\t------------------------"
}
function journal () {
	local NOW=$(date +%s.%N)
	DIFF=$(echo "$NOW - $START" | bc)
	# echo -e "${@}" | tee -a "${FICHIER_LOG}" >/dev/null
	# echo -e "[${DIFF}] ${@}" | tee -a "${FICHIER_LOG}" >/dev/null
	echo -e "[${DIFF}] ${@}" >> "${FICHIER_LOG}"
	
}
# echo "ouverture du journal"
_journal

# ---------------------------------------------
# INITIALISATION DES VARIALES par des valeurs par défaut
# Communs
	SOURCE="${HOME}"
	DESTINATION="${HOME}"

# Mov2Mp4
# ${SOURCE} ${VCODEC} ${DESTINATION}
	VCODEC="libx264"
	# VCODEC="mpeg4"
# 
# Mp42Gifclassique
# ${SOURCE} ${RESOLUTION} ${DESTINATION}
	RESOLUTION="320x180"
# 
# Mp42Gif2classique
# ${DEBUT} ${DUREE} ${SOURCE} ${RESOLUTION} ${DESTINATION}
	DEBUT=10
	DUREE=5
# 
# Mp42Gifplus
# partie 1
# ${SOURCE} ${FPS} ${SCALE} ${FLAGS} ${PALETTE}
# partie 2
# ${SOURCE} ${PALETTE} ${FILER_COMPLEX} ${DESTINATION}
# 
# 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"

listRESOLUTION="1024x768 800x600 300x300 600x600 320x180"

dossierImages="$(dirname "${SOURCE}")/" ;
TMP_LOG="/tmp/$nomlogiciel.log"
TMP_TOUT="/tmp/affichetout.txt"


# ---------------------------------------------
# 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}
" > "${NOM_LOGICIEL}.ini"
# " | tee "${NOM_LOGICIEL}.ini" >/dev/null
[ $? -eq 0 ] && journal "sauvegarde effectuée"
}

# ---------------------------------------------
function chargerFichierIni () {
journal "\t\t\tinitialisation"
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
		> "${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"
	local 	RESOLUTIONS=()
	RESOLUTIONS+=( $listRESOLUTION )
	# RESOLUTIONS+=( "1024x768" "800x600" "300x300" "600x600" )
	readarray -t RESOLUTIONS < <(for a in "${RESOLUTIONS[@]}"; do echo "$a"; done | sort)
	# RESOLUTIONS=("${RESOLUTION}" "${RESOLUTIONS[@]}")
	# RESOLUTIONS=("${RESOLUTIONS[@]}")

	RESOLUTION_new="$(zenity --entry \
		--title="modifier la valeur de ..." \
		--text="RESOLUTION :" \
		--entry-text "${RESOLUTION}" "${RESOLUTIONS[@]}")" ;
	case $? in
		0)
			RESOLUTION="${RESOLUTION_new}" ; 
			journal "RESOLUTION=${RESOLUTION}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "DEBUT=${DEBUT}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "DUREE=${DUREE}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "VCODEC=${VCODEC}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "PALETTE=${PALETTE}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "FPS=${FPS}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "SCALE=${SCALE}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "FLAGS=${FLAGS}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "FILER_COMPLEX=${FILER_COMPLEX}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}

# ---------------------------------------------
function frm_principale () {
journal "\t\t\tfrm_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="$FONCTION"

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 \
	--title="vid2gif - ${NOM_LOGICIEL} - version $VERSION" \
	--text="$LAQUESTION" \
	--ok-label="Sélectionner" \
	--cancel-label="quitter" \
	--hide-column 1 --column "" --column "choix" --column "Valeur" \
	1 "$KA" "$VA" \
	2 "$KB" "$VB" \
	0 " ----------------- AIDE ICI -----------------" "		Paramètres" \
	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 " ----------------- AIDE ICI -----------------" "		Fonctions" \
	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 "\t\t\tfrm_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 ;;
		100)	DESTINATION="${SOURCE%.*}.mp4"
				ENCODE 0 && {
				SOURCE="${DESTINATION}"
				DESTINATION="${SOURCE%.*}.gif"
					}
			;;
		101)	ENCODE 1 ;;
		102)	ENCODE 2 ;;
		103)	ENCODE 3 && ENCODE 4 ;;

		0) AfficherAide ;;
		
		*) # 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 () {
journal "function setFichiersSelectionnes" ;
dossierImages_new="$(dirname "${SOURCE}")/"
if [ -d "$dossierImages_new" ]
then
	dossierImages="$dossierImages_new"
else
	dossierImages="$HOME/Images"
fi
#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}")/" ;
		journal "SOURCE=${SOURCE}" ;;
	1) journal "annulé" ;;
	-1) journal "An unexpected error has occurred." ;;
esac
}

function gestionExtGIF () {
	# Ajout éventuel d'une extension en gif
	local leFichier="${@}"
	local unTEST

	unTEST="${leFichier##*/}" # récupération du nom de fichier seul
	unTEST="${unTEST##*.}" # récupération de l'extension du fichier
	# unTEST="${unTEST,,}" # passage en minuscule pur bash
	if [ ! ${unTEST,,} == gif ] 
	then
		echo "${leFichier}".gif
	else 
		echo "${leFichier}"
	fi
	}
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="$(gestionExtGIF "${DESTINATION_new}")" ;
		journal "DESTINATION=${DESTINATION}" ;;
	1) journal "annulé" ;;
	-1) journal "An unexpected error has occurred." ;;
esac
}

# ---------------------------------------------
# FONCTIONS SPECIFIQUES

function Mov2Mp4bis () {
		# ffmpeg -i /point/de/montage/source.MOV -vcodec libx264 /point/de/montage/source.mp4
		DESTINATION="${SOURCE%.*}.mp4"
		# msgbox "DESTINATION=${DESTINATION}"
		ffmpeg -y -i "${SOURCE}" -vcodec "${VCODEC}" "${DESTINATION}" 2> "${TMP_LOG}" &
		wait $!
		return $?
}
function Mov2Mp4 () {
	journal "**********************
	Mov2Mp4"
	# Transformation d'un mov en mp4
	local unTEST
	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
		Mov2Mp4bis &
	fi
	journal "fin Mov2Mp4"
}
function Mp42Gifclassique () {
	journal "**********************
	Mp42Gifclassique
	Création d’un GIF animé, méthode «classique»
	A) gif contenant toute la vidéo
	ffmpeg -y -i ${SOURCE} -s ${RESOLUTION} ${DESTINATION}"
	# ffmpeg -y -i "${SOURCE}" -s "${RESOLUTION}" "${DESTINATION}"

	ffmpeg -y -i "${SOURCE}" -s "${RESOLUTION}" "${DESTINATION}" 2> "${TMP_LOG}" &
	wait $!
	return $?
}
function Mp42Gif2classique () {	journal "**********************
	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}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	journal "fin Mp42Gif2classique"
}
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}" 2> "${TMP_LOG}" &
		wait $!
		return $? 
}
function Mp42Gifplusplus () {
	journal "Mp42Gifplusplus"
	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}" 2> "${TMP_LOG}" &
	wait $!
	return $?
}
function POURCENTAGE () {
	sed -e 's/\r/\n/g' "${TMP_LOG}" | \
	grep time= | \
	tail -n 1 | \
	sed -e 's/frame/IMAGE/;s/fps/\nFPS/;s/q/\nQUALITEE/;s/size/\nPOID/;s/time/\nTEMPS/;s/bitrate/\nBITRATE/;s/speed/\nSPEED/' | \
	tr -d ' ' > "${TMP_TOUT}"

	. "${TMP_TOUT}"

	IFS=':' leTemps=( $TEMPS )
	ACTU_POURCENTAGE=$(bc<<<"(${leTemps[2]}+${leTemps[1]}*60+${leTemps[0]}*3600)*100/$TOTALS")

	grep IMAGE "${TMP_TOUT}" && \
	echo "#ENTRE : $SOURCE\nSORTIE : $DESTINATION\nIMAGE=$IMAGE\nFPS=$FPS\nQUALITEE=$QUALITEE\nPOID=$POID\nTEMPS=$TEMPS s\nBITRATE=$BITRATE\nSPEED=$SPEED" || \
	echo "#ENTRE : $SOURCE\nSORTIE : $DESYINATION\nPOID=$POID\nTEMPS=$TEMPS s\nBITRATE=$BITRATE\nSPEED=$SPEED"
	
	echo ${ACTU_POURCENTAGE}
}
function ENCODE () {
	DECOMPTE=$(ffmpeg -i "$SOURCE" 2>&1 | grep Duration | awk '{ print $DESTINATION }' | tr ':.,' ' ')
	DECOMPTEH=$(cut -d' ' -f2<<<$DECOMPTE)
	DECOMPTEM=$(cut -d' ' -f3<<<$DECOMPTE)
	DECOMPTES=$(cut -d' ' -f4<<<$DECOMPTE)
	TOTALS=$(bc<<<"$DECOMPTES+$DECOMPTEM*60+$DECOMPTEH*3600")

	# echo "DECOMPTE=$DECOMPTE"
	# echo "DECOMPTEH=$DECOMPTEH"
	# echo "DECOMPTEM=$DECOMPTEM"
	# echo "TOTALS=$TOTALS"

	case $1 in
		# x)		;;
		0)
			Mov2Mp4 &
			PID=$!
			;;
		1)
			Mp42Gifclassique &
			PID=$!
			;;
		2)
			Mp42Gif2classique &
			PID=$!
			;;
		3)
			Mp42Gifplus &
			PID=$!
			;;
		4)
			Mp42Gifplusplus &
			PID=$!
			;;

		*)	exit 112 ;; # pouquoi pas 112 ? :°)
	esac

	sleep .5 # TODO ; certainement inutile

	while [[ $(pidof ffmpeg) ]]
	do
		sleep .2 # TODO ; certainement UTILE 
		POURCENTAGE
	done | zenity --progress --auto-close --title="${txtTITLE}"

	if [[ "${PIPESTATUS[0]}" != "0" ]]
	then
		kill $(pidof ffmpeg)
	fi

	wait $PID
	SORTIE=$?

	if [[ "$SORTIE" = "0" ]]
	then
		zenity --info --title="${txtTITLE}" --text="Encodage terminé !"
	else
		zenity --error --title="${txtTITLE}" --text="Encodage interrompu !" --timeout=2
		zenity --text-info --filename="${TMP_LOG}" --title="${txtTITLE}" --width=800 --height=600
	fi

	journal "fin encodage"

	# exit $SORTIE # TODO : return $SORTIE ?
}

# ---------------------------------------------
function _main () {
journal "_main"	
	menuchoice=$(frm_principale);
	frm_principale_parser ${menuchoice%|*} # pour corriger le 1|1

	if [ ${QUITTER} -eq 0 ] ; then
		# on boucle _main tant que quitter est différent de 1
		_main
	fi
	}
function main () {
	#-initialisation
	chargerFichierIni ;
	QUITTER=0
	_main
	}
# ---------------------------------------------
function AfficherAide () {
# $FONCTION
echo "Convertir des vidéos ou parties vidéos mov et mp4 en gif
-------------------------------------------------------
ce script est issu d'une discussion sur Dolys
https://dolys.fr/forums/topic/creer-des-gifs-animes-de-qualite-a-partir-dune-video

-------------------------------------------------------
DEPENDANCES : $listDEPENDANCES

-------------------------------------------------------
Installation pour un utilisateur :
créer un dossier bin personnel :
mkdir ${HOME}/bin
y mettre le script
> ${HOME}/bin/vid2gif
le rendre exécutable
chmod +x ${HOME}/bin/vid2gif
éditer et coller le script suivant avec gedit (ou nano ou vi, vim, leafpad,...)
gedit ${HOME}/bin/vid2gif

Attention
si vous avez dû créer le dossier bin car il n'existait pas, 
mkdir ${HOME}/bin 
n'a pas renvoyé d'erreur (puisque le dossier n'existait pas !)
il faudra relancer l'utilisateur pour que ce dossier bin soit ajouté au PATH automatiquement
... dans le doute déconnectez puis reconnectez votre session

-------------------------------------------------------
Pour lancer le script 
dans un terminal
vid2gif

TODO en GUI :
il faut créer un lanceur ou un lien.

-------------------------------------------------------
Pour utiliser le tableau zenity
pour modifier une des valeurs du tableau, double cliquez sur la ligne à modifier
choisissez une valeur et valider... ou annuler pour récupérer la valeur précédente.

Choisissez un fichier mov et une destination gif
lancez l'option Mov2Mp4
ou
Choisissez un mp4 et choisissez une des options Mp42Gifclassique, Mp42Gif2classique ou Mp42Gifplus

NB pour faire des tests et comparer des options, pensez à changer le nom du fichier DESTINATION (le gif)
TODO :
zenity demande en cas d'écrasement d'un fichier, c'est à supprimer et à ajouter en fonction dans le script.
" | zenity --width=800 --height=600 --text-info="${@}"
	}

# ---------------------------------------------
# Programme principale
main

exit 0

Dernière modification par kholo (Le 14/07/2017, à 08:30)

Hors ligne

#11 Le 14/07/2017, à 16:04

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@kholo

J’ai testé ton interface graphique et voici ce que ça donne :
- fonction Mov2Mp4
Je pars d’un fichier.Mov qui fait 104 Mo et d'une durée de 38 secondes et j’arrive sans problème à un fichier Mp4 qui fait 25,5 Mo pour une durée de 38 secondes.
Donc, cette fonction marche très bien.

- fonction Mp42Gifclassique
Je pars d’un fichier Mp4 qui fait 25,5 Mo et d'une durée de 38 secondes et j’arrive sans problème à un gif animé faisant 8,7 Mo pour une durée de 38 secondes
Donc, cette fonction aussi marche très bien.

- fonction Mp42Gif2classique
Je pars d’un fichier Mp4 qui fait 25,5 Mo et d'une durée de 38 secondes et j’arrive sans problème à un gif animé faisant 1,1 Mo pour une durée de 4 secondes.
Donc, cette fonction aussi marche très bien.

- fonction Mp42Gifplus
Je pars d’un fichier Mp4 qui fait 25,5 Mo et d'une durée de 38 secondes et j’arrive sans problème à un gif animé faisant 13,7 Mo pour une durée de 38 secondes.
Donc, cette fonction aussi marche très bien.

Le seul problème que j’ai rencontré, c’est l’absence de fonction  Mp42Gif2plus (c’est à dire celle qui permettrait d’arriver à un gif animé de qualité améliorée et dont le poids est inférieur ou égal à 2 Mo. C'est dommage parce que c'est en fait la plus intéressante pour publier dans un topic où la taille des gif est le plus souvent limitée à 1 ou 2 Mo, guère plus.

Dernière remarque mais là c’est du pinaillage, la fonction Mp42Gifplus ne se déroule pas comme les autres si j’utilise l’interface graphique. Dans ce cas, il y a en effet 4 panneaux qui s’affichent successivement à l’écran au lieu de 2 seulement pour les autres fonctions (et il faut donc cliquer à 2 reprises sur un panneau  "encodage termine !"). Ca s’affiche dans cet ordre :
Le tout premier panneau qui s'affiche est celui-ci :
view-img-mini_2017-07-14-17c4e6866ecran.png
Là, il ne se passe rien de particulier, il faut laisser le script "mouliner" jusqu'à ce qu'apparaisse ce second panneau :
view-img-mini_2017-07-14-115ed7c65ecran2.png
On clique sur "Valider" et  un troisième panneau s'affiche :
view-img-mini_2017-07-14-13cd38167ecran3.png
Il faut laisser "mouliner" le script et, lorsqu'il a fini, un quatrième panneau apparaît :
view-img-mini_2017-07-14-158ab9298ecran4.png
On reclique sur "valider" et c'est fini, le gif est bien là.
Au total, malgré cette bizarrerie, cette fonction Mp42Gifplus arrive au bon résultat et c’est bien là le principal !

Encore un grand merci pour ton travail kholo !

Dernière modification par jlfh0816 (Le 14/07/2017, à 16:08)


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#12 Le 14/07/2017, à 19:45

kholo

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@jlfh0816
cool... ça c'est du retour...
Mp42Gif2plus : je regarde

Mp42Gifplus : j'en parle dans ma TODO list : je vais séparer la création de la palette de l'encodage
donc lors de la création, les infos de sortie ne se parsent pas de la même façon et la msgbox affiche que c'est terminé alors que ce n'est que la palette qui est terminée.

...
hop la 0.020 (attention je suis encore dessus mais elle a moins de défaut que la 0.019)

#!/bin/bash
# ----------------------------------------------
NOM_LOGICIEL="${0##*/}"
FONCTION="mise en script de cette page :
https://dolys.fr/forums/topic/creer-des-gifs-animes-de-qualite-a-partir-dune-video/

le script créera un fichier de configuration pour les variables
puis chargera une fenêtre de choix à partir d'une liste zenity"

txtTODO="# ----------------------------------------------
# gestion des arguments et des appels en LdC getopts
# ouverture et enregistrement de confs
# TMP_LOG et TMP_TOUT à passer en FIFO
# Mp42Gifplus à finir (palette; progress barre vide , msgbox donne fini au lieu de palette )
# mov2mp4 à supprimer de ce script (inutile)
# -> du coup revoir la gestion des extensions dans zenity --file-selection
# aide à finir...
# infos dans le log à améliorer
# Mp42Gifplus ; finir de séparer la création de la palette
# function _journal () { ...
# function _main () { # function main () {
# faire une fonction pour l'initialisation
# voir QUITTER=1 et _quitter ; doit pouvoir être plus propre (comme cette tournure !)
# 
# gestion des erreurs
# refonte du code ; normalisation (variable en maj, fonctions en min, underscores....)
# 
# GUI ; séparations de la gestion des fonctions pour n'avoir que les options utiles à chaque fonction
# GUI ; 0  ----------------- AIDE ICI -----------------		Paramètres ; pas bien placé 
# ajour de fonctionnalités
# localisation ;°)
"

VERSION="0.020"
# NOTES DE VERSIONS
# ----------------------------------------------
# kholo - cyril ury 07/2017
# ...
# 0.020
# ajout de la dernière fonction complete mp42gif2plus
# suppression de l'accès à mov2mp4
# 0.019
# ajout progress barre (du coup plein d'autres trucs)
# horodatage des logs, gestion de certaines erreurs 
# en parallèle de la gestion du "annuler" des barre de progression
# infos ajoutées pour lecteurs du forum ;°)
# TODO list bien remplie !
# 0.016
# reprise des variables ${variable} 
# ${QUITTER} devient variable numérique # -> if [ ${QUITTER} -eq 0 ] ; then
# 0.015
# mise en pratique des préconisations de Anonyme68
# https://forum.ubuntu-fr.org/viewtopic.php?pid=21760381#p21760381
# 0.014
# première mise en ligne
# ----------------------------------------------

# nautilus "$PWD"
# exit

# durée d'exécution pour horodatage du log
# START=$(date +%s.%N)
# command
# END=$(date +%s.%N)
# DIFF=$(echo "$END - $START" | bc)
# echo $DIFF
START=$(date +%s.%N)

function testDependances () {
local programme

listDEPENDANCES="bash
zenity
ffmpeg"

IFS=$'\n' listDEPENDANCES=( "$listDEPENDANCES" )
for programme in ${listDEPENDANCES[@]}
do
	programmePath=$(which "$programme") >/dev/null
	file -b -i "$programmePath" >/dev/null
	if [ ! $? -eq 0 ] ; then printf "$programme " ; fi
done
	}
OUT=$(testDependances)
if [ ! ${#OUT} -eq 0 ] 
then 
	echo -e "\t\t\t----"
	echo "un ou plusieurs programmes ne sont pas installés"
	echo "pour installer, tapez"
	echo "sudo apt install $OUT"
	exit 1
# else
	# echo -e "\t\t\t----"
fi

# exit 0

# ---------------------------------------------
function _journal () {
	FICHIER_LOG="${NOM_LOGICIEL}.log"

	# if [ -f "${FICHIER_LOG}" ]
	# then
		# #echo "" > "${FICHIER_LOG}"
		# > "${FICHIER_LOG}"
	# else
		# > "${FICHIER_LOG}"
	# fi

	# on vide le log ou on le crée si il n'existe pas
	> "${FICHIER_LOG}"
	journal "ouverture - $(date)"
	journal "\t\t\t------------------------"
	}
function journal () {
	local NOW=$(date +%s.%N)
	DIFF=$(echo "$NOW - $START" | bc)
	# echo -e "${@}" | tee -a "${FICHIER_LOG}" >/dev/null
	# echo -e "[${DIFF}] ${@}" | tee -a "${FICHIER_LOG}" >/dev/null
	echo -e "[${DIFF}] ${@}" >> "${FICHIER_LOG}"
	}
# echo "ouverture du journal"
_journal

# ---------------------------------------------
# INITIALISATION DES VARIALES par des valeurs par défaut
# Communs
	SOURCE="${HOME}"
	DESTINATION="${HOME}"

# Mov2Mp4
# ${SOURCE} ${VCODEC} ${DESTINATION}
	VCODEC="libx264"
	# VCODEC="mpeg4"
# 
# Mp42Gifclassique
# ${SOURCE} ${RESOLUTION} ${DESTINATION}
	RESOLUTION="320x180"
# 
# Mp42Gif2classique
# ${DEBUT} ${DUREE} ${SOURCE} ${RESOLUTION} ${DESTINATION}
	DEBUT=10
	DUREE=5
# 
# Mp42Gifplus
# partie 1
# ${SOURCE} ${FPS} ${SCALE} ${FLAGS} ${PALETTE}
# partie 2
# ${SOURCE} ${PALETTE} ${FILER_COMPLEX} ${DESTINATION}
# 
# 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"

listRESOLUTION="1024x768 800x600 300x300 600x600 320x180"

dossierImages="$(dirname "${SOURCE}")/" ;
TMP_LOG="/tmp/$nomlogiciel.log"
TMP_TOUT="/tmp/affichetout.txt"


# ---------------------------------------------
# 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}
" > "${NOM_LOGICIEL}.ini"
# " | tee "${NOM_LOGICIEL}.ini" >/dev/null
[ $? -eq 0 ] && journal "sauvegarde effectuée"
	}

# ---------------------------------------------
function chargerFichierIni () {
journal "\t\t\tinitialisation"
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
		> "${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"
	local 	RESOLUTIONS=()
	RESOLUTIONS+=( $listRESOLUTION )
	# RESOLUTIONS+=( "1024x768" "800x600" "300x300" "600x600" )
	readarray -t RESOLUTIONS < <(for a in "${RESOLUTIONS[@]}"; do echo "$a"; done | sort)
	# RESOLUTIONS=("${RESOLUTION}" "${RESOLUTIONS[@]}")
	# RESOLUTIONS=("${RESOLUTIONS[@]}")

	RESOLUTION_new="$(zenity --entry \
		--title="modifier la valeur de ..." \
		--text="RESOLUTION :" \
		--entry-text "${RESOLUTION}" "${RESOLUTIONS[@]}")" ;
	case $? in
		0)
			RESOLUTION="${RESOLUTION_new}" ; 
			journal "RESOLUTION=${RESOLUTION}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "DEBUT=${DEBUT}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "DUREE=${DUREE}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "VCODEC=${VCODEC}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "PALETTE=${PALETTE}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "FPS=${FPS}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "SCALE=${SCALE}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "FLAGS=${FLAGS}" ;;
		1) journal "annulé" ;;
		-1) journal "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}" ; 
			journal "FILER_COMPLEX=${FILER_COMPLEX}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}

# ---------------------------------------------
function frm_principale () {
journal "\t\t\tfrm_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="$FONCTION"

tropLONG="ffmpeg -y -i SOURCE -vf fps=FPS,scale=SCALE:-1:flags=FLAGS,palettegen PALETTE
ffmpeg -y -i SOURCE -i PALETTE -filter_complex FILER_COMPLEX DESTINATION"
tropLONG2="ffmpeg -y -ss DEBUT -t DUREE -i SOURCE -vf fps=FPS,scale=SCALE:-1:flags=FLAGS,palettegen PALETTE
ffmpeg -y -ss DEBUT -t DUREE -i SOURCE -i PALETTE -filter_complex FILER_COMPLEX DESTINATION"

zenity --list --width=1024 --height=620 \
	--title="vid2gif - ${NOM_LOGICIEL} - version $VERSION" \
	--text="$LAQUESTION" \
	--ok-label="Sélectionner" \
	--cancel-label="quitter" \
	--hide-column 1 --column "" --column "choix" --column "Valeur" \
	1 "$KA" "$VA" \
	2 "$KB" "$VB" \
	0 " ----------------- AIDE ICI -----------------" "		Paramètres" \
	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 " ----------------- AIDE ICI -----------------" "		Fonctions" \
	101 "Mp42Gifclassique" "ffmpeg -i SOURCE -s RESOLUTION DESTINATION" \
	102 "Mp42Gif2classique" "ffmpeg -y -ss DEBUT -t DUREE -i SOURCE -s RESOLUTION DESTINATION" \
	103 "Mp42Gifplus" "$tropLONG" \
	104 "Mp42Gif2plus" "$tropLONG2" \
	;
	# 100 "Mov2Mp4" "ffmpeg -i SOURCE -vcodec VCODEC DESTINATION" \ #
	}
function frm_principale_parser () {
journal "\t\t\tfrm_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)	DESTINATION="${SOURCE%.*}.mp4"
				ENCODE 0 && {
				SOURCE="${DESTINATION}"
				DESTINATION="${SOURCE%.*}.gif"
					}
				;;
		101)	ENCODE 1 ;;
		102)	ENCODE 2 ;;
		103)	ENCODE 3 && ENCODE 4 ;;
		104)	ENCODE 5 && ENCODE 6 ;;

		0) AfficherAide ;;
		
		*) # 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 () {
journal "function setFichiersSelectionnes" ;
dossierImages_new="$(dirname "${SOURCE}")/"
if [ -d "$dossierImages_new" ]
then
	dossierImages="$dossierImages_new"
else
	dossierImages="$HOME/Images"
fi
#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}")/" ;
		journal "SOURCE=${SOURCE}" ;;
	1) journal "annulé" ;;
	-1) journal "An unexpected error has occurred." ;;
esac
	}

function gestionExtGIF () {
	# Ajout éventuel d'une extension en gif
	local leFichier="${@}"
	local unTEST

	unTEST="${leFichier##*/}" # récupération du nom de fichier seul
	unTEST="${unTEST##*.}" # récupération de l'extension du fichier
	# unTEST="${unTEST,,}" # passage en minuscule pur bash
	if [ ! ${unTEST,,} == gif ] 
	then
		echo "${leFichier}".gif
	else 
		echo "${leFichier}"
	fi
	}
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="$(gestionExtGIF "${DESTINATION_new}")" ;
		journal "DESTINATION=${DESTINATION}" ;;
	1) journal "annulé" ;;
	-1) journal "An unexpected error has occurred." ;;
esac
	}

# ---------------------------------------------
# FONCTIONS SPECIFIQUES
function Mov2Mp4bis () {
		# ffmpeg -i /point/de/montage/source.MOV -vcodec libx264 /point/de/montage/source.mp4
		DESTINATION="${SOURCE%.*}.mp4"
		# msgbox "DESTINATION=${DESTINATION}"
		ffmpeg -y -i "${SOURCE}" -vcodec "${VCODEC}" "${DESTINATION}" 2> "${TMP_LOG}" &
		wait $!
		return $?
	}
function Mov2Mp4 () {
	journal "**********************
	Mov2Mp4"
	# Transformation d'un mov en mp4
	local unTEST
	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
		Mov2Mp4bis &
	fi
	journal "fin Mov2Mp4"
	}
function Mp42Gifclassique () {
	journal "**********************
	Mp42Gifclassique
	Création d’un GIF animé, méthode «classique»
	A) gif contenant toute la vidéo
	ffmpeg -y -i ${SOURCE} -s ${RESOLUTION} ${DESTINATION}"
	# ffmpeg -y -i "${SOURCE}" -s "${RESOLUTION}" "${DESTINATION}"

	ffmpeg -y -i "${SOURCE}" -s "${RESOLUTION}" "${DESTINATION}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	}
function Mp42Gif2classique () {
	journal "**********************
	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}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	journal "fin Mp42Gif2classique"
	}
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}" 2> "${TMP_LOG}" &
		wait $!
		return $? 
	}
function Mp42Gifplusplus () {
	journal "Mp42Gifplusplus"
	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}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	}
function Mp42Gif2plus () {
	journal "Mp42Gif2plus"
	journal "# étape 1 : génération d’une palette de couleurs"
	journal "ffmpeg -y -ss ${DEBUT} -t ${DUREE} -i ${SOURCE} -vf fps=${FPS},scale=${SCALE}:-1:flags=${FLAGS},palettegen ${PALETTE}"
	ffmpeg -y -ss "${DEBUT}" -t "${DUREE}" -i "${SOURCE}" -vf fps="${FPS}",scale="${SCALE}":-1:flags="${FLAGS}",palettegen "${PALETTE}" 2> "${TMP_LOG}" &
	wait $!
	return $? 
	}
function Mp42Gif2plusplus () {
	journal "Mp42Gif2plusplus"
	journal "# étape 2 : génération du GIF animé «amélioré»"
	ffmpeg -y -ss "${DEBUT}" -t "${DUREE}" -i "${SOURCE}" -i "${PALETTE}" -filter_complex "${FILER_COMPLEX}" "${DESTINATION}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	}

# ****************************************
function POURCENTAGE () {
	sed -e 's/\r/\n/g' "${TMP_LOG}" | \
	grep time= | \
	tail -n 1 | \
	sed -e 's/frame/IMAGE/;s/fps/\nFPS/;s/q/\nQUALITEE/;s/size/\nPOID/;s/time/\nTEMPS/;s/bitrate/\nBITRATE/;s/speed/\nSPEED/' | \
	tr -d ' ' > "${TMP_TOUT}"

	. "${TMP_TOUT}"

	IFS=':' leTemps=( $TEMPS )
	ACTU_POURCENTAGE=$(bc<<<"(${leTemps[2]}+${leTemps[1]}*60+${leTemps[0]}*3600)*100/$TOTALS")

	grep IMAGE "${TMP_TOUT}" && \
	echo "#ENTRE : $SOURCE\nSORTIE : $DESTINATION\nIMAGE=$IMAGE\nFPS=$FPS\nQUALITEE=$QUALITEE\nPOID=$POID\nTEMPS=$TEMPS s\nBITRATE=$BITRATE\nSPEED=$SPEED" || \
	echo "#ENTRE : $SOURCE\nSORTIE : $DESYINATION\nPOID=$POID\nTEMPS=$TEMPS s\nBITRATE=$BITRATE\nSPEED=$SPEED"
	
	echo ${ACTU_POURCENTAGE}
	}
function POURCENTAGE2 () {
	sed -e 's/\r/\n/g' "${TMP_LOG}" | \
	grep time= | \
	tail -n 1 | \
	sed -e 's/frame/IMAGE/;s/fps/\nFPS/;s/q/\nQUALITEE/;s/size/\nPOID/;s/time/\nTEMPS/;s/bitrate/\nBITRATE/;s/speed/\nSPEED/' | \
	tr -d ' ' > "${TMP_TOUT}"

	. "${TMP_TOUT}"

	IFS=':' leTemps=( $TEMPS )
	ACTU_POURCENTAGE=$(bc<<<"(${leTemps[2]}+${leTemps[1]}*60+${leTemps[0]}*3600)*100/$TOTALS")

	grep IMAGE "${TMP_TOUT}" && \
	echo "#ENTRE : $SOURCE\nSORTIE : $DESTINATION\nIMAGE=$IMAGE\nFPS=$FPS\nQUALITEE=$QUALITEE\nPOID=$POID\nTEMPS=$TEMPS s\nBITRATE=$BITRATE\nSPEED=$SPEED" || \
	echo "#ENTRE : $SOURCE\nSORTIE : $DESYINATION\nPOID=$POID\nTEMPS=$TEMPS s\nBITRATE=$BITRATE\nSPEED=$SPEED"
	
	echo ${ACTU_POURCENTAGE}
	}
function ENCODE () {
	DECOMPTE=$(ffmpeg -i "$SOURCE" 2>&1 | grep Duration | awk '{ print $DESTINATION }' | tr ':.,' ' ')
	DECOMPTEH=$(cut -d' ' -f2<<<$DECOMPTE)
	DECOMPTEM=$(cut -d' ' -f3<<<$DECOMPTE)
	DECOMPTES=$(cut -d' ' -f4<<<$DECOMPTE)
	TOTALS=$(bc<<<"$DECOMPTES+$DECOMPTEM*60+$DECOMPTEH*3600")

	TOTALS2=$(bc<<<"$DUREE-$DEBUT") # temps de la partie choisie pour être convertie

	# echo "DECOMPTE=$DECOMPTE"
	# echo "DECOMPTEH=$DECOMPTEH"
	# echo "DECOMPTEM=$DECOMPTEM"
	# echo "TOTALS=$TOTALS"
	# echo "TOTALS2=$TOTALS2"

	estPalette=false

	case $1 in
		# x)		;;
		0)
			Mov2Mp4 &
			PID=$!
			;;
		1)
			Mp42Gifclassique &
			PID=$!
			;;
		2)
			Mp42Gif2classique &
			PID=$!
			;;
		3)
			TOTALS="${TOTALS2}"
			estPalette=true
			Mp42Gifplus &
			PID=$!
			;;
		4)
			TOTALS="${TOTALS2}"
			Mp42Gifplusplus &
			PID=$!
			;;
		5)
			TOTALS="${TOTALS2}"
			estPalette=true
			Mp42Gif2plus &
			PID=$!
			;;
		6)
			TOTALS="${TOTALS2}"
			Mp42Gif2plusplus &
			PID=$!
			;;

		*)	exit 112 ;; # pouquoi pas 112 ? :°)
	esac

	sleep .5 # TODO ; certainement inutile

	while [[ $(pidof ffmpeg) ]]
	do
		sleep .2 # TODO ; certainement UTILE 
		if $estPalette
		then
			# POURCENTAGE
			POURCENTAGE2
		else
			POURCENTAGE
		fi
	done | zenity --progress --auto-close --title="${txtTITLE}"

	if [[ "${PIPESTATUS[0]}" != "0" ]]
	then
		kill $(pidof ffmpeg)
	fi

	wait $PID
	SORTIE=$?

	if [[ "$SORTIE" = "0" ]]
	then
		if $estPalette
		then
			zenity --info --title="${txtTITLE}" --text="création de la palette terminé !"
		else
			zenity --info --title="${txtTITLE}" --text="Encodage terminé !"
			# DEBUG
			# zenity --text-info --filename="${TMP_LOG}" --title="${txtTITLE}" --width=800 --height=600
		fi
	else
		zenity --error --title="${txtTITLE}" --text="Encodage interrompu !" --timeout=2
		zenity --text-info --filename="${TMP_LOG}" --title="${txtTITLE}" --width=800 --height=600
	fi

	journal "fin encodage"

	# exit $SORTIE # TODO : return $SORTIE ?
	}

# ---------------------------------------------
function _main () {
journal "_main"	
	menuchoice=$(frm_principale);
	frm_principale_parser ${menuchoice%|*} # pour corriger le 1|1

	if [ ${QUITTER} -eq 0 ] ; then
		# on boucle _main tant que quitter est différent de 1
		_main
	fi
	}
function main () {
	#-initialisation
	chargerFichierIni ;
	QUITTER=0
	_main
	}
# ---------------------------------------------
function AfficherAide () {
# $FONCTION
echo "Convertir des vidéos ou parties vidéos mov et mp4 en gif
-------------------------------------------------------
ce script est issu d'une discussion sur Dolys
https://dolys.fr/forums/topic/creer-des-gifs-animes-de-qualite-a-partir-dune-video

-------------------------------------------------------
DEPENDANCES : $listDEPENDANCES

-------------------------------------------------------
Installation pour un utilisateur :
créer un dossier bin personnel :
mkdir ${HOME}/bin
y mettre le script
> ${HOME}/bin/vid2gif
le rendre exécutable
chmod +x ${HOME}/bin/vid2gif
éditer et coller le script suivant avec gedit (ou nano ou vi, vim, leafpad,...)
gedit ${HOME}/bin/vid2gif

Attention
si vous avez dû créer le dossier bin car il n'existait pas, 
mkdir ${HOME}/bin 
n'a pas renvoyé d'erreur (puisque le dossier n'existait pas !)
il faudra relancer l'utilisateur pour que ce dossier bin soit ajouté au PATH automatiquement
... dans le doute déconnectez puis reconnectez votre session

-------------------------------------------------------
Pour lancer le script 
dans un terminal
vid2gif

TODO en GUI :
il faut créer un lanceur ou un lien.

-------------------------------------------------------
Pour utiliser le tableau zenity
pour modifier une des valeurs du tableau, double cliquez sur la ligne à modifier
choisissez une valeur et valider... ou annuler pour récupérer la valeur précédente.

Choisissez un fichier mov et une destination gif
lancez l'option Mov2Mp4
ou
Choisissez un mp4 et choisissez une des options Mp42Gifclassique, Mp42Gif2classique ou Mp42Gifplus

NB pour faire des tests et comparer des options, pensez à changer le nom du fichier DESTINATION (le gif)
TODO :
zenity demande en cas d'écrasement d'un fichier, c'est à supprimer et à ajouter en fonction dans le script.
" | zenity --width=800 --height=600 --text-info="${@}"
	}

# ---------------------------------------------
# Programme principale
main

exit 0

Hors ligne

#13 Le 15/07/2017, à 08:40

Anonyme68

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

Je me suis penché aussi sur le fond du script. Ça me parait aussi gratiné.

Quel peut bien être l’intérêt de pouvoir choisir un codec vidéo ? Le but c'est de convertir en GIF ?

Ensuite l’intérêt de pouvoir choisir son fichier palette ? Le fichier palette sera généré de toute manière si il est nécessaire, non ?

Pourquoi avoir limité aux seuls fichiers mp4 ? ffmpeg gère de nombreux formats

Ensuite, il y a le choix entre 2 types de conversions :

- Mp42Gifclassique --> inutile car ffmpeg fait de la merde (on pourrait nommé GIF avec palette de couleur standard par exemple)
- Mp42Gifplus --> un gif un peu plus normal mais de loin d'être un "GIF plus"

Dans le format GIF, chaque image peut avoir sa palette d'image, le fait de la calculer en avance limite la vidéo à 256 couleurs.

Avec le bon logiciel (imagemagick par exemple) on peut progressivement augmenter le nombre de couleurs dans la scène et faire un GIF de bien meilleure qualité. (et ça c'est un tour de force qu'on pourrait par exemple nommé "GIF plus").

Exemple :

youtube-dl https://www.youtube.com/watch?v=zDxgQjTN-8Q
mkdir frames
ffmpeg -i Free\ HD\ Colorful\ Kaleidoscope\ Video\ Background-zDxgQjTN-8Q.mp4 -vf scale=320:-1:flags=lanczos,fps=10 frames/ffout%03d.png
convert -loop 0 frames/ffout*.png output-avec-convert.gif
ffmpeg -y -ss 30 -t 3 -i Free\ HD\ Colorful\ Kaleidoscope\ Video\ Background-zDxgQjTN-8Q.mp4 -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
ffmpeg -y -i Free\ HD\ Colorful\ Kaleidoscope\ Video\ Background-zDxgQjTN-8Q.mp4 -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
ffmpeg -i Free\ HD\ Colorful\ Kaleidoscope\ Video\ Background-zDxgQjTN-8Q.mp4  -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" output-avec-ffmpeg.gif

tu compares output-avec-convert.gif et output-avec-ffmpeg.gif, il a pas photo. Pour une taille légèrement supérieure (12181268 octets et 17667977 octets).

Là c'est un exemple avec beaucoup de couleur, sinon c'est moins flagrant.

Après le résultat avec ffmpeg est loin d'être optimisé au niveau taille (vu que cela être le but sur le site Doltys) :

gifsicle --optimize=3 image.gif > image-optimisee.gif

846/2381 jeux linux sur Steam

Vous avez plein d'ISO d'ubuntu ? Une bonne bande passante ? Aimer partager ? Essayer mon script

Hors ligne

#14 Le 15/07/2017, à 09:17

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@kholo
J'ai testé ta version 0.020 et la fonction Mp42Gif2plus fonctionne très bien.
En partant du même fichier Mp4 de 25,5 Mo pour une durée de 38 secondes, j'arrive à un gif animé de 1,8 Mo et qui dure 5 secondes.
Merci, c'est exactement ce que je souhaitais !

Sinon, j'ai vu que tu avais également intercalé un panneau-mesage intermédiaire "réalisation de la palette terminée", c'est sympa car comme ça on sait où en est le script.

Un grand merci pour ce que tu fais et pour ta réactivité ! big_smile

@Anomyme68
Merci de tes commentaires. Etant une bille en informatique, j'ai besoin de temps pour comprendre tout ce que tu proposes mais je vais tester dès que j'en aurais le temps (là, c'est famille pour le reste du week-end...). Mais si on peut encore améliorer le gif final, c'est forcément tout bon à prendre smile

Dernière modification par jlfh0816 (Le 15/07/2017, à 09:18)


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#15 Le 15/07/2017, à 10:36

kholo

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

on doit pouvoir surtout reprendre la base comme moteur et l'utiliser pour tout un tas de conversions...
très instructif ce fil, je suis bien content de moi !
je vais digérer les infos de Anonyme68 et avancer sur ma DOTO liste
bon WeekEnd !!!

Hors ligne

#16 Le 15/07/2017, à 16:45

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@Anonyme68
J'ai testé ton script sur mon fichier mp4 de départ, toujours le même, celui qui fait 25,5 Mo pour une durée de 38 secondes. Et, effectivement, convert permet d'obtenir un gif animé de 10,7 Mo (contre 13,8 Mo pour ffmpeg).
Et la qualité visuelle est au rendez-vous.
Le seul problème pratique, c'est qu'apparemment convert ne permet pas (mais je peux me tromper !) de sélectionner une partie bien précise de la vidéo de départ pour construire son gif. Il ne sait qu'utiliser l'intégralité du mp4 de départ. Par exemple, il ne sait pas faire un gif en n'utilisant que l'extrait de mp4 situé entre la 10ème et la 15ème seconde de celui-ci.
Alors que ffmpeg fait cela sans soucis.

Dans l'absolu, on pourrait peut-être contourner l'obstacle en identifiant dans le dossier /frames, les seules frames correspondant à l'intervalle 10ème à 15ème secondes..... mais je ne vois pas comment faire. C'est dommage parce que si je pouvais isoler ces seules frames, on pourrait alors les copier dans un nouveau dossier auquel on appliquerait ensuite convert.
Et ça serait super parce que, j'en conviens tout à fait, convert fait des gifs animés de taille plus petite que ffmpeg et avec une qualité visuelle au moins aussi bonne.

Excuse-moi si je ne suis pas très clair dans mes explications mais, en tous cas, je te remercie de t'être penché sur ce sujet et d'avoir fait part de tes suggestions !  big_smile

Dernière modification par jlfh0816 (Le 15/07/2017, à 17:43)


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#17 Le 15/07/2017, à 17:28

kholo

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

si je reprend la procédure de Anonyme68, j'ai ça :

mkdir "${DIR_TEMP_FRAME}"
ffmpeg -i "$SOURCE" -vf scale="${SCALE}":-1:flags="${FLAGS}",fps="${FPS}" "${DIR_TEMP_FRAME}"/ffout%03d.png
convert -loop 0 "${DIR_TEMP_FRAME}"/ffout*.png "${DESTINATION}"

alors si on fait ça pour ffmpeg ?

ffmpeg -ss "${DEBUT}" -t "${DUREE}" -i "$SOURCE" -vf scale="${SCALE}":-1:flags="${FLAGS}",fps="${FPS}" "${DIR_TEMP_FRAME}"/ffout%03d.png

ça doit limiter la première sortie à la seule partie souhaitée

Hors ligne

#18 Le 15/07/2017, à 18:02

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@kholo
Mais oui, tu as raison, ça le fait !
Donc, pour un extrait de 4 secondes (pour cet essai, les 4 premières secondes de la vidéo mp4) de mon fichier mp4 de départ, j'obtiens un gif animé de 4 secondes qui fait 1,2 Mo avec convert et 1,4 Mo avec ffmpeg.
Et ceci pour une qualité vidéo visuelle très bonne (bon, faut dire que je n'ai pas trop de couleurs dans mon extrait pour voir s'il y a ou non une supériorité visuelle de convert par rapport à ffmpeg et vice-versa...).
Merci beaucoup kholo !

output_avec_ffmpeg (durée de 2,5 secondes et une taille finale de 912 Ko)
view-img-mini_2017-07-15-103231ff7outputavecff.gif

output_avec_convert (même durée de 2,5 secondes mais taille finale de 731 Ko seulement)
view-img-mini_2017-07-15-1a23b7089outputavecco.gif

Est-ce que tu vois une différence visuelle objective ou pas ?

Dernière modification par jlfh0816 (Le 15/07/2017, à 18:17)


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#19 Le 16/07/2017, à 11:38

erresse

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

Salut,
@jlfh0816:
Objectivement, je ne vois pas de différence significative entre les deux extraits que tu as postés sur le plan de la qualité de l'image.
Cependant, je ne sais pas si c'est subjectif, mais il me semble que l'animation créée avec convert est légèrement plus rapide que celle créée avec ffmpeg...
@kholo:
Bravo pour ton travail, ton script marche globalement bien mais je testerai volontiers la prochaine mouture !


Plus de 50 ans d'informatique, ça en fait des lignes de commandes en console, mais on n'avait pas le choix...
Excellente raison pour, aujourd'hui qu'on le peut, utiliser au maximum les INTERFACES GRAPHIQUES !
Important : Une fois résolu, pensez à clore votre sujet en ajoutant [Résolu] devant le titre du 1er message, et un bref récapitulatif de la solution à la fin de celui-ci. Merci.

Hors ligne

#20 Le 17/07/2017, à 00:12

Anonyme68

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

Au final, si la scène reste dans les mêmes couleurs tout le long, il n'y aura pas de grosses différences. Au niveau de la taille finale ça sera pire enfaite.

Le contre exemple, c'est le GIF qu'on peut voir en exemple sur le site dolys :

mini_935425combinedgimp.gif

Il y a clairement pas assez de couleurs pour rendre correctement toutes les scènes (paradoxalement elle est utilisée pour vanter la palette de couleur fixe). L'eau présente des dégradés assez disgracieux.

Dans l'absolu, on pourrait peut-être contourner l'obstacle en identifiant dans le dossier /frames, les seules frames correspondant à l'intervalle 10ème à 15ème secondes..... mais je ne vois pas comment faire. C'est dommage parce que si je pouvais isoler ces seules frames, on pourrait alors les copier dans un nouveau dossier auquel on appliquerait ensuite convert.
Et ça serait super parce que, j'en conviens tout à fait, convert fait des gifs animés de taille plus petite que ffmpeg et avec une qualité visuelle au moins aussi bonne.

Excuse-moi si je ne suis pas très clair dans mes explications mais, en tous cas, je te remercie de t'être penché sur ce sujet et d'avoir fait part de tes suggestions !  big_smile

Si tu connais ton nombre d'image par seconde, tu sais quand commence la 10ème seconde.

Exemple : pour 60 images par seconde, la 10ème seconde commence à l'image 600 et la 15ème à 900.

Donc pour sélectionner cette plage avec imagemagick tu fais :

convert mavideo.mp4[600-900] mongif.gif

a ce que j'ai pu voir, Imagemagick ne permet pas de retirer des images périodiquement, donc je pense que c'est plus simple d'extraire les images avec ffmpeg.

Dernière modification par Anonyme68 (Le 17/07/2017, à 00:14)


846/2381 jeux linux sur Steam

Vous avez plein d'ISO d'ubuntu ? Une bonne bande passante ? Aimer partager ? Essayer mon script

Hors ligne

#21 Le 17/07/2017, à 22:05

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

Anonyme68 a écrit :

Donc pour sélectionner cette plage avec imagemagick tu fais :

convert mavideo.mp4[600-900] mongif.gif

@Anonyme68
Merci pour cette suggestion pour sélectionner une plage bien définie de la vidéo mp4.

Anonyme68 a écrit :

...donc je pense que c'est plus simple d'extraire les images avec ffmpeg

Mais, tu as raison, c'est encore plus pratique avec ffmpeg pour extraire des images. C'est d'ailleurs la méthode que kholo m'a montré ci-dessus (post #17) et c'est ce qui m'a permis d'obtenir les 2 gifs animés ci-dessus (post #18), réalisés avec convert pour l'un et ffmpeg pour l'autre.
Encore merci de ton intervention !

Dernière modification par jlfh0816 (Le 17/07/2017, à 22:06)


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#22 Le 19/07/2017, à 10:18

kholo

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

bonjour,
ça avance, ça avance...

je reviens sur convert...
suite à une erreur, après recherches, je trouve ça dans convert :

convert -list delegate

et cette ligne :

mpeg:decode =>          "ffmpeg" -v -1 -i "%i" -vframes %S -vcodec pam -an -f rawvideo -y "%u.pam" 2> "%Z"

ce qui en soit signifie que "convert" sous traite le boulot à ffmpeg
pour moi ça limite l’intérêt de convert pour ce genre de boulot si on peut s'adresser directement à ffmpeg

-------------------------------------------
par contre, je dois pouvoir recréer la fonction en suivant le canevas de convert... et on voit que ya des trucs intéressants :

ffmpeg -v -1 -i "%i" -vframes %S -vcodec pam -an -f rawvideo -y "%u.pam" 2> "%Z"

on voit

-i "%i"

le fichier

 -vframes %S

-vframes number (output)
Set the number of video frames to output. This is an obsolete alias for "-frames:v", which you should use instead.

-vcodec pam

-vcodec codec (output) Set the video codec. This is an alias for "-codec:v".

 -an 

Disable audio recording.

-f rawvideo

-f fmt (input/output) Force input or output file format. The format is normally auto detected for input files and guessed from the file extension for output files, so this option is not needed in most cases.

-y 

écrasement de destination sans confirmation

"%u.pam"

la sortie

2> "%Z"

la gestion du journal

Hors ligne

#23 Le 19/07/2017, à 13:21

kholo

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

version 0.024

#!/bin/bash

# ----------------------------------------------

# ETAGE PID FIFO
PID=$$
#FIFO=/tmp/FIFO${PID}
#mkfifo ${FIFO}
#
# tmpdir=$(mktemp -d)
# trap 'rm -rf "$tmpdir"' EXIT INT TERM HUP
# mkfifo "$tmpdir/pipe" 
# 


# ----------------------------------------------
NOM_LOGICIEL="${0##*/}"
FONCTION="mise en script de cette page :
https://dolys.fr/forums/topic/creer-des-gifs-animes-de-qualite-a-partir-dune-video/

vidéos vers gif animés"

txtTODO="
# ----------------------------------------------
# gestion des arguments et des appels en LdC getopts
# ouverture et enregistrement de confs
# TMP_LOG et TMP_TOUT à passer en FIFO
# Mp42Gifplus à finir (palette; progress barre vide , msgbox donne fini au lieu de palette )
# mov2mp4 à supprimer de ce script (inutile)
# -> du coup revoir la gestion des extensions dans zenity --file-selection
# aide à finir...
# infos dans le log à améliorer
# Mp42Gifplus ; finir de séparer la création de la palette
# function _journal () { ...
# function _main () { # function main () {
# faire une fonction pour l'initialisation
# voir QUITTER=1 et _quitter ; doit pouvoir être plus propre (comme cette tournure !)
# 
# gestion des dépendances ; convert nescessite ImageMagick -> bug dans apt install
# 
# gestion des erreurs
# refonte du code ; normalisation (variable en maj, fonctions en min, underscores....)
# 
# GUI ; séparations de la gestion des fonctions pour n'avoir que les options utiles à chaque fonction
# GUI ; 0  ----------------- AIDE ICI -----------------		Paramètres ; pas bien placé 
# ajour de fonctionnalités
# localisation ;°)
"

VERSION="0.024"
txtTITLE="${NOM_LOGICIEL} - version ${VERSION}"
# NOTES DE VERSIONS
# ----------------------------------------------
# kholo - cyril ury 07/2017
# ...
# 0.024
# convert ; convertion directe de mp4 à gif pas fonctionnelle
# time out sur les zenity info pour qu'ils se ferment tout seul
# mise en forme
# 0.023
# étage PID
# ajout gestion de TMP
# ajout FIFO
# 0.022
# refonte d'une partie du code
# 0.021
# début traitement d'arguments
# FILER_COMPLEX créé automatiqueùment sur 1 seul format voir setFILER_COMPLEX
# 0.020
# ajout de la dernière fonction complete mp42gif2plus
# suppression de l'accès à mov2mp4
# 0.019
# ajout progress barre (du coup plein d'autres trucs)
# horodatage des logs, gestion de certaines erreurs 
# en parallèle de la gestion du "annuler" des barre de progression
# infos ajoutées pour lecteurs du forum ;°)
# TODO list bien remplie !
# 0.016
# reprise des variables ${variable} 
# ${QUITTER} devient variable numérique # -> if [ ${QUITTER} -eq 0 ] ; then
# 0.015
# mise en pratique des préconisations de Anonyme68
# https://forum.ubuntu-fr.org/viewtopic.php?pid=21760381#p21760381
# 0.014
# première mise en ligne
# ----------------------------------------------

# ---------------------------------------------

#pour debug
# nautilus "$PWD"
# exit 0

# ---------------------------------------------

# durée d'exécution pour horodatage du log
# START=$(date +%s.%N)
# command
# END=$(date +%s.%N)
# DIFF=$(echo "$END - $START" | bc)
# echo $DIFF
START=$(date +%s.%N)

# ---------------------------------------------

# ETAGE testDependances 
function testDependancesSuite () {
	local programme
	local programmePath

	listDEPENDANCES="bash zenity ffmpeg gifsicle"

	# IFS=$'\n' listDEPENDANCES=( "$listDEPENDANCES" )
	IFS=' ' listDEPENDANCES=( "$listDEPENDANCES" )
	for programme in ${listDEPENDANCES[@]}
	do
		programmePath=$(which "$programme") >/dev/null
		file -b -i "$programmePath" >/dev/null
		if [ ! $? -eq 0 ] ; then printf "$programme " ; fi
	done

	# imagemagick -> convert
	programmePath=$(which "convert") >/dev/null
	file -b -i "$programmePath" >/dev/null
	if [ ! $? -eq 0 ] ; then printf "imagemagick " ; fi
	}
function testDependances () {
	OUT=$(testDependancesSuite)
	if [ ! ${#OUT} -eq 0 ] 
	then 
		echo -e "\t\t\t----"
		echo "un ou plusieurs programmes ne sont pas installés"
		echo "pour installer, tapez"
		echo "sudo apt install $OUT"
		exit 1
	# else
		# echo -e "\t\t\t----"
	fi
	}
testDependances

# ---------------------------------------------

# ETAGE JOURNAL
function _journal () {
	FICHIER_LOG="${NOM_LOGICIEL}.log"

	# on vide le log ou on le crée si il n'existe pas
	> "${FICHIER_LOG}"
	journal "ouverture - $(date)"
	journal "\t\t\t------------------------"
	}
function journal () {
	local NOW=$(date +%s.%N)
	DIFF=$(echo "$NOW - $START" | bc)
	# echo -e "${@}" | tee -a "${FICHIER_LOG}" >/dev/null
	# echo -e "[${DIFF}] ${@}" | tee -a "${FICHIER_LOG}" >/dev/null
	echo -e "[${DIFF}] ${@}" >> "${FICHIER_LOG}"
	}
_journal

# ---------------------------------------------

# ETAGE INITIALISATION 
# VARIALES par des valeurs par défaut
function _INITIALISATION_DEFAUT () {
	DIR_PERSO="$HOME/.config/kholo/vid2gif"
	[ ! -d "${DIR_PERSO}" ] && mkdir -p "${DIR_PERSO}"
	FICHIER_INI="${DIR_PERSO}/${NOM_LOGICIEL}.ini"

	DIR_MODELES="${DIR_PERSO}/mods"
	[ ! -d "${DIR_MODELES}" ] && mkdir -p "${DIR_MODELES}"

	TMP="/tmp/${NOM_LOGICIEL}/${PID}"
	[ ! -d "${TMP}" ] && mkdir -p "${TMP}"

	SOURCE="${HOME}"
	DESTINATION="${HOME}"

	DIR_IMAGES="$(dirname "${SOURCE}")/" ;
	TMP_LOG="${TMP}/${NOM_LOGICIEL}.log"
	TMP_TOUT="${TMP}/affichetout.txt"

	DIR_TEMP_FRAME="${TMP}/frame"
	TMP_FFMPEG_PNG="ffout"

	VCODEC="libx264"	# VCODEC="mpeg4"
	RESOLUTION="320x180"
	DEBUT=10
	DUREE=5
	PALETTE="${TMP}/palette.png"
	FPS=10
	SCALE=320
	FLAGS='lanczos'
	FILER_COMPLEX="fps=${FPS},scale=${SCALE}:-1:flags=${FLAGS}[x];[x][1:v]paletteuse"

	listRESOLUTION="1024x768 800x600 300x300 600x600 320x180"
	TMP_LIST="${TMP}/file.txt"
	# > "${TMP_LIST}"
	}

# 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 CreerLignesOptions () {
echo "# création automatique $0 
# $(date)
# vid2gif version $VERSION"

case $1 in
	tout) 
	echo "SOURCE=${SOURCE}
DESTINATION=${DESTINATION}"
	;;
esac
echo "RESOLUTION=${RESOLUTION}
DEBUT=${DEBUT}
DUREE=${DUREE}
VCODEC=${VCODEC}
# PALETTE=${PALETTE}
FPS=${FPS}
SCALE=${SCALE}
FLAGS=${FLAGS}
FILER_COMPLEX=${FILER_COMPLEX}
"
	}
function sauverIni () {
	journal "function sauverIni"
	CreerLignesOptions tout > "${FICHIER_INI}"

	# " | tee "${FICHIER_INI}" >/dev/null
	[ $? -eq 0 ] && journal "sauvegarde effectuée"
	}
function chargerFichierIni () {
	journal "\t\t\tinitialisation"
	journal "FICHIER_INI"
	journal "le nom du fichier ini est : ${FICHIER_INI}"
	if [ -f "${FICHIER_INI}" ] ; then
		journal "chargement du fichier ini"
		chargerIni
	else
		> "${FICHIER_INI}"
	fi
	}

# TRAITEMENT DES ARGUMENTS DE LANCEMENT DU SCRIPT
function traiterLesArguments () {

# pour tests
	# if [ -z $1 ]; then
		# $0 -x -z -o OPTION -f /tmp -o /etc/fstab -f "/un/chemin/avec des/espaces" un autre truc
		# exit 4
	# fi


	while getopts f:xzo: option # : pour dire que l'option attend un argument
	do
		case "$option" in
			x) echo "x";;
			z) echo "z";;
			o) echo "o=$OPTARG";;
			f) echo "fichier=$OPTARG";;
		esac
	done
	shift $(($OPTIND-1))

	[ -n $1 ] && echo "un autre fichier : ${@}"

	}
# traiterLesArguments "$@" # FONCTION EN SOMMEIL

# ---------------------------------------------

function choisirFICHIER_OPTIONS () {

	# DIR_MODELES="$(zenity --file-selection --directory)"
	# DIR_MODELES="mods"

	TMP_LIST="${TMP}/file.txt"

	> "${TMP_LIST}"

	list="$(cd "$DIR_MODELES" ; ls -1 *)"
	IFS=$'\n'
	for l in ${list[@]}
	do
		echo "valeur=$l=FALSE" >> "${TMP_LIST}"
	done
	echo "valeur=autre=FALSE" >> "${TMP_LIST}"

	NAMES=( $(awk -F= '$1 == "valeur"{print $3"\n"$2}' "${TMP_LIST}") )
	zenity --list --text="Du texte ici:" --radiolist --column "Colonne A" --column "Colonne B" "${NAMES[@]}"

	echo "? -> $?"
	rm -f "${TMP_LIST}"
}

# ETAGE sauvegarde et ouverture des options en fichier
# TODO
function FICHIER_OPTIONS_Ouvrir () {
journal "fonction FICHIER_OPTIONS_Ouvrir"
	setFICHIER_OPTIONS
	[ -f "${FICHIER_OPTIONS}" ] && \
	{
		# msgbox "lecture du fichier ${FICHIER_OPTIONS}"
		while read ligne ;
		do
			parserLigneIni "$ligne"
		done < "${FICHIER_OPTIONS}"
	}
	setPALETTE
	}
function FICHIER_OPTIONS_Enregistrer () {
	journal "function FICHIER_OPTIONS_Enregistrer"
	msgbox "fonction à terminer : FICHIER_OPTIONS_Enregistrer"
	# $(CreerLignesOptions) > "${FICHIER_OPTIONS}"
	# [ $? -eq 0 ] && journal "sauvegarde effectuée"

	}
function FICHIER_OPTIONS_EnregistrerSous () {
	journal "function FICHIER_OPTIONS_EnregistrerSous"

	msgbox "fonction à terminer : FICHIER_OPTIONS_EnregistrerSous"
	# FICHIER_OPTIONS_Enregistrer
	}

# ---------------------------------------------

# ETAGE Fonctions générales Alias
function msgbox () {
	zenity --info --text="${@}"
	}

function nettoyerDossierTmp () {
# 
	# cd "${@}"
	# for element in *
	# do
		# if [ -f "$element" ]
		# then
			# rm "$element"
		# else 
			# nettoyerDossierTmp "$element"
			# rm -d "$element"
		# fi
	# done
	# rm -d "${@}"
	rm -R "${TMP}"
	}
function _quitter () {
journal "_quitter"
# mettre ici tout ce qui sera nescessaire à la bonne fermeture
	sauverIni
	nettoyerDossierTmp
	exit 0
	}

# ---------------------------------------------

# ETAGE Fonctions pour définir les valeurs des variables
function setSource () {
# on peut transformer cette partie pour des traitements par lots
	setFichiersSelectionnes
	}
function frm_FichiersSelectionnes () {
	zenity --file-selection \
		--title="Séléctionnez des fichiers" \
		--filename="$DIR_IMAGES/" \
		--file-filter='Images (mp4, mov) | *.mp4 *.MP4 *.mov *.MOV' \
		--file-filter='All files | *'
	}
function setFichiersSelectionnes () {
	journal "function setFichiersSelectionnes" ;
	DIR_IMAGES_new="$(dirname "${SOURCE}")/"
	[ -d "$DIR_IMAGES_new" ] && DIR_IMAGES="$DIR_IMAGES_new" || DIR_IMAGES="$HOME/Images"

	local SOURCE_new
	SOURCE_new="$(frm_FichiersSelectionnes)" ;

	case $? in
		0) 
			SOURCE="${SOURCE_new}" ;
			DIR_IMAGES="$(dirname "${SOURCE}")/" ;
			journal "SOURCE=${SOURCE}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}

function gestionExtGIF () {
	# Ajout éventuel d'une extension en gif
	local leFichier="${@}"
	local unTEST

	unTEST="${leFichier##*/}" # récupération du nom de fichier seul
	unTEST="${unTEST##*.}" # récupération de l'extension du fichier
	# unTEST="${unTEST,,}" # passage en minuscule pur bash
	if [ ! ${unTEST,,} == gif ] 
	then
		echo "${leFichier}".gif
	else 
		echo "${leFichier}"
	fi
	}
function setDestination () {
# on peut transformer cette partie pour des traitements par lots
	setDESTINATION
	}
function frm_DESTINATION () {
	zenity --file-selection \
		--title="Séléctionnez un fichier" \
		--save --confirm-overwrite \
		--filename="${DESTINATION}" \
		--file-filter='gif files (gif) | *.gif'
	}
function setDESTINATION () {
	# choisir un fichier de destination
	local DESTINATION_new="$(frm_DESTINATION)" ;

	case $? in
		0)
			DESTINATION="$(gestionExtGIF "${DESTINATION_new}")" ;
			journal "DESTINATION=${DESTINATION}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}

function setRESOLUTION () {
	journal "set RESOLUTION"
	local 	RESOLUTIONS=()
	RESOLUTIONS+=( $listRESOLUTION )
	# RESOLUTIONS+=( "1024x768" "800x600" "300x300" "600x600" )
	readarray -t RESOLUTIONS < <(for a in "${RESOLUTIONS[@]}"; do echo "$a"; done | sort)
	# RESOLUTIONS=("${RESOLUTION}" "${RESOLUTIONS[@]}")
	# RESOLUTIONS=("${RESOLUTIONS[@]}")

	RESOLUTION_new="$(zenity --entry \
		--title="${txtTITLE}" \
		--text="modifier la valeur de... RESOLUTION :" \
		--entry-text "${RESOLUTION}" "${RESOLUTIONS[@]}")" ;
	case $? in
		0)
			RESOLUTION="${RESOLUTION_new}" ; 
			journal "RESOLUTION=${RESOLUTION}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}
function setDEBUT () {
	journal "set DEBUT"
	DEBUT_new="$(zenity --entry \
		--title="${txtTITLE}" \
		--text="modifier la valeur de... DEBUT :" \
		--entry-text "${DEBUT}")" ;
	case $? in
		0)
			DEBUT="${DEBUT_new}" ; 
			journal "DEBUT=${DEBUT}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}
function setDUREE () {
	journal "set DUREE"
	DUREE_new="$(zenity --entry \
		--title="${txtTITLE}" \
		--text="modifier la valeur de... DUREE :" \
		--entry-text "${DUREE}")" ;
	case $? in
		0)
			DUREE="${DUREE_new}" ; 
			journal "DUREE=${DUREE}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}
function setVCODEC () {
	journal "set VCODEC"
	VCODEC_new="$(zenity --entry \
		--title="${txtTITLE}" \
		--text="modifier la valeur de... VCODEC :" \
		--entry-text "${VCODEC}")" ;
	case $? in
		0)
			VCODEC="${VCODEC_new}" ; 
			journal "VCODEC=${VCODEC}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}
function setPALETTE () {
	journal "set PALETTE"
	# PALETTE_new="$(zenity --entry \
		# --title="${txtTITLE}" \
		# --text="modifier la valeur de... PALETTE :" \
		# --entry-text "${PALETTE}")" ;
	# case $? in
		# 0)
			# PALETTE="${PALETTE_new}" ; 
			# journal "PALETTE=${PALETTE}" ;;
		# 1) journal "annulé" ;;
		# -1) journal "An unexpected error has occurred." ;;
	# esac
	PALETTE="${TMP}/palette.png"
	}
function setFPS () {
	journal "set FPS"
	FPS_new="$(zenity --entry \
		--title="${txtTITLE}" \
		--text="modifier la valeur de... FPS :" \
		--entry-text "${FPS}")" ;
	case $? in
		0)
			FPS="${FPS_new}" ; 
			journal "FPS=${FPS}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}
function setSCALE () {
	journal "set SCALE"
	SCALE_new="$(zenity --entry \
		--title="${txtTITLE}" \
		--text="modifier la valeur de... SCALE :" \
		--entry-text "${SCALE}")" ;
	case $? in
		0)
			SCALE="${SCALE_new}" ; 
			journal "SCALE=${SCALE}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}
function setFLAGS () {
	journal "set FLAGS"
	FLAGS_new="$(zenity --entry \
		--title="${txtTITLE}" \
		--text="modifier la valeur de... FLAGS :" \
		--entry-text "${FLAGS}")" ;
	case $? in
		0)
			FLAGS="${FLAGS_new}" ; 
			journal "FLAGS=${FLAGS}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	}
function setFILER_COMPLEX () {
	journal "set FILER_COMPLEX"
	# FILER_COMPLEX_new="$(zenity --entry \
		# --title="${txtTITLE}" \
		# --text="modifier la valeur de... FILER_COMPLEX :" \
		# --entry-text "${FILER_COMPLEX}")" ;
	# case $? in
		# 0)
			# FILER_COMPLEX="${FILER_COMPLEX_new}" ; 
			# journal "FILER_COMPLEX=${FILER_COMPLEX}" ;;
		# 1) journal "annulé" ;;
		# -1) journal "An unexpected error has occurred." ;;
	# esac
	FILER_COMPLEX="fps=${FPS},scale=${SCALE}:-1:flags=${FLAGS}[x];[x][1:v]paletteuse"
	}

function setFICHIER_OPTIONS () {
journal "function setFICHIER_OPTIONS" ;
#sélectionner les images

	# TMP_LIST="${TMP}/file.txt"
	> "${TMP_LIST}"

	list="$(cd "$DIR_MODELES" ; ls -1 *)"
	IFS=$'\n'
	for l in ${list[@]}
	do
		echo "valeur=$l=FALSE" >> "${TMP_LIST}"
	done
	echo "valeur=autre=FALSE" >> "${TMP_LIST}"

	NAMES=( $(awk -F= '$1 == "valeur"{print $3"\n"$2}' "${TMP_LIST}") )
	# zenity --list --text="Du texte ici:" --radiolist --column "Colonne A" --column "Colonne B" "${NAMES[@]}"

	local FICHIER_OPTIONS_new="$(zenity --list --text="Du texte ici:" --radiolist --column "Colonne A" --column "Colonne B" "${NAMES[@]}")" ;
	# msgbox "${FICHIER_OPTIONS}"
	case $? in
		0) 
			FICHIER_OPTIONS="${DIR_MODELES}/${FICHIER_OPTIONS_new}" ;
			# DIR_IMAGES="$(dirname "${FICHIER_OPTIONS}")/" ;
			journal "FICHIER_OPTIONS=${FICHIER_OPTIONS}" ;;
		1) journal "annulé" ;;
		-1) journal "An unexpected error has occurred." ;;
	esac
	rm -f "${TMP_LIST}"
	}

# ---------------------------------------------

# ETAGE FORME 
# PRINCIPALE
function frm_principale () {
journal "\t\t\tfrm_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}"
	setFILER_COMPLEX
	# VK="fps=FPS,scale=SCALE:-1:flags=FLAGS[x];[x][1:v]paletteuse"

LAQUESTION="$FONCTION"

# 101 "Mp42Gifclassique" "ffmpeg -i SOURCE -s RESOLUTION DESTINATION"
txtfonction[1]="Mp42Gif simple"
valfonction[1]="ffmpeg -i SOURCE -s RESOLUTION DESTINATION
-> conversion complète avec ffmpeg
-----------------------"
	# 102 "Mp42Gif2classique" "ffmpeg -y -ss DEBUT -t DUREE -i SOURCE -s RESOLUTION DESTINATION"
txtfonction[2]="Mp42Gif simple DEBUT / DUREE"
valfonction[2]="ffmpeg -y -ss DEBUT -t DUREE -i SOURCE -s RESOLUTION DESTINATION
-> comme précédente mais choix d'un début et d'une fin
-----------------------"
	# 103 "Mp42Gifplus" "$tropLONG"
txtfonction[3]="Mp42Gif palette"
valfonction[3]="ffmpeg -y -i SOURCE -vf fps=FPS,scale=SCALE:-1:flags=FLAGS,palettegen PALETTE
ffmpeg -y -i SOURCE -i PALETTE -filter_complex FILER_COMPLEX DESTINATION
-> conversion en deux passes ; une crée une palette de couleur, l'autre convertie en utilisant la palette
-----------------------"
	# 104 "Mp42Gif2plus" "$tropLONG2"
txtfonction[4]="Mp42Gif palette DEBUT / DUREE"
valfonction[4]="ffmpeg -y -ss DEBUT -t DUREE -i SOURCE -vf fps=FPS,scale=SCALE:-1:flags=FLAGS,palettegen PALETTE
ffmpeg -y -ss DEBUT -t DUREE -i SOURCE -i PALETTE -filter_complex FILER_COMPLEX DESTINATION
-> idem précédent mais choix d'un début et d'une fin
-----------------------"
	# 105 "Mp42Gif2Anonyme68" "$tropLONG3"
txtfonction[5]="Mp42Gif Anonyme68 DEBUT / DUREE"
valfonction[5]="ffmpeg -ss DEBUT -t DUREE -i SOURCE -vf scale=SCALE:-1:flags=FLAGS,fps=FPS DIR_TEMP_FRAME/TMP_FFMPEG_PNG%03d.png
convert -loop 0 DIR_TEMP_FRAME/TMP_FFMPEG_PNG*.png DESTINATION
-> selon méthode de Anonyme68 et utilisation de convert du paquet Imagemagic
-----------------------"
	# 106 "Mp42GifConvert" "convert SOURCE[V1-V2] DESTINATION 	# V1 et V2, début et fin en nombre de frames"
# txtfonction[6]="Mp42GifConvert"
# valfonction[6]="convert SOURCE[V1-V2] DESTINATION 	# V1 et V2, début et fin en nombre de frames
# conversion avec convert du paquet Imagemagick"

zenity --list --width=1200 --height=650 \
	--title="vid2gif - ${txtTITLE}" \
	--text="${LAQUESTION}" \
	--ok-label="Sélectionner" \
	--cancel-label="quitter" \
	--hide-column 1 --column "" --column "choix" --column "Valeur" \
	1 "$KA" "$VA" \
	2 "$KB" "$VB" \
	0 " ----------------- AIDE ICI -----------------" "		Choisir les paramètres						----------------------------------" \
	200 "options" "modifier" \
	201 "options" "voir" \
	0 " ----------------- AIDE ICI -----------------" "		Choisir une fonction							----------------------------------" \
	101 "${txtfonction[1]}" "${valfonction[1]}" \
	102 "${txtfonction[2]}" "${valfonction[2]}" \
	103 "${txtfonction[3]}" "${valfonction[3]}" \
	104 "${txtfonction[4]}" "${valfonction[4]}" \
	105 "${txtfonction[5]}" "${valfonction[5]}" \
	;
	# 106 "${txtfonction[6]}" "${valfonction[6]}" \ #
	}
function frm_principale_parser () {
journal "\t\t\tfrm_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)		;; # 11)		setFILER_COMPLEX ;;

		# 100)	DESTINATION="${SOURCE%.*}.mp4"
				# lanceurEncodage 0 && {
				# SOURCE="${DESTINATION}"
				# DESTINATION="${SOURCE%.*}.gif"
					# }
				# ;;
		101)	lanceurEncodage 1 ;;
		102)	lanceurEncodage 2 ;;
		103)	lanceurEncodage 3 && lanceurEncodage 4 ;;
		104)	lanceurEncodage 5 && lanceurEncodage 6 ;;
		# 105)	Mp42Gif2Anonyme68 && Mp42Gif2Anonyme68Suite ;;
		105)	lanceurEncodage 7 && lanceurEncodage 8 ;;
		# 106)	Mp42GifConvert ;;
		# 106)	lanceurEncodage 9 ;;

		200)	 
				local menuchoice
				menuchoice=$(frm_options);
				frm_options_parser ${menuchoice%|*} # pour corriger le 1|1
				;;

		201)	voirLesVariables ;;
		0)		AfficherAide ;;
		
		*) # POUR QUITTER PROPREMENT (sauver le ini !)
			QUITTER=1
			_quitter ;;
	esac
	}

function frm_options () {
	journal "frm_options"

	KFOO="Fichier option ouvrir"
	VFOO="${FICHIER_OPTIONS}"
	KFOE="Fichier option enregistrer"
	VFOE="${FICHIER_OPTIONS}"

	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}"
	setFILER_COMPLEX
	VK="fps=FPS,scale=SCALE:-1:flags=FLAGS[x];[x][1:v]paletteuse"

zenity --list --width=1024 --height=600 \
	--title="vid2gif - ${NOM_LOGICIEL} - version ${VERSION}" \
	--text="${LAQUESTION}" \
	--ok-label="Sélectionner" \
	--cancel-label="quitter" \
	--hide-column 1 --column "" --column "choix" --column "Valeur" \
	1 "$KA" "$VA" \
	2 "$KB" "$VB" \
	301 "$KFOO" "$VFOO" \
	302 "$KFOE" "$VFOE" \
	0 " ----------------- AIDE ICI -----------------" "		Choisir les paramètres						----------------------------------" \
	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" \
	;
	}
function frm_options_parser () {
journal "\t\t\tfrm_options_parser"
journal " :tfrm_options_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)		;;
		301)	FICHIER_OPTIONS_Ouvrir ;;
		302)	FICHIER_OPTIONS_EnregistrerSous ;;

		0) AfficherAide ;;
		
		*) # POUR QUITTER PROPREMENT (sauver le ini !)
			# QUITTER=1
			# _quitter 
			;;
	esac
	}

# ---------------------------------------------

# ETAGE FONCTIONS SPECIFIQUES
function Mov2Mp4bis () {
		# ffmpeg -i /point/de/montage/source.MOV -vcodec libx264 /point/de/montage/source.mp4
		DESTINATION="${SOURCE%.*}.mp4"
		# msgbox "DESTINATION=${DESTINATION}"
		ffmpeg -y -i "${SOURCE}" -vcodec "${VCODEC}" "${DESTINATION}" 2> "${TMP_LOG}" &
		wait $!
		return $?
	}
function Mov2Mp4 () {
	journal "**********************
	Mov2Mp4"
	# Transformation d'un mov en mp4
	local unTEST
	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
		Mov2Mp4bis &
	fi
	journal "fin Mov2Mp4"
	}
function Mp42Gifclassique () {
# GIF avec palette de couleur standard
	journal "**********************
	Mp42Gifclassique
	Création d’un GIF animé, méthode «classique»
	A) gif contenant toute la vidéo
	ffmpeg -y -i ${SOURCE} -s ${RESOLUTION} ${DESTINATION}"
	# ffmpeg -y -i "${SOURCE}" -s "${RESOLUTION}" "${DESTINATION}"

	ffmpeg -y -i "${SOURCE}" -s "${RESOLUTION}" "${DESTINATION}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	}
function Mp42Gif2classique () {
	journal "**********************
	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}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	journal "fin Mp42Gif2classique"
	}
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}" 2> "${TMP_LOG}" &
	wait $!
	return $? 
	}
function Mp42Gifplusplus () {
	journal "Mp42Gifplusplus"
	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}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	}
function Mp42Gif2plus () {
	journal "Mp42Gif2plus"
	journal "# étape 1 : génération d’une palette de couleurs"
	journal "ffmpeg -y -ss ${DEBUT} -t ${DUREE} -i ${SOURCE} -vf fps=${FPS},scale=${SCALE}:-1:flags=${FLAGS},palettegen ${PALETTE}"
	ffmpeg -y -ss "${DEBUT}" -t "${DUREE}" -i "${SOURCE}" -vf fps="${FPS}",scale="${SCALE}":-1:flags="${FLAGS}",palettegen "${PALETTE}" 2> "${TMP_LOG}" &
	wait $!
	return $? 
	}
function Mp42Gif2plusplus () {
	journal "Mp42Gif2plusplus"
	journal "# étape 2 : génération du GIF animé «amélioré»"
	ffmpeg -y -ss "${DEBUT}" -t "${DUREE}" -i "${SOURCE}" -i "${PALETTE}" -filter_complex "${FILER_COMPLEX}" "${DESTINATION}" 2> "${TMP_LOG}" &
	wait $!
	return $?
	}

function Mp42Gif2Anonyme68Suite () {
	convert -loop 0 "${DIR_TEMP_FRAME}/${TMP_FFMPEG_PNG}"*.png "${DESTINATION}" 2> "${TMP_LOG}" &

	wait $!
	return $?
	}
function Mp42Gif2Anonyme68 () {
	journal "Mp42Gif2Anonyme68"
	mkdir "${DIR_TEMP_FRAME}"

	# ffmpeg -i "$SOURCE" -vf scale="${SCALE}":-1:flags="${FLAGS}",fps="${FPS}" "${DIR_TEMP_FRAME}"/"${TMP_FFMPEG_PNG}"%03d.png
	ffmpeg -ss "${DEBUT}" -t "${DUREE}" -i "${SOURCE}" -vf scale="${SCALE}":-1:flags="${FLAGS}",fps="${FPS}" "${DIR_TEMP_FRAME}/${TMP_FFMPEG_PNG}"%03d.png 2> "${TMP_LOG}" &

	wait $!
	return $?
	}

# function trouve_ImgsParSec () {
	# local FPS_SOURCE=$(ffmpeg -i "$SOURCE" 2>&1 | grep "Stream" | grep "Video" )
	# FPS_SOURCE="${FPS_SOURCE##*:}"
	# FPS_SOURCE=$(cut -d',' -f5<<<$FPS_SOURCE)
	# FPS_SOURCE="$(cut -d' ' -f1<<<$FPS_SOURCE)"
	# echo "$FPS_SOURCE"
	# }
# function Mp42GifConvert () {
	# #https://forum.ubuntu-fr.org/viewtopic.php?pid=21763320#p21763320
	# #convert mavideo.mp4[600-900] mongif.gif
	# ImgsParSec=$(trouve_ImgsParSec)
	# FIN=$((${DEBUT}+${DUREE}))
	# 
	# leDEBUT="$((${DEBUT}*$ImgsParSec))"
	# laFIN="$((${FIN}*$ImgsParSec))"
	# journal "-------------------------------------------------
	# convert $SOURCE[$leDEBUT-$laFIN] ${DESTINATION}"
# 
# #convert -delay 13 -loop 0 frameTemp.*.gif output.gif
	# #convert "$SOURCE"[100-1500] "${DESTINATION}" 2> "${TMP_LOG}" &
	# #convert "$SOURCE"[${leDEBUT}-${laFIN}] frameTemp.*.gif "${DESTINATION}" 2> "${TMP_LOG}" &
# 
	# ffmpeg -i "$SOURCE" -r 8 frameTemp.%05d.gif
	# convert -delay 13 -loop 0 frameTemp.*.gif "${DESTINATION}" 2> "${TMP_LOG}" &
# 
	# wait $!
	# return $?
	# }

# ---------------------------------------------

# Fonctions à incorporer non appellées
function Mp42Mp3 () {
	#https://forum.ubuntu-fr.org/viewtopic.php?pid=21762613#p21762613
	# for vid in *.mp4; do 
		# ffmpeg -i "$vid" -q:a 0 -map a "${vid%.mp4}.mp3";
	# done
	ffmpeg -i "$SOURCE" -q:a 0 -map a "${SOURCE%.mp4}.mp3";
	}
function optimisationGIF () {
	#gifsicle --optimize=3 image.gif > image-optimisee.gif
	#gifsicle --optimize=3 "${DESTINATION}" > "${DESTINATION##*.}-optimized.gif"
	gifsicle --optimize=3 "${DESTINATION}" > "${DESTINATION%.gif}-optimized.gif"
	}

# ---------------------------------------------

# ETAGE GESTION ZENITY PROGRESS
function calculPourcentage () {
	sed -e 's/\r/\n/g' "${TMP_LOG}" | \
	grep time= | \
	tail -n 1 | \
	sed -e 's/frame/IMAGE/;s/fps/\nFPS/;s/q/\nQUALITEE/;s/size/\nPOID/;s/time/\nTEMPS/;s/bitrate/\nBITRATE/;s/speed/\nSPEED/' | \
	tr -d ' ' > "${TMP_TOUT}"

	. "${TMP_TOUT}"

	IFS=':' leTemps=( $TEMPS )
	ACTU_calculPourcentage=$(bc<<<"(${leTemps[2]}+${leTemps[1]}*60+${leTemps[0]}*3600)*100/$TOTALS")

	grep IMAGE "${TMP_TOUT}" && \
	echo "#ENTRE : $SOURCE\nSORTIE : $DESTINATION\nIMAGE=$IMAGE\nFPS=$FPS\nQUALITEE=$QUALITEE\nPOID=$POID\nTEMPS=$TEMPS s\nBITRATE=$BITRATE\nSPEED=$SPEED" || \
	echo "#ENTRE : $SOURCE\nSORTIE : $DESYINATION\nPOID=$POID\nTEMPS=$TEMPS s\nBITRATE=$BITRATE\nSPEED=$SPEED"
	
	echo ${ACTU_calculPourcentage}
	}
function calculPourcentage2 () {
	echo "50"
	local tout
	# clear
	# date
	# echo "ici : $(ps h --pid $PID)"
	# ps aux | grep -v grep | grep ffmpeg # 1 2 4 5 9
	tout="$(ps aux | grep -v grep | grep ffmpeg)"
	tout=( ${tout} )
	echo "#Création de la palette\n1 : \t${tout[1]}\n2 : \t${tout[2]}\n4 : \t${tout[4]}\n5 : \t${tout[5]}\n9 : \t${tout[9]}"
	sleep 0.5
	}
function calculPourcentage3 () {
	echo "50"
	local tout
	# clear
	# date
	# echo "ici : $(ps h --pid $PID)"
	# ps aux | grep -v grep | grep ffmpeg # 1 2 4 5 9
	tout="$(ps aux | grep -v grep | grep convert)"
	echo "#${tout}"
	# tout=( ${tout} )
	# echo "#1 : ${tout[1]}\n2 : ${tout[2]}\n4 : ${tout[4]}\n5 : ${tout[5]}\n9 : ${tout[9]}"
	sleep 0.5
	}
function lanceurEncodage () {
	DECOMPTE=$(ffmpeg -i "$SOURCE" 2>&1 | grep Duration | awk '{ print $DESTINATION }' | tr ':.,' ' ')
	DECOMPTEH=$(cut -d' ' -f2<<<$DECOMPTE)
	DECOMPTEM=$(cut -d' ' -f3<<<$DECOMPTE)
	DECOMPTES=$(cut -d' ' -f4<<<$DECOMPTE)
	TOTALS=$(bc<<<"$DECOMPTES+$DECOMPTEM*60+$DECOMPTEH*3600")

	TOTALS2=$(bc<<<"$DUREE-$DEBUT") # temps de la partie choisie pour être convertie

	# echo "DECOMPTE=$DECOMPTE"
	# echo "DECOMPTEH=$DECOMPTEH"
	# echo "DECOMPTEM=$DECOMPTEM"
	# echo "TOTALS=$TOTALS"
	# echo "TOTALS2=$TOTALS2"

	estPalette=false

	case $1 in
		# x)		;;
		0)
			Mov2Mp4 &
			PID=$!
			;;
		1)
			Mp42Gifclassique &
			PID=$!
			;;
		2)
			Mp42Gif2classique &
			PID=$!
			;;
		3)
			TOTALS="${TOTALS2}"
			estPalette=true
			Mp42Gifplus &
			PID=$!
			;;
		4)
			TOTALS="${TOTALS2}"
			Mp42Gifplusplus &
			PID=$!
			;;
		5)
			TOTALS="${TOTALS2}"
			estPalette=true
			Mp42Gif2plus &
			PID=$!
			;;
		6)
			TOTALS="${TOTALS2}"
			Mp42Gif2plusplus &
			PID=$!
			;;
		7)
			TOTALS="${TOTALS2}"
			Mp42Gif2Anonyme68 &
			PID=$!
			;;
		8)
			TOTALS="${TOTALS2}"
			Mp42Gif2Anonyme68Suite &
			PID=$!
			;;
		# 9)
			# TOTALS="${TOTALS2}"
			# Mp42GifConvert &
			# PID=$!
			# ;;

		*)	exit 112 ;; # pouquoi pas 112 ? :°)
	esac

	sleep .5 # TODO ; certainement inutile

	while [[ $(pidof ffmpeg) ]]
	do
		sleep .2 # TODO ; certainement UTILE 
		# if $estPalette
		# then
			# calculPourcentage2
		# else
			# calculPourcentage
		# fi
		case $1 in
		# 1) ;;
		# 2) ;;
		3) calculPourcentage2 ;;
		# 4) ;;
		5) calculPourcentage2 ;;
		# 6) ;;
		7) calculPourcentage2 ;;
		# 8) ;;
		9) calculPourcentage3 ;;

		# ) ;;
		*) calculPourcentage ;;
		esac
	done | zenity --progress --auto-close --title="${txtTITLE}"

	sleep 1 # TODO ; certainement inutile

	if [[ "${PIPESTATUS[0]}" != "0" ]]
	then
		kill $(pidof ffmpeg)
		# kill $(pidof convert)
	fi

	wait $PID
	SORTIE=$?

	if [[ "$SORTIE" = "0" ]]
	then
		if $estPalette
		then
			zenity --info --title="${txtTITLE}" --text="création de la palette terminé !" --timeout=2
		else
			zenity --info --title="${txtTITLE}" --text="Encodage terminé !" --timeout=2
			# DEBUG
			# zenity --text-info --filename="${TMP_LOG}" --title="${txtTITLE}" --width=800 --height=600
		fi
	else
		zenity --error --title="${txtTITLE}" --text="Encodage interrompu !" --timeout=2
		zenity --text-info --filename="${TMP_LOG}" --title="${txtTITLE}" --width=800 --height=600
	fi

	journal "fin encodage"

	# exit $SORTIE # TODO : return $SORTIE ?
	}

# ---------------------------------------------

# DEBUGGAGE
function voirLesVariables () {
msgbox "$(CreerLignesOptions)"
}

# ---------------------------------------------

# ETAGE MAIN
function _main () {
journal "_main"	
	menuchoice=$(frm_principale);
	frm_principale_parser ${menuchoice%|*} # pour corriger le 1|1

	if [ ${QUITTER} -eq 0 ] ; then
		# on boucle _main tant que quitter est différent de 1
		_main
	fi
	}
function main () {
	#-initialisation
	_INITIALISATION_DEFAUT
	chargerFichierIni ;
	QUITTER=0
	# voirLesVariables
	_main
	}

# ---------------------------------------------

# ETAGE Aide
function AfficherAide () {
# $FONCTION
echo "Convertir des vidéos ou parties vidéos mov et mp4 en gif
-------------------------------------------------------
ce script est issu d'une discussion sur Dolys
https://dolys.fr/forums/topic/creer-des-gifs-animes-de-qualite-a-partir-dune-video

-------------------------------------------------------
DEPENDANCES : $listDEPENDANCES

-------------------------------------------------------
Installation pour un utilisateur :
créer un dossier bin personnel :
mkdir ${HOME}/bin
y mettre le script
> ${HOME}/bin/vid2gif
le rendre exécutable
chmod +x ${HOME}/bin/vid2gif
éditer et coller le script suivant avec gedit (ou nano ou vi, vim, leafpad,...)
gedit ${HOME}/bin/vid2gif

Attention
si vous avez dû créer le dossier bin car il n'existait pas, 
mkdir ${HOME}/bin 
n'a pas renvoyé d'erreur (puisque le dossier n'existait pas !)
il faudra relancer l'utilisateur pour que ce dossier bin soit ajouté au PATH automatiquement
... dans le doute déconnectez puis reconnectez votre session

-------------------------------------------------------
Pour lancer le script 
dans un terminal
vid2gif

TODO en GUI :
il faut créer un lanceur ou un lien.

-------------------------------------------------------
Pour utiliser le tableau zenity
pour modifier une des valeurs du tableau, double cliquez sur la ligne à modifier
choisissez une valeur et valider... ou annuler pour récupérer la valeur précédente.

Choisissez un fichier mov et une destination gif
lancez l'option Mov2Mp4
ou
Choisissez un mp4 et choisissez une des options Mp42Gifclassique, Mp42Gif2classique ou Mp42Gifplus

NB pour faire des tests et comparer des options, pensez à changer le nom du fichier DESTINATION (le gif)
TODO :
zenity demande en cas d'écrasement d'un fichier, c'est à supprimer et à ajouter en fonction dans le script.
" | zenity --width=800 --height=600 --text-info="${@}"
	}

# ---------------------------------------------

# lanceur principale
main

exit 0

Hors ligne

#24 Le 19/07/2017, à 15:38

jlfh0816

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

@kholo
Merci pour cette nouvelle version, tu fais un super travail.
Je ne peux pas t'aider pour coder alors j'essaie de te renvoyer l'ascenseur en testant et en postant le résultat. C'est toujours ça, mais vraiment désolé de ne pas pouvoir faire plus ... roll

Pour cette nouvelle série de tests, je suis parti d'un nouveau fichier mp4 faisant 10,4 Mo et durant 27 secondes.

Avec la fonction Mp42gifsimple, j'arrive à un gif animé de 14,8 Mo d'une durée de 27 secondes.
Avec la fonction Mp42gifsimple DEBUT/DUREE, j'arrive à un gif animé de 2,5 Mo d'une durée de 5 secondes.
Avec la fonction Mp42gifpalette, j'arrive à un gif animé de 11,6 Mo d'une durée de 27 secondes.
Avec la fonction Mp42gifpalette DEBUT/DUREE, j'arrive à un gif animé de 2,1 Mo d'une durée de 5 secondes.
Avec la fonction Mp42gifAnonyme68 DEBUT/DUREE, j'arrive à un gif animé de 2,2 Mo d'une durée de 5 secondes.

Par contre (j'ai sans doute raté un épisode ...), je n'ai pas trouvé comment entrer les valeurs DEBUT et DUREE lorsque je clique sur le tableau Zenity ?
Je pense que, par défaut, la DUREE est fixée à 5 secondes et le DEBUT à 0, est-ce exact ?
Comment l'utilisateur lambda doit-il faire pour les modifier dans le tableau Zenity ?

Merci mille fois de ton travail kholo !

Dernière modification par jlfh0816 (Le 19/07/2017, à 18:08)


Xubuntu - Voyager 14.04.5 LTS (64 bits) et Xubuntu - Voyager 16.04.01 LTS (64 bits)

Hors ligne

#25 Le 19/07/2017, à 17:29

kholo

Re : [TUTO] script bash conversion vidéos mov et mp4 vers gif

dans le tableau zenity un double clic sur une ligne pour la lancer ou clic sur la ligne puis bouton "Sélectionner"

ligne options modifier pour modifier les options, ça doit ouvrir une autre fenêtre list zenity avec les valeurs des options.
si ça ne marche pas chez toi fais le moi savoir... mais je pense pas !

dans les options
attention "ouvrir" et "enregistrer les options" n'est pas fonctionnel... (ouvre juste une zenity)
... en fait ouvrir fonctionne mais il faut mettre les patterns à la main dans le bon dossier

Le comportement par défaut oblige à repasser par la fenêtre principale quand on change une valeur, je vais revoir ça
... mais c'est fonctionnel !

NB j'ai laissé la création d'un dossier dans le dossier personnel de config : ~/.config/kholo
qu'il faudra aussi géré à la main (suppression éventuelle)

Hors ligne