Je veux faire une animation .gif
d'un .mp4
vidéo. Je préférerais le faire à partir de la ligne de commande, donc veuillez ne citer que des outils en ligne de commande.
Réponses
Trop de publicités?ffmpeg
3.4.4 peut le faire directement sur Ubuntu 18.04
Vous voudrez probablement utiliser quelque chose comme :
sudo apt install ffmpeg
wget -O opengl-rotating-triangle.mp4 https://github.com/cirosantilli/media/blob/master/opengl-rotating-triangle.mp4?raw=true
ffmpeg \
-i opengl-rotating-triangle.mp4 \
-r 15 \
-vf scale=512:-1 \
-ss 00:00:03 -to 00:00:06 \
opengl-rotating-triangle.gif
opengl-triangle rotatif.gif
Infos sur l'image : 426kB, 45 images, 512x512 taille apparente, coalescé Temps de conversion sur un Lenovo P51 : 0.5s.
La conversion ci-dessus a également fonctionné après une ulimit -Sv 1000000
(utilisation de la DRAM limitée à 1GB), donc il ne "consomme pas d'énormes quantités de mémoire" comme les tentatives précédentes que j'ai faites avec Imagemagick qui ont presque tué ma machine. 500MB a cependant échoué parce que ffmpeg n'a pas réussi à charger ses bibliothèques partagées... il est temps d'améliorer votre RAM ;-) ?
Procédure de génération des données d'essai décrite sur ce post .
La sortie a un motif de pointillés visible, qui n'est pas aussi visible dans la méthode "ffmpeg + convert" ci-dessous. Nous pouvons essayer d'améliorer la qualité de l'image avec les méthodes décrites à :
- https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality
- https://stackoverflow.com/questions/42980663/ffmpeg-high-quality-animated-gif
Par exemple, en utilisant le palettegen
filtre :
ffmpeg \
-i opengl-rotating-triangle.mp4 \
-r 15 \
-vf "scale=512:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
-ss 00:00:03 -to 00:00:06 \
opengl-rotating-triangle-palettegen.gif
opengl-rotating-triangle-palettegen.gif
Infos sur l'image : 979K, 45 images, 512x512 taille apparente, coalescé Temps de conversion sur un Lenovo P51 : 3.5s.
C'est ce que nous voyons :
- le motif en pointillé est beaucoup moins visible maintenant
- La taille du GIF a grossièrement doublé. TODO : pourquoi le simple fait de choisir une palette augmente-t-il la taille de l'image ? Est-ce parce qu'il y a maintenant plus de couleurs et que nous avons besoin de plus de bits par couleur ? Comment observer chaque palette ?
- Le temps de génération était 7x plus lent, probablement parce que ffmpeg scanne d'abord toute la vidéo pour déterminer une palette optimale.
Nous pourrions également jouer avec des documents palettegen
des paramètres comme palettegen=max_colors=16
pour atteindre différents points de compromis entre la taille et la qualité.
Analyse de l'argumentation
-
-ss 00:00:03 -to 00:00:06
: heure de début et de fin pour couper la vidéo.Non, les GIFs ne sont pas le meilleur moyen de
piratedistribuer des vidéos en ligne.Voir aussi : https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg
-
-vf scale=512:-1
: faire la sortie512
pixels en hauteur, et ajuster la largeur pour maintenir le ratio d'aspect.Il s'agit d'un cas d'utilisation courant pour les images destinées au web, qui ont généralement une résolution beaucoup plus faible que les vidéos.
Si vous supprimez cette option, le GIF de sortie a la même hauteur que la vidéo d'entrée.
La hauteur de la vidéo originale peut être trouvée par exemple avec
ffprobe
: https://superuser.com/questions/595177/how-to-retrieve-video-file-information-from-command-line-under-linux/1035178#1035178 et est de 1024 x 1024 dans notre cas. -
-r 15
: échantillonnage FPS.Par exemple, la vidéo originale était de 30 FPS, donc
-r 15
signifie queffmpeg
choisira un cadre sur 2 (= 30 / 15
).Le nombre d'images par seconde perçu en sortie est cependant ajusté pour correspondre à l'entrée, vous ne remarquerez donc pas d'accélération, mais seulement une plus grande granularité.
Le FPS d'entrée peut être trouvé avec
ffprobe
et le nombre total de trames d'entrée peut être trouvé avecmediainfo
comme expliqué à : https://superuser.com/questions/84631/how-do-i-get-the-number-of-frames-in-a-video-on-the-linux-command-line/1044894#1044894Je recommande cette option car les formats vidéo ont généralement un taux de rafraîchissement plus élevé en raison de la plus grande résolution. Avec des GIFs plus petits, le taux de rafraîchissement est moins perceptible, et nous pouvons donc sauter certaines images et faire des GIFs plus petits.
Exemple de séquence de caméra vidéo
Si vous voulez voir la qualité du résultat d'une caméra vidéo de Wikimedia Commons avec une commande similaire :
wget https://upload.wikimedia.org/wikipedia/commons/f/f9/STS-132_Liftoff_Space_Shuttle_Atlantis.ogv
ffmpeg -i STS-132_Liftoff_Space_Shuttle_Atlantis.ogv -r 15 -vf scale=512:-1 \
-ss 00:00:17 -to 00:00:22 STS-132_Liftoff_Space_Shuttle_Atlantis.gif
STS-132_Liftoff_Shuttle_Shuttle_Atlantis.gif
Infos sur l'image : 1.3MB, 75 images, taille apparente 512x288, coalescé (a un effet minime cependant, car le métrage est légèrement panoramique depuis le début), temps de conversion sur un Lenovo P51 : 2.3s.
Voici une version avec palettegen
mais seulement 2 secondes pour respecter la limite de téléchargement de 2MiB :
Infos sur l'image : 1.5MB, 30 images, taille apparente 512x288, temps de conversion sur un Lenovo P51 : 43s.
Un plus direct :
sudo apt-get install ffmpeg
ffmpeg -i in.mp4 out.gif
fonctionne également, mais le GIF de sortie serait beaucoup plus volumineux que la vidéo d'entrée, car les formats vidéo peuvent être compressés plus efficacement entre les trames grâce à des algorithmes avancés, alors que le GIF ne peut faire que de la un simple cadre rectangulaire diff .
Avant 18.04 : ffmpeg
+ convert
one-liner sans fichiers intermédiaires
ffmpeg
ne pouvait pas gérer le GIF auparavant. Le meilleur que j'ai eu était quelque chose comme :
sudo apt-get install ffmpeg imagemagick
ffmpeg -i opengl-rotating-triangle.mp4 -r 15 -vf scale=512:-1 \
-ss 00:00:03 -to 00:00:06 -f image2pipe -vcodec ppm - |
convert -deconstruct -delay 5 -loop 0 - opengl-rotating-triangle-image-magick.gif
opengl-rotating-triangle-image-magick.gif
Infos sur l'image : 995kB, 45 images, taille apparente 512x512, coalescé.
Pour les images de la navette Atlantis, et analogues :
ffmpeg -i STS-132_Liftoff_Space_Shuttle_Atlantis.ogv -r 15 -vf scale=512:-1 \
-ss 00:00:17 -to 00:00:22 -f image2pipe -vcodec ppm - |
convert -deconstruct -delay 5 -loop 0 - STS-132_Liftoff_Space_Shuttle_Atlantis_512x.gif
a donné un meilleur résultat, mais le GIF final était considérablement plus gros (6,2 Mo), et je ne peux donc pas le télécharger.
Explication de certains des arguments :
-
-loop 0
: ajouter le champ "Loop count" de l'extension Netscape Gif à la sortie. 0 signifie une boucle infinie comme décrit à : http://www.vurdalakov.net/misc/gif/netscape-looping-application-extensioneog
,firefox
et chrome bouclent tous infiniment par défaut même sans lui, donc je ne suis pas sûr qu'il soit encore nécessaire. -
-delay 5
: temps d'attente avant l'affichage de l'image suivante, en centièmes de seconde, comme décrit dans le site : https://en.wikipedia.org/wiki/GIF#Animated_GIF octet 324. Donc100
signifie 1 FPS,5
signifie1 / 0.5 == 20FPS
. -
-deconstruct
: compresser à travers les images avec des différences rectangulaires, voir aussi : comment puis-je redimensionner un fichier GIF animé en utilisant ImageMagick ?
Même si vous réduisez la hauteur et la fréquence d'images, le GIF de sortie peut toujours être plus grand que la vidéo, car les "vrais" formats vidéo non GIF compriment les images entre elles, tandis que le GIF comprime uniquement les images individuelles.
Un direct :
convert input.mp4 rpi2-bare-metal-blink.gif
a fonctionné, mais a presque tué mon ordinateur à cause d'un dépassement de mémoire, et a produit un résultat 100x plus grand pour mon fichier d'entrée de 2s 1Mb. Peut-être qu'un jour ImageMagick rattrapera son retard.
Voir aussi : https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality
Testé sur Ubuntu 17.10.
Gifski
C'est une autre option qui a été portée à mon attention et qui revendique des algorithmes intelligents, alors essayons-la.
Nous devons d'abord convertir la vidéo en une séquence d'images, puis l'introduire dans gifsky, par exemple :
sudo snap install gifski
mkdir -p frames
ffmpeg \
-i opengl-rotating-triangle.mp4 \
-r 15 \
-vf scale=512:-1 \
-ss 00:00:03 -to 00:00:06 \
frames/%04d.png
gifski -o opengl-rotating-triangle-gifski.gif frames/*.png
opengl-triangle rotatif-gifski.gif
Infos sur l'image : 954K, 45 images, taille apparente 512x512, non coalescé, temps de conversion sur un Lenovo P51 : 4.8s.
Et la STS 2s :
Infos sur l'image : 1.6M, 30 images, taille apparente 512x288, non coalescé, temps de conversion sur un Lenovo P51 : 2.8s.
Donc pour moi, subjectivement, cela n'a pas semblé offrir d'avantage significatif par rapport à ffmpeg. palettegen
.
Deux étapes :
-
Extraire des images d'une vidéo
Créez un répertoire appelé frames dans le même répertoire que votre
.mp4
fichier. Utilisez la commande :ffmpeg -i video.mp4 -r 5 'frames/frame-%03d.jpg' -r 5 stands for FPS value for better quality choose bigger number adjust the value with the -delay in 2nd step to keep the same animation speed %03d gives sequential filename number in decimal form
-
cd frames convert -delay 20 -loop 0 *.jpg myimage.gif -delay 20 means the time between each frame is 0.2 seconds which match 5 fps above. When choosing this value 1 = 100 fps 2 = 50 fps 4 = 25 fps 5 = 20 fps 10 = 10 fps 20 = 5 fps 25 = 4 fps 50 = 2 fps 100 = 1 fps in general 100/delay = fps -loop 0 means repeat forever
Docs : options de conversion gif
Vous vous retrouverez avec un fichier assez volumineux. guide de la magie des images pour optimiser les gif sur les options que vous pouvez ajouter à la commande de la deuxième étape pour obtenir un fichier plus petit.
gififier est un utilitaire tout-en-un basé sur les nœuds qui simplifie la conversion. Il dépend de nodejs
, npm
, ffmpeg
y imagemagick
qui sont tous disponibles dans les dépôts.
Une fois que vous avez npm
installé, vous pouvez installer gifify
globalement avec :
npm install -g gifify
Une vidéo peut être convertie en un fichier .GIF avec :
gifify video.mp4 -o video.gif
Vous pouvez également définir une position de début et de fin dans la vidéo et ajouter une légende :
gifify clip.mp4 -o clip.gif --from 01:48:23.200 --to 01:48:25.300 --text 'we are the knights who say nip!'
La conversion peut prendre plusieurs minutes, même pour les petites vidéos.
NOTE :
ffmpeg
yimagemagick
peut avoir besoin d'être compilé avec certaines bibliothèques spécifiques (par exemple libass et fontconfig en conséquence).
J'ai commencé à mettre en place un outil afin de fournir une interface simplifiée pour les actions courantes.
Vous pouvez convertir un MP4 en GIF comme suit :
$ npm install @mountbuild/mouse -g
$ mouse convert input.mp4 -o output.gif -s 00:00:00 -e 00:00:03
Vous pouvez modifier l'heure de début et de fin, ainsi que l'heure d'arrivée. --fps
y --width
également.
Il nécessite l'installation de ffmpeg.
Si vous n'avez rien d'autre à faire, consultez la source et voyez comment écrire votre propre script pour faire cela en JavaScript.