30 FPS Não Existe em GIF

14 de setembro de 2026 · 7 min de leitura

Peça 30 quadros por segundo a qualquer codificador de GIF e ele vai dizer que sim. É mentira, e o motivo está a quatro bytes de profundidade no formato: o atraso de um quadro de GIF é um número inteiro de centésimos de segundo, e 100/30 não é um número inteiro.

Cada quadro de um GIF carrega o próprio atraso, guardado num bloco Graphic Control Extension que se parece com isto:

0x21 0xF9 0x04 <packed> <delay lo> <delay hi> <transparent> 0x00

Os dois bytes de atraso são um inteiro de 16 bits little-endian, e a unidade dele é centésimos de segundo. Não milissegundos. Não um número racional. Uma contagem inteira de centésimos, de 0 a 65.535.

Esse único fato fixa todo o conjunto de taxas de quadros que um GIF consegue expressar. Se o atraso tem que ser um inteiro n, a taxa tem que ser 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 …

Trinta não está nessa lista. Nem 60, nem 24, nem 15 — três das quatro taxas em que a maioria dos vídeos é gravada.

O que o codificador realmente faz com o seu 30

Ele calcula 100/30 = 3,33 centésimos, descobre que não consegue guardar isso e arredonda para 3. Seu GIF agora roda a 33,33 fps, 11,11 % rápido demais. O erro não é a parte interessante; a duração é:

Você pedeAtraso guardadoRoda aErroDez segundos viram
60 fps2 cs50,00 fps−16,67 %12,00 s
50 fps2 cs50,00 fpsexato10,00 s
30 fps3 cs33,33 fps+11,11 %9,00 s
25 fps4 cs25,00 fpsexato10,00 s
24 fps4 cs25,00 fps+4,17 %9,60 s
20 fps5 cs20,00 fpsexato10,00 s
15 fps7 cs14,29 fps−4,76 %10,50 s
12 fps8 cs12,50 fps+4,17 %9,60 s
10 fps10 cs10,00 fpsexato10,00 s
8 fps13 cs7,69 fps−3,85 %10,40 s
5 fps20 cs5,00 fpsexato10,00 s

Dez segundos de vídeo capturados a 30 fps são 300 quadros. A 3 centésimos cada um, isso dá 900 centésimos — nove segundos. O GIF termina um segundo inteiro antes do clipe de onde foi feito. Peça 60 e ele estica no outro sentido: 600 quadros a 2 cs são 12,00 segundos.

Das taxas que alguém realmente pede, só 50, 25, 20, 10 e 5 voltam exatas. Todo o resto desanda, e desanda por uma porcentagem fixa que cresce com a duração do clipe. Monte um GIF em cima de uma música e essa é a explicação inteira para o loop ir se afastando da batida.

Os codificadores escondem isso alternando dois atrasos

É aqui que deixa de ser aritmética e passa a ser algo que você consegue ler de um arquivo no seu disco. Um codificador bem feito não arredonda todos os quadros do mesmo jeito — ele alterna, para que a média saia certa.

Pegamos um GIF produzido pelo ffmpeg, nominalmente a 12 fps, e percorremos os blocos dele para ler o atraso de cada quadro:

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 quadros por segundo de média. A média é perfeita — e nenhum quadro do arquivo está a 12 fps. Quadros consecutivos ficam a 80 ms e depois 90 ms de distância, um salto de 12,5 % entre vizinhos que nunca se resolve, porque o codificador está comprando uma taxa impossível com duas possíveis.

A consequência merece uma frase só: “a taxa de quadros de um GIF” costuma ser uma média que nenhum quadro individual tem. Qualquer ferramenta que informa um número único para um GIF está informando algo que não está no arquivo. Se você quer saber o que o seu GIF realmente faz, precisa olhar todos os atrasos.

Mudar a velocidade não deveria encostar num pixel

Como a temporização mora inteiramente naqueles dois bytes por quadro, retemporizar um GIF é uma edição de bytes. A paleta, os dados de pixel comprimidos em LZW, as posições dos quadros, o índice de transparência — nada disso precisa ser lido, muito menos reescrito.

A maioria dos alteradores de velocidade de GIF faz ao contrário: decodifica em quadros, recodifica, requantiza a paleta. Isso custa uma geração visível de cor cada vez que você mexe no arquivo, e é por isso que um GIF que passou por duas ou três ferramentas fica pior que o original sem ninguém saber apontar onde.

Medimos a edição de bytes no arquivo de 24 quadros acima, que tem 54.596 bytes:

Retemporizado paraBytes alteradosPor quadroFração do arquivo
20 cs (5 fps)2410,044 %
4 cs (25 fps)2410,044 %
3 cs (33,33 fps)2410,044 %
2× de velocidade (4, 5, 4, 4, 5 …)2410,044 %
300 cs (0,33 fps)4820,088 %

Um byte por quadro, não dois, em tudo menos na última linha — porque o byte alto do atraso é zero dos dois lados da edição, a menos que o atraso passe de 256 centésimos. Dois bytes são escritos por quadro; em geral só um deles difere. De qualquer forma o arquivo volta com o mesmo tamanho e com os dados de pixel idênticos bit a bit, que é a propriedade que importa.

Por que o seu navegador não consegue te contar nada disso

O jeito óbvio de conferir a temporização de um GIF é carregar e assistir. Não funciona, e a falha é absoluta, não aproximada.

Montamos seis cópias do mesmo GIF de 12 quadros — pixels idênticos, só os bytes de atraso reescritos — com atrasos de 0, 1, 2, 3, 5 e 10 centésimos. Cada uma foi exibida na tela e desenhada num canvas a cada 4 ms por quatro segundos, com um hash dos pixels a cada vez para contar quantas vezes o quadro mudou.

Zero avanços. Nos seis arquivos. Desenhar um GIF animado num canvas devolve um quadro estático: o navegador anima a imagem na tela, mas não entrega o quadro atual ao seu código. Não é um bug que a gente contornou — é a razão de uma ferramenta que queira dizer a verdade sobre um GIF ter que analisar o arquivo ela mesma.

Isso também significa que tem um número que não vamos te dar. Navegadores 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, exatamente pelo motivo acima, então nenhum número sobre isso aparece em nenhuma das nossas páginas. Todo o resto desta página saiu de um arquivo real.

O que fazer a respeito

Se você pode escolher a taxa, escolha uma que exista: 25, 20 ou 10 fps são exatas, e 25 está perto o bastante de 24 para ninguém ver diferença. Se você precisa de 30 ou 60 exatos, você não precisa de um GIF — precisa de um contêiner com base de tempo mais fina, que é a razão honesta para converter para MP4. Um MP4 a 30 fps é 30 fps, e em geral vai ser uma fração do tamanho.

E se você só quer ver o que o seu próprio GIF está fazendo, o alterador de velocidade de GIF desenha o atraso de cada quadro como uma barra, diz a taxa exata que você vai receber pela taxa que pediu, e informa quantos bytes ele mudou para chegar lá. Roda no seu navegador; nada é enviado.

Perguntas frequentes

Por que um GIF não faz 30 fps se vídeo faz?

Porque o formato GIF guarda o atraso de cada quadro como um número inteiro de centésimos de segundo, e 100/30 é 3,33 — um atraso que não existe. Contêineres de vídeo guardam a base de tempo como fração, então 30 fps é exatamente 30/1 e 29,97 é exatamente 30000/1001. É uma limitação do formato de arquivo de 1989, não do seu codificador.

Meu GIF diz 12 fps mas os quadros parecem irregulares. Está quebrado?

Quase certamente não — ele é alternado de propósito. Lemos um GIF real do ffmpeg nominalmente a 12 fps e encontramos atrasos de 8, 9, 8, 8, 9 se repetindo: 24 quadros somando 200 centésimos, o que dá exatamente 12,0000 fps de média enquanto quadros consecutivos ficam a 80 ms e 90 ms de distância. A média está certa e nenhum quadro tem esse valor.

Mudar a velocidade de um GIF piora a qualidade?

Não precisa piorar. A temporização mora em dois bytes por quadro, então retemporizar pode ser uma edição de bytes pura que nunca decodifica um pixel. No nosso arquivo de teste de 24 quadros, retemporizar mudou 24 bytes de 54.596 e o arquivo voltou com o mesmo tamanho. Ferramentas que decodificam e recodificam perdem qualidade, sim, porque requantizam a paleta toda vez.

O que significa um atraso de quadro igual a 0?

Que o arquivo se recusa a especificar um, e cada visualizador decide por conta própria. É o único caso em que a reprodução é genuinamente imprevisível entre navegadores e aplicativos, então vale escrever um atraso de verdade em vez de deixar em zero.

Quais taxas de quadros são exatas em GIF?

Qualquer taxa da forma 100/n. Entre as que as pessoas pedem, são 100, 50, 25, 20, 12,5, 10, 5, 4, 2 e 1 fps. A lista curta prática é 25, 20 e 10 — e 25 fps substitui 24 tão de perto que a diferença é invisível.