Linux : Créer un gif de bonne qualité à partir d’une vidéo en ligne de commande grâce à ffmpeg

Partager cet article

Temps estimé pour la lecture de cet article : 45 min

Introduction

linux-videotogif-minions

Que ce soit pour égailler nos fils d’actualités twitter ou pour imager une situation le gif est revenu à la mode. Personnellement, je m’en sers peu mais j’ai eu récemment besoin d’utiliser le format afin de montrer une animation android en action. Oui, mais voila comment en partant d’une vidéo puis-je créer un gif rapidement ? La solution que je vous propose ici est en ligne de commande et tout ça grâce à la librarie ffmpeg.

Le format GIF

Le GIF ou Graphics Interchange Format est un format d’image numérique couramment utilisé sur le web. Il a été mis au point par CompuServe en 1987. Ce format utilise l’algorithme de compression sans perte LZW. Le format GIF est limité à 256 couleurs, toutefois il supporte la transparence et surtout permet de réaliser des animations répétables en utilisant une suite d’images.

Il existe de très nombreux sites qui propose un ensemble de gifs prêts à être utilisé :

Initiation à la librarie ffmpeg

linux-videotogif-ffmpeg

FFmpeg est une application qui va vous permettre de réaliser des traitements de flux audio ou vidéo. D’une simple conversion de vidéos, en passant par une extraction de bande son d’une vidéo, c’est grâce à cet outil que nous allons pouvoir créer des gifs facilement ! Ce projet a été créé par Fabrice Bellard en 2000, et est maintenant maintenu par Michael Niedermayer.

Avant de vous montrer, le script que nous allons utiliser, je vais vous montrer quelques possibilitées de ffmpeg.

Obtenir des informations sur une vidéo

Commencons par une commande assez simple et classique qui va nous permettre d’obtenir des informations détaillées sur une vidéo.

ffmpeg -i Sintel.2010.1080p.mkv

Ce qui nous retourne ceci :

Input #0, matroska,webm, from 'Sintel.2010.1080p.mkv':
  Metadata:
    encoder         : libebml v1.0.0 + libmatroska v1.0.0
    creation_time   : 2011-04-25 12:57:46
  Duration: 00:14:48.03, start: 0.000000, bitrate: 10562 kb/s
    Chapter #0:0: start 0.000000, end 103.125000
    Metadata:
      title           : Chapter 01
    Chapter #0:1: start 103.125000, end 148.667000
    Metadata:
      title           : Chapter 02
    Chapter #0:2: start 148.667000, end 349.792000
    Metadata:
      title           : Chapter 03
    Chapter #0:3: start 349.792000, end 437.208000
    Metadata:
      title           : Chapter 04
    Chapter #0:4: start 437.208000, end 472.075000
    Metadata:
      title           : Chapter 05
    Chapter #0:5: start 472.075000, end 678.833000
    Metadata:
      title           : Chapter 06
    Chapter #0:6: start 678.833000, end 744.083000
    Metadata:
      title           : Chapter 07
    Chapter #0:7: start 744.083000, end 888.032000
    Metadata:
      title           : Chapter 08
    Stream #0:0(eng): Video: h264 (High), yuv420p(tv, bt709/unknown/unknown), 1920x818, SAR 1:1 DAR 960:409, 24 fps, 24 tbr, 1k tbn, 48 tbc
    Stream #0:1(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 640 kb/s
    Metadata:
      title           : AC3 5.1 @ 640 Kbps
    Stream #0:2(ger): Subtitle: subrip
    Stream #0:3(eng): Subtitle: subrip
    Stream #0:4(spa): Subtitle: subrip
    Stream #0:5(fre): Subtitle: subrip
    Stream #0:6(ita): Subtitle: subrip
    Stream #0:7(dut): Subtitle: subrip
    Stream #0:8(pol): Subtitle: subrip
    Stream #0:9(por): Subtitle: subrip
    Stream #0:10(rus): Subtitle: subrip
    Stream #0:11(vie): Subtitle: subrip

Si on observe le résultat obtenu, voilà ce qu’on peut récupérer :

  • L’input 0 décrit le format du fichier : Matroska ici.
  • On a la durée de la vidéo ainsi que son bitrate (quantité de données numériques transmises par unité de temps)
  • Le nombre de chapitres dont est composé notre vidéo (cette partie est optionnelle elle dépendra du flux vidéo observé)
  • Le premier flux (stream), correspond au flux vidéo en lui-même, on retrouve sa taille, l’espace de couleur utilisé (ici yuv420), le framerate et j’en passe
  • Le second stream, correspond à l’audio sur certaines vidéos de grosse qualité, il est possible d’en retrouver plusieurs, on y retrouve la langue utilisée et le framerate
  • Enfin, les derniers streams sont des sous-titres, ici on voit qu’on en a une bonne dizaine

Extraire le son d’une vidéo pour en faire un MP3

linux-videtogif-audio

Il est possible d’extraire du son d’une vidéo, pratique quand vous voulez récupérer la musique d’un clip par exemple. D’ailleurs, youtube-dl utilise ffmpeg dans ce but, vous pouvez retrouver une courte introduction à cet outil dans mon article sur le DDL.

ffmpeg -i video.avi -vn -ar 44100 -ac 2 -ab 256k -f mp3 sound.mp3

Regardons ensemble les différents paramètres :

  • -i video.avi: c’est tout simplement le fichier source, c’est-à-dire dans notre cas précis notre vidéo
  • -vn: signifie tout simplement « no video »
  • -ar 44100: correspond à la fréquence audio de l’échantillon que l’on veut obtenir.
  • -ac 2: le nombre de canaux audio (1=mono, 2=stereo)
  • -ab 256k: le bitrate du fichier de sortie, ici 256 kb/s (par défaut c’est 128)
  • -f mp3: le format du fichier de sortie
  • sound.mp3: le nom du fichier de sortie

Remarque: Petite aparté d’ailleurs, savez-vous pourquoi un fichier audio a une fréquence de 44100 Hz ? Une fréquence de 11 kHz se révèle suffisante pour l’enregistrement de la parole, mais elle ne convient pas pour de la musique. La haute fidélité propose de restituer les fréquences inférieures à 22 kHz. C’est en effet la limite de l’audible pour l’oreille humaine. Par ailleurs, l’échantillonage provoque une perte d’information et Shannon a démontré que la fréquence d’échantillonnage doit être supérieur à 2 fois la fréquence maximale utile. Pour compresser de la musique en haute fidélité, il faut donc, échantilloner à une fréquence de 44kHz (44100).

Incruster des sous-titres à une vidéo

linux-videotogif-langues

Si vous regardez quelques séries et que vous êtres un grand fan de VO, vous devez être familier avec les fichiers .srt, qui permettent de décrire l’ensemble des répliques des acteurs dans le film. FFmpeg va nous permettre d’incruster directement les sous-titres dans la vidéo, cela va ainsi vous permettre de créer une vidéo avec l’ensemble des sous-titres que vous désirez, cela peut être pratique si vous voulez pratiquer une langue étrangère :)

ffmpeg -i movie.mp4 -i subtitles.srt -map 0 -map 1 -c copy -c:v libx264 -crf 23 -preset veryfast output.mkv

L’option preset permet de proposer un ensemble d’options afin d’adapter l’encodage de la vidéo désirée. Ainsi, un preset assez lent va permettre d’obtenir une meilleure compression. Voici les différents preset classés par ordre de vitesse décroissant : ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo. Le preset par défaut est medium.

Si vous voulez donc un encodage rapide, il vaut mieux utiliser : -preset ultrafast à l’inverse si vous voulez favoriser la compression, il vaut mieux utiliser : -preset veryslow.

Capturer l’écran de son bureau

linux-videotogif-rec

Cette solution vient de l’article de ffmpeg proposé par linuxtricks. Elle va vous de réaliser une capture vidéo de l’écran de votre ordinateur, pratique pour de futurs youtubers ou pour aider un ami avec un tutoriel vidéo.

Tout d’abord, pour obtenir une capture sans son :

ffmpeg -f x11grab -r 30 -s 1920x1080 -i :0.0 -vcodec libx264 out.mkv
  • -r 30 : correspond au nombre de FPS désirés
  • -s 1920×1080 : doit correspondre à la résolution de votre écran

Si vous voulez, en plus enregistrer le microphone en HD, voici la commande a utiliser:

ffmpeg -f alsa -ac 2 -i pulse -f x11grab -r 30 -s  1920x1080 -i :0.0 -acodec pcm_s16le -vcodec libx264 bureau.mkv

Et enfin, voici une commande plus spécifique optimisée pour enregistrer des captures de jeux:

 ffmpeg -threads 0 -async 30 -f alsa -i pulse -f x11grab -s 1920x1080 -r 30 -i :0 -vcodec libx264 -preset superfast -crf 16 -acodec libmp3lame -f mp4 video.mp4

Notre script final : videoToGif

Passons maintenant dans le vif du sujet, il est possible de réaliser un gif assez simplement, grâce à la commande suivante :

ffmpeg -ss 00:03:06 -t 10 -i input.avi -vf scale=500:-1 output.gif

Regardons les différents paramètres :

  • -ss : c’est la position de départ du gif
  • -t : la durée totale du gif
  • -vf scale=500:-1 : permet de modifier la taille des images obtenues

Si, on exécute la commande telle quel, voici ce qu’on obtient :

linux-videotogif-brucebad

Mais, on peut largement améliorer la qualité du gif obtenu, le script final est très fortement inspiré de cet article, je vous conseille de le lire si vous voulez comprendre en détail la technique utilisée, pour ma part, je vais juste la résumé très brièvement.

Comme on l’a vu dans le début de l’article le format GIF est limité à une palette de 256 couleurs. Par défaut, ffmpeg va utiliser cette palette. La première étape afin d’améliorer la qualité du GIF sera donc de définir une meilleure palette de couleurs. C’est ce que permet le filtre palettegen, il va réaliser un histogramme de toutes les couleurs présente dans chaque frame et créé une palette basée là-dessus. Le second filtre que l’on va utiliser se nomme paletteuse, grâce à lui on va pouvoir utiliser la palette réalisée précédemment et le filtre va se charger de trouver la couleur la plus proche dans la palette de la couleur d’entrée. Plusieurs options sont disponibles pour chaque filtre, je vous laisse consulter l’article précédent ou même la documentation pour adapter le script à vos besoins !

function videoToGif() {
    name=$(basename "$1")
    name="${name%.*}.gif"

	start_time=$2
	duration=$3

	palette="/tmp/palette.png"
	if [ $# -eq 4 ]; then
		filters="fps=$4,scale=500:-1:flags=lanczos"
	elif [ $# -eq 5 ]; then
		filters="fps=$4,scale=$5:-1:flags=lanczos"
	else 
		filters="fps=15,scale=500:-1:flags=lanczos"
	fi
	
	ffmpeg -v warning -ss $start_time -t $duration -i "$1" -vf "$filters,palettegen" -y $palette
	ffmpeg -v warning -ss $start_time -t $duration -i "$1" -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse=dither=sierra2" -y $name
}

Analysons maintenant un peu le script, rien de bien compliqué, on utilise la fonction basename pour récupérer le nom du fichier sans l’extension et ainsi nommer notre gif en fonction du nom de la vidéo fourni en entrée. On récupère dans les variables start_time et duration les arguments correspondants. On crée une variable palette qui contiendra donc notre palette globale, on précise le chemin dans le dossier temporaire /tmp (dossier qui permet de stocker des fichiers temporaires, il ne faut pas s’attendre à retrouver le fichier par la suite. En effet ce répertoire peut être purgé n’importe quand. Dans la vaste majorité des distributions, ce répertoire est nettoyé à chaque redémarrage). Ensuite, on vérifie si on a précisé d’autres paramètres, si c’est le cas, on les fait correspondre à la variable souhaitée et enfin, on lance deux commandes la première, pour extraire la palette de couleurs globales et la seconde pour réaliser le gif.

Maintenant qu’on a notre script, regardons comment l’utiliser et à quoi correspondent les paramètres :

videoToGif bruce_tout_puissant.mkv 01:01:53 6 10 600
  • Le premier argument, c’est tout simplement la vidéo source
  • Le second, c’est la position dans la vidéo à laquelle doit commencer le gif
  • Le troisième, c’est la durée du gif
  • Le quatrième argument qui est optionnel, c’est le nombre d’images par seconde (les FPS), en général 15 suffit, mais en baissant vous pouvez diminuer la taille du gif obtenu
  • Enfin, le dernier argument également optionnel, c’est la largeur du gif final obtenu, plus elle sera grande plus le gif sera lourd

Et tadddaaa !!! Voilà, enfin le résultat final obtenu grâce à notre script :

linux-videotogif-brucegood

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *