Cada quadro de um GIF carrega o próprio atraso, guardado na sua Graphic Control Extension:
0x21 0xF9 0x04 <packed> <delay lo> <delay hi> <transparent> 0x00
Esses dois bytes de atraso são um número de 16 bits em centésimos de segundo. Um número inteiro. Esse detalhe decide todo o resto: as únicas taxas de quadros que um GIF consegue expressar são 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 … e nada entre elas. 30 não está nessa lista. Nem 60, nem 24, nem 15.
Um codificador a quem se pede 30 fps calcula 100/30 = 3,33 centésimos, não consegue guardar isso e arredonda para 3. O seu GIF passa a rodar a 33,33 fps. Esta é a tabela inteira, e a última coluna é a que importa:
| Você pede | Atraso guardado | Roda de verdade a | Erro | Dez segundos viram |
|---|---|---|---|---|
| 60 fps | 2 cs | 50,00 fps | −16,67 % | 12,00 s |
| 50 fps | 2 cs | 50,00 fps | exato | 10,00 s |
| 30 fps | 3 cs | 33,33 fps | +11,11 % | 9,00 s |
| 25 fps | 4 cs | 25,00 fps | exato | 10,00 s |
| 24 fps | 4 cs | 25,00 fps | +4,17 % | 9,60 s |
| 20 fps | 5 cs | 20,00 fps | exato | 10,00 s |
| 15 fps | 7 cs | 14,29 fps | −4,76 % | 10,50 s |
| 12 fps | 8 cs | 12,50 fps | +4,17 % | 9,60 s |
| 10 fps | 10 cs | 10,00 fps | exato | 10,00 s |
Dez segundos de vídeo capturados a 30 fps são 300 quadros. Três centésimos cada um dão 900 centésimos — nove segundos. O GIF termina um segundo inteiro antes do clipe de onde veio, e se você está casando com música ou cortando contra um vídeo, é daí que vem o descompasso. Só 50, 25, 20, 10 e 5 voltam exatos.
Eles não arredondam todos os quadros do mesmo jeito. Pegamos um GIF feito pelo ffmpeg nominalmente a 12 fps e lemos os atrasos direto dos bytes:
8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8, 8, 9, 8
Vinte e quatro quadros, 200 centésimos, exatamente 2,00 segundos — o que dá exatamente 12,0000 fps de média. A média é perfeita. Mas quadros consecutivos ficam a 80 ms e depois 90 ms de distância, uma variação de 12,5 % entre vizinhos que nunca some, porque o codificador está pagando por uma taxa impossível alternando duas possíveis.
Vale dizer a consequência sem rodeios: “a taxa de quadros de um GIF” costuma ser uma média que nenhum quadro individual tem. Uma ferramenta que te mostra um número está mostrando algo que não está no arquivo. Esta página mostra todos os atrasos, uma barra por quadro, para você ver se o seu é uniforme ou alternado.
Aqui está a parte que diferencia esta ferramenta de qualquer outro alterador de velocidade de GIF. Mudar a velocidade de um GIF é escrever aqueles dois bytes de atraso por quadro. Mais nada. A paleta, os dados de pixel comprimidos em LZW, as posições dos quadros, a transparência — nada disso entra na conta.
A maioria das ferramentas decodifica o GIF em quadros e recodifica, o que requantiza a paleta e custa uma geração visível de cor cada vez que você mexe. Esta escreve apenas os dois bytes de atraso de cada quadro e devolve o resto intocado.
Quantos bytes de fato diferem é menos ainda, e a página conta para você em vez de prometer. Retemporizamos um GIF de 24 quadros com 54.596 bytes e 24 bytes mudaram — um por quadro, 0,044 % do arquivo. Um e não dois, porque o byte alto do atraso é zero sempre que o atraso é menor que 256 centésimos de segundo, então ir de 8 para 20 move um byte só. Peça um atraso de 3,00 segundos e o segundo byte também se mexe, e a conta vira 48. O número do seu arquivo está na página, ao lado do tamanho total dele.
Você poderia esperar ler a temporização de um GIF carregando e assistindo. Não dá. Desenhar um GIF animado num canvas devolve um quadro estático — testamos seis arquivos com atrasos de 1 a 10 centésimos, amostrando a cada 4 ms por quatro segundos cada, e tivemos zero avanços de quadro nos seis. O decodificador de imagem do navegador anima o GIF na tela, mas não entrega o quadro atual para o seu código.
Então uma ferramenta que queira dizer a verdade sobre um GIF precisa ler o arquivo ela mesma, que é o que esta faz, no seu navegador, sem enviar nada.
Há uma coisa que deliberadamente não afirmamos. Os navegadores também impõem um atraso mínimo próprio, e valores muito pequenos são tratados como algo maior — mas não conseguimos medir isso aqui, pelo motivo acima, então nenhum número sobre isso aparece nesta página. Se você precisa de temporização exata, a resposta não é um GIF: converta para MP4, onde a base de tempo é a que você quiser.
Não. O arquivo é lido pelo seu navegador, analisado na própria página, e a cópia retemporizada é montada na memória e devolvida como download. Ele nunca chega a um servidor, que é também por que a ferramenta continua funcionando com a aba offline depois que a página carregou.
Não tem como. Só os dois bytes de atraso de cada quadro são escritos; a paleta e os dados de pixel comprimidos passam intocados. A página informa quantos bytes diferem entre o arquivo que você deu e o que ela devolve — no nosso GIF de teste de 24 quadros foram 24 de 54.596, e se estivesse recodificando seria quase o arquivo inteiro.
Porque o formato guarda o atraso como número inteiro de centésimos de segundo, e 100/30 é 3,33. Esse atraso não existe. Três centésimos dão 33,33 fps e quatro dão 25. Se você precisa de 30, precisa de um formato com base de tempo mais fina — MP4 ou WebM.
Quase certamente não. Codificadores alternam entre dois atrasos para fazer uma média impossível sair certa — 8, 9, 8, 8, 9 dá exatamente 12 fps de média. Também é normal um GIF feito à mão segurar um quadro de propósito. A faixa de barras nesta página mostra todos os atrasos para você saber qual é o seu caso.
Significa que o arquivo não especifica um, e cada visualizador decide por conta própria. É o único caso em que você realmente não consegue prever a reprodução, e vale a pena definir um valor de verdade em vez de deixar assim. Escolha “atraso exato por quadro” e dê um.
Sim — o multiplicador de velocidade vai de 0,25× a 4×, e ele divide o atraso existente de cada quadro em vez de substituí-lo, então um GIF que foi alternado de propósito mantém o ritmo relativo. Definir uma taxa de quadros alvo, em vez disso, deixa todos os quadros uniformes.
Não. O arquivo retemporizado tem exatamente o mesmo tamanho do original, byte por byte, porque dois bytes são sobrescritos e não inseridos. Se você precisa de um GIF menor, a alavanca é o número de quadros ou a paleta, não a temporização.
Sim. O trabalho é proporcional ao número de quadros, não ao número de pixels, porque os dados de pixel nunca são decodificados. Um GIF com centenas de quadros é retemporizado tão rápido quanto um com dez.