Executando verificação de segurança...
22

Como fazer GIFs animados de alta qualidade e alta resolução usando FFmpeg

GIFs animados são uma ótima forma de ilustrar algo rápido em uma página, como exemplo esta publicação onde eu inseri alguns GIFs para demonstrar alguns novos recursos do TabNews, como por exemplo a abertura instantânea de páginas:

Abertura instantânea de páginas

Mas ao mesmo tempo, eu sempre tive dificuldade em produzir eles de uma forma que mantivessem uma alta resolução e alta qualidade, inclusive em casos onde eu estava gravando a minha tela. Todo sistema web e online que eu utilizava para converter Vídeo para GIF meio que acabava destruindo a qualidade final ao deixar ruídos e pixels feios.

Então eu comecei a estudar para valer como fazer isso usando o FFmpeg, que é um aplicativo grátis e open source que converte arquivos de áudio e vídeo através da linha de comando.

Tutoriais sobre como usar FFmpeg para converter Vídeo para GIFs

Nas minhas pesquisas, eu encontrei muitos tutoriais explicando como usar o FFmpeg para converter arquivos de vídeo para GIFs, mas nenhum deles explicava realmente como manter uma alta qualidade em casos onde a gravação é uma tela de computador, então como estou usando bastante isso aqui no TabNews, nada mais justo de deixar registrado como eu estou fazendo.

2 comandos que podem ser consolidados em 1 comando

Ao final desta publicação eu vou colocar a versão de 1 linha que eu uso para converter arquivos de vídeo em GIF, mas primeiro vou explicar de forma separada para você entender o que está acontecendo e tudo começa na geração da paleta de cores do GIF e você faz isso através do comando abaixo:

ffmpeg -i video.mov -vf "palettegen=stats_mode=diff" -y /tmp/palette.png

Este comando irá utilizar o ffmpeg para ler o arquivo video.mov, analisar todas as cores dele e montar uma paleta final que será salva no caminho /tmp/palette.png. Esta paleta será utilizada no comando a seguir para que o GIF final tenha, ao mesmo tempo, a maior fidelidade possível de cores e ocupando o menor espaço possível.

Isso acontece pois o modo stats_mode=diff irá registrar e antecipar na paleta apenas os pixels do arquivo de vídeo original que se mexeram, o que é ótimo quando você usa como fonte um vídeo de uma tela onde a maioria dos pixels podem ficar estáticos.

*Observação 1: Você pode importar praticamente qualquer formato de vídeo e não somente mov.

*Observação 2: Note que o caminho /tmp/palette.png possa ser incompatível com o seu sistema operacional, mas você pode salvar este arquivo em qualquer lugar que quiser.

Gerando o GIF de alta qualidade

O segundo passo é renderizar para valer o GIF e isso acontece na segunda parte do comando:

ffmpeg -i video.mov -i /tmp/palette.png -filter_complex "trim=start_frame=0, fps=30, paletteuse=dither=none" -y video-convertido.gif

Aqui fazemos a importação de novo do video.mov, a importação da paleta /tmp/palette.png e aplicamos alguns filtros:

  • trim=start_frame=0 define quantos frames você quer cortar do início do vídeo, caso queira remover alguma rebarba.
  • fps=30 define os frames por segundo do GIF final.
  • paletteuse=dither=none define que não seja feito dither, que é artificialmente misturar as cores para tentar compensar a falta de cores da paleta na hora de representar um degradê, por exemplo.

Então com os comandos acima eu gerei esse GIF abaixo que é eu gravando uma parte da tela aqui do editor de Markdown do TabNews:

Exemplo de GIF

Cuidado com o tamanho do arquivo final e isto vai ser definido por primariamente três coisas:

  1. Quantas coisas se mexem na tela, então tente ao máximo manter as coisas paradas na tela.
  2. Os frames por segundo especificados na propriedade fps=30.
  3. A resolução do arquivo de vídeo, que pode ser controlada pelo filtro scale=800:-1.

Então para reduzir a resolução mantendo a mesma escala, você pode usar a propriedade scale como no exemplo abaixo:

ffmpeg -i video.mov -i /tmp/palette.png -filter_complex "trim=start_frame=0, fps=30, scale=800:-1, paletteuse=dither=none" -y video-convertido.gif

Com o trade-off de, quanto menor a resolução, menos cristalino o GIF ficará.

Comando final

No meu caso, eu gravo os vídeos usando um macOS que por padrão grava os vídeos da tela com a extensão .mov. Então coloquei os comandos acima tudo em uma linha e já assumindo que o arquivo de vídeo é um .mov, porque daí eu altero o nome do arquivo o início do script pela variável videoname e ao final ele gera um arquivo .gif com esse mesmo nome.

videoname="video-que-acabei-de-gravar" && ffmpeg -i "${videoname}.mov" -vf "palettegen=stats_mode=diff" -y /tmp/palette.png && ffmpeg -i "${videoname}.mov" -i /tmp/palette.png -filter_complex "trim=start_frame=0, fps=30, paletteuse=dither=none" -y "${videoname}.gif"

Após executar esse comando, vai entrar o arquivo video-que-acabei-de-gravar.mov e vai sair o GIF video-que-acabei-de-gravar.gif.

Carregando publicação patrocinada...
2