30 i/s N’Existe Pas en GIF
Demandez 30 images par seconde à n’importe quel encodeur GIF et il dira oui. Il ment, et la raison se trouve à quatre octets de profondeur dans le format : le délai d’une image de GIF est un nombre entier de centièmes de seconde, et 100/30 n’est pas un nombre entier.
Chaque image d’un GIF porte son propre délai, stocké dans un bloc Graphic Control Extension qui ressemble à ceci :
0x21 0xF9 0x04 <packed> <delay lo> <delay hi> <transparent> 0x00
Les deux octets de délai forment un entier 16 bits en little-endian, et son unité est le centième de seconde. Pas la milliseconde. Pas un nombre rationnel. Un compte entier de centièmes, de 0 à 65 535.
Ce seul fait fixe l’ensemble complet des cadences qu’un GIF peut exprimer. Si le délai doit être un entier n, la cadence doit être 100/n :
100, 50, 33,33, 25, 20, 16,67, 14,29, 12,5, 11,11, 10, 9,09, 8,33, 7,69,
7,14, 6,67, 6,25, 5,88, 5,56, 5,26, 5,00 …
Trente n’y figure pas. Ni 60, ni 24, ni 15 — trois des quatre cadences auxquelles la vidéo est tournée.
Ce qu’un encodeur fait vraiment de votre 30
Il calcule 100/30 = 3,33 centièmes, constate qu’il ne peut pas le stocker, et arrondit à 3. Votre GIF tourne désormais à 33,33 i/s, 11,11 % trop vite. L’erreur n’est pas le plus intéressant ; la durée, si :
| Vous demandez | Délai stocké | Joue à | Erreur | Dix secondes deviennent |
|---|---|---|---|---|
| 60 i/s | 2 cs | 50,00 i/s | −16,67 % | 12,00 s |
| 50 i/s | 2 cs | 50,00 i/s | exact | 10,00 s |
| 30 i/s | 3 cs | 33,33 i/s | +11,11 % | 9,00 s |
| 25 i/s | 4 cs | 25,00 i/s | exact | 10,00 s |
| 24 i/s | 4 cs | 25,00 i/s | +4,17 % | 9,60 s |
| 20 i/s | 5 cs | 20,00 i/s | exact | 10,00 s |
| 15 i/s | 7 cs | 14,29 i/s | −4,76 % | 10,50 s |
| 12 i/s | 8 cs | 12,50 i/s | +4,17 % | 9,60 s |
| 10 i/s | 10 cs | 10,00 i/s | exact | 10,00 s |
| 8 i/s | 13 cs | 7,69 i/s | −3,85 % | 10,40 s |
| 5 i/s | 20 cs | 5,00 i/s | exact | 10,00 s |
Dix secondes de vidéo capturées à 30 i/s, cela fait 300 images. À 3 centièmes chacune, cela fait 900 centièmes — neuf secondes. Le GIF se termine une seconde entière avant le plan dont il est issu. Demandez 60 et il s’allonge dans l’autre sens : 600 images à 2 cs font 12,00 secondes.
Parmi les cadences que l’on demande réellement, seules 50, 25, 20, 10 et 5 reviennent exactes. Tout le reste dérive, et dérive d’un pourcentage fixe qui grandit avec la durée du plan. Montez un GIF sur une musique et voilà l’explication entière du décalage progressif de la boucle.
Les encodeurs le masquent en alternant deux délais
C’est ici que l’on quitte l’arithmétique pour quelque chose que vous pouvez lire dans un fichier de votre disque. Un bon encodeur n’arrondit pas toutes les images de la même façon — il alterne, pour que la moyenne tombe juste.
Nous avons pris un GIF produit par ffmpeg, nominalement à 12 i/s, et parcouru ses blocs pour lire le délai de chaque image :
8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8
Vingt-quatre images. 200 centièmes. Exactement 2,00 secondes, soit exactement 12,0000 images par seconde en moyenne. La moyenne est parfaite — et aucune image du fichier n’est à 12 i/s. Les images consécutives sont espacées de 80 ms puis 90 ms, un écart de 12,5 % entre voisines qui ne se résorbe jamais, parce que l’encodeur paie une cadence impossible avec deux cadences possibles.
La conséquence tient en une phrase : « la cadence d’un GIF » est le plus souvent une moyenne qu’aucune image ne possède. Tout outil qui annonce un nombre unique pour un GIF annonce quelque chose qui n’est pas dans le fichier. Pour savoir ce que fait vraiment votre GIF, il faut regarder tous les délais.
Changer la vitesse ne devrait toucher aucun pixel
Puisque la temporisation tient entièrement dans ces deux octets par image, retemporiser un GIF est une édition d’octets. La palette, les données de pixels compressées en LZW, la position des images, l’indice de transparence — rien de tout cela n’a besoin d’être lu, encore moins réécrit.
La plupart des changeurs de vitesse de GIF font l’inverse : décoder en images, ré-encoder, requantifier la palette. Cela coûte une génération visible de couleur à chaque passage, et c’est pourquoi un GIF passé par deux ou trois outils paraît moins bon que l’original sans que personne puisse dire où.
Nous avons mesuré l’édition d’octets sur le fichier de 24 images ci-dessus, qui pèse 54 596 octets :
| Retemporisé à | Octets modifiés | Par image | Part du fichier |
|---|---|---|---|
| 20 cs (5 i/s) | 24 | 1 | 0,044 % |
| 4 cs (25 i/s) | 24 | 1 | 0,044 % |
| 3 cs (33,33 i/s) | 24 | 1 | 0,044 % |
| vitesse 2× (4, 5, 4, 4, 5 …) | 24 | 1 | 0,044 % |
| 300 cs (0,33 i/s) | 48 | 2 | 0,088 % |
Un octet par image, et non deux, pour tout sauf la dernière ligne — parce que l’octet de poids fort du délai vaut zéro des deux côtés de l’édition tant que le délai ne dépasse pas 256 centièmes. Deux octets sont écrits par image ; un seul diffère en général. Dans tous les cas le fichier revient de la même longueur, avec des données de pixels identiques bit pour bit, ce qui est la propriété qui compte.
Pourquoi votre navigateur ne peut rien vous dire de tout cela
La façon évidente de vérifier la temporisation d’un GIF est de le charger et de le regarder. Cela ne marche pas, et l’échec est total, pas approximatif.
Nous avons fabriqué six copies du même GIF de 12 images — pixels identiques, seuls les octets de délai réécrits — avec des délais de 0, 1, 2, 3, 5 et 10 centièmes. Chacune a été affichée à l’écran et dessinée sur un canvas toutes les 4 ms pendant quatre secondes, en hachant les pixels à chaque fois pour compter les changements d’image.
Zéro avancement. Sur les six fichiers. Dessiner un GIF animé sur un canvas renvoie une image fixe : le navigateur anime l’image à l’écran mais ne transmet pas l’image courante à votre code. Ce n’est pas un bug que nous avons contourné — c’est la raison pour laquelle un outil qui veut vous dire la vérité sur un GIF doit analyser le fichier lui-même.
Cela veut dire aussi qu’il y a un chiffre que nous ne vous donnerons pas. Les navigateurs imposent leur propre délai minimum, et les très petites valeurs sont traitées comme quelque chose de plus grand — mais nous n’avons pas pu le mesurer ici, précisément pour la raison ci-dessus, donc aucun chiffre à ce sujet ne figure sur nos pages. Tout le reste de cette page vient d’un fichier réel.
Que faire
Si vous pouvez choisir votre cadence, choisissez-en une qui existe : 25, 20 ou 10 i/s sont exactes, et 25 est assez proche de 24 pour que personne ne voie la différence. S’il vous faut 30 ou 60 exactement, ce n’est pas d’un GIF que vous avez besoin, mais d’un conteneur à base de temps plus fine — c’est la raison honnête de le convertir en MP4. Un MP4 à 30 i/s fait bien 30 i/s, et il pèsera en général une fraction du poids.
Et si vous voulez simplement voir ce que fait votre propre GIF, le changeur de vitesse de GIF dessine le délai de chaque image sous forme de barre, vous donne la cadence exacte que vous obtiendrez pour celle que vous demandez, et indique combien d’octets il a modifiés pour y arriver. Il fonctionne dans votre navigateur ; rien n’est envoyé.
Questions fréquentes
Pourquoi un GIF ne peut-il pas faire 30 i/s alors que la vidéo le peut ?
Parce que le format GIF stocke le délai de chaque image en nombre entier de centièmes de seconde, et que 100/30 vaut 3,33 — un délai qui n’existe pas. Les conteneurs vidéo stockent une base de temps sous forme de fraction : 30 i/s y vaut exactement 30/1 et 29,97 exactement 30000/1001. C’est une limite du format de fichier de 1989, pas de votre encodeur.
Mon GIF annonce 12 i/s mais les images semblent irrégulières. Est-il abîmé ?
Presque certainement pas — il est alterné exprès. Nous avons lu un vrai GIF ffmpeg nominalement à 12 i/s et trouvé des délais de 8, 9, 8, 8, 9 qui se répètent : 24 images totalisant 200 centièmes, soit exactement 12,0000 i/s en moyenne, alors que les images consécutives sont à 80 ms et 90 ms. La moyenne est juste et aucune image ne l’a.
Changer la vitesse d’un GIF dégrade-t-il sa qualité ?
Ce n’est pas obligatoire. La temporisation tient dans deux octets par image, donc retemporiser peut être une pure édition d’octets qui ne décode aucun pixel. Sur notre fichier de test de 24 images, la retemporisation a modifié 24 octets sur 54 596 et le fichier est revenu de la même longueur. Les outils qui décodent et ré-encodent, eux, perdent de la qualité : ils requantifient la palette à chaque fois.
Que signifie un délai d’image de 0 ?
Que le fichier refuse d’en préciser un, et que chaque visionneuse décide seule. C’est le seul cas où la lecture est réellement imprévisible d’un navigateur ou d’une application à l’autre : mieux vaut écrire un vrai délai que de le laisser à zéro.
Quelles cadences sont exactes en GIF ?
Toute cadence de la forme 100/n. Parmi celles que l’on demande, ce sont 100, 50, 25, 20, 12,5, 10, 5, 4, 2 et 1 i/s. La liste courte utile est 25, 20 et 10 — et 25 i/s remplace 24 d’assez près pour que la différence soit invisible.