2013-02-22 20:06:30 +0000 2013-02-22 20:06:30 +0000
335
335

Como posso converter um vídeo para GIF usando ffmpeg, com qualidade razoável?

Estou a converter um vídeo para GIF com ffmpeg:

ffmpeg -i input.flv -ss 00:00:00.000 -pix_fmt rgb24 -r 10 -s 320x240 -t 00:00:10.000 output.gif

Funciona muito bem, mas o ficheiro gif de saída tem uma qualidade muito baixa.

Alguma ideia de como posso melhorar a qualidade do gif convertido?

Respostas (12)

505
505
505
2013-02-22 21:31:46 +0000

ffmpeg exemplo

183k

ffmpeg podem produzir GIF de alta qualidade. Antes de começar é sempre recomendado o uso de uma versão recente: download ou compile .

ffmpeg -ss 30 -t 3 -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 output.gif
  • Este exemplo salta os primeiros 30 segundos (-ss 30) da entrada e cria uma saída de 3 segundos (-t 3).
  • fps filtragem define a frame rate. Uma taxa de 10 frames por segundo é utilizada no exemplo.
  • escala filtro redimensionará a saída para 320 pixels de largura e determinará automaticamente a altura enquanto preserva a relação de aspecto. O lanczos algoritmo de escala é utilizado neste exemplo.
  • palettegen e paletteuse filtros irão gerar e utilizar uma paleta personalizada gerada a partir da sua entrada. Estes filtros têm muitas opções, por isso consulte os links para uma lista de todas as opções e valores disponíveis. Veja também a secção Advanced options abaixo.
  • split filter will allow everything to be done in one command and avoids having to create a temporary PNG file of the palette.
  • Control looping with -loop output option but the values are confusing. Um valor de 0 é looping infinito, -1 não é looping, e 1 vai fazer looping uma vez significando que vai tocar duas vezes. Então um valor de 10 fará o GIF tocar 11 vezes.

Opções avançadas

Os filtros palettegen e paletteuse têm muitas opções adicionais. As mais importantes são:

  • stats_mode (paletegen). Pode forçar os filtros a focar a paleta na imagem geral (full que é o padrão), apenas as partes móveis (diff), ou cada moldura individual (single). Por exemplo, para gerar uma paleta para cada frame individual use palettegen=stats_mode=single & paletteuse=new=1.

  • dither (paleteuse). Escolha o algoritmo de dithering. Existem três tipos principais: determinístico (bayer), difusão de erros (todos os outros incluindo o sierra2_4a por defeito), e nenhum. O seu GIF pode parecer melhor usando um algoritmo de dithering em particular, ou nenhum dithering em particular. Se você quiser tentar bayer certifique-se de testar a opção bayer_scale também.

Veja GIF de alta qualidade com FFmpeg para explicações, imagens de exemplo, e informações mais detalhadas para uso avançado.

Veja também a documentação palettegen e paletteuse para todas as opções e valores disponíveis.


exemplo ImageMagick convert

227k

Outro método de linha de comando é o pipe de ffmpeg para convert (ou magick) da ImageMagick.

ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" -c:v pam -f image2pipe - | convert -delay 10 - -loop 0 -layers optimize output.gif

ffmpeg opções:

  • -vf "fps=10,scale=320:-1:flags=lanczos" a filtergraph usando os filtros fps e scale . fps define a taxa de quadros para 10, e a escala define o tamanho para 320 pixels de largura e altura é automaticamente determinada e usa um valor que preserva a relação de aspecto. O lanczos algoritmo de escala é utilizado neste exemplo.

  • -c:v pam Escolhe o codificador de imagem pam. O exemplo produz o formato de imagem PAM (Portable AnyMap) que é um formato RGB simples e sem perdas que suporta transparência (alpha) e é suportado por convert. É mais rápido de codificar que o PNG.

  • -f image2pipe escolhe o muxer image2pipe porque ao sair para um pipe ffmpeg precisa de ser dito qual o muxer a utilizar.

convert opções:

  • -delay Veja Configurar frame rate secção abaixo.

  • -loop 0 faz loop infinito.

  • -layers optimize irá permitir o optimizador de GIF de uso geral. Veja ImageMagick Animation Optimization para mais detalhes. Não é garantido que irá produzir um output menor, por isso vale a pena tentar sem -layers optimize e comparar resultados.

Definir frame rate

Definir frame rate com uma combinação do filtro fps em ffmpeg e -delay em convert. Isto pode tornar-se complicado porque o convert apenas recebe um fluxo bruto de imagens para que nenhum fps seja preservado. Em segundo lugar, o valor de -delay em convert está em ticks (há 100 ticks por segundo), não em frames por segundo. Por exemplo, com fps=12.5 = 100/12.5 = 8 = -delay 8.

convert arredonda o valor de -delay para um número inteiro, portanto 8.4 resulta em 8 e 8.5 resulta em 9. Isto significa efectivamente que ** apenas algumas taxas de fotogramas são suportadas** quando se define um atraso uniforme em todos os fotogramas (um atraso específico pode ser definido por fotograma, mas isso está para além desta resposta).

-delay parece ser ignorado se for utilizado como opção de saída, pelo que tem de ser utilizado antes de -, como mostra o exemplo.

Finalmente, os navegadores e visualizadores de imagens podem implementar um atraso mínimo, pelo que o seu -delay pode ser ignorado de qualquer forma.

Video cortesia do U.S. Fish & Wildlife Service National Conservation Training Center.

88
88
88
2014-03-18 09:47:53 +0000

Se preferir evitar ficheiros de imagem intermédios, os comandos fornecidos por LordNeckBeard podem ser canalizados entre ffmpeg e ImageMagick’s convert para que não sejam necessários ficheiros intermédios:

ffmpeg -i input.flv -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 5 -loop 0 - output.gif

O -f image2pipe diz a ffmpeg para dividir o vídeo em imagens e torná-lo adequado para ser “piped out”, e o -vcodec ppm especifica o formato de saída a ser ppm (por alguma razão se o formato for png, ou o convert não lê todas as imagens do “pipe”, ou o ffmpeg não as produz todas). O - para ambos os comandos especifica que um pipe será usado para output e input respectivamente.

Para optimizar o resultado sem guardar um ficheiro, pode pipear o output de convert para um segundo comando convert:

ffmpeg -i input.flv -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 5 -loop 0 - gif:- | convert -layers Optimize - output.gif

O gif:- diz ao convert para pipear o seu output como dados formatados como gif e o -layers Optimize diz ao segundo convert para executar os métodos optimize-frame e optimize-transparancy (ver o ImageMagick Introdução à Optimização da Animação ). Note que a saída do -layers Optimize pode nem sempre fornecer um ficheiro de tamanho mais pequeno, por isso pode querer tentar converter para um gif sem optimização primeiro para ter a certeza.

Lembre-se que durante todo este processo tudo está em memória, por isso pode precisar de memória suficiente se as imagens forem bastante grandes.

38
38
38
2015-03-23 18:39:20 +0000

A partir de ffmpeg 2.6, podemos fazer ainda melhor:

palette="/tmp/palette.png"
filters="fps=15,scale=320:-1:flags=lanczos"

ffmpeg -i input.flv -vf "$filters,palettegen" -y $palette
ffmpeg -i input.flv -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y output.gif

HT

20
20
20
2017-10-05 12:04:32 +0000

A resposta de @Stephane é muito boa. Mas vai receber um aviso como Buffer queue overflow, dropping. para alguns vídeos, e o gif gerado tem algum frame perdido.

Aqui está uma versão melhor com o filtro fifo para evitar Buffer queue overflow quando usar o filtro paletteuse. Utilizando o filtro split para evitar a criação de ficheiros de palete intermédios PNG.

ffmpeg -i input.mp4 -filter_complex 'fps=10,scale=320:-1:flags=lanczos,split [o1] [o2];[o1] palettegen [p]; [o2] fifo [o3];[o3] [p] paletteuse' out.gif
18
18
18
2015-07-12 09:35:07 +0000

Fiz a minha própria versão do guião, que também parametriza a resolução de saída e a frame rate.

Running ./gifenc.sh input.mov output.gif 720 10 irá produzir um GIF de 720p de 10fps a partir do filme que lhe deu. Você pode precisar fazer chmod +x gifenc.sh para o arquivo.

#!/bin/sh

palette="/tmp/palette.png"

filters="fps=$4,scale=$3:-1:flags=lanczos"

ffmpeg -v warning -i "$1" -vf "$filters,palettegen" -y "$palette"
ffmpeg -v warning -i "$1" -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y "$2"

Você pode ler os detalhes no meu Github

Assumptions: ffmpeg está instalado, e o script está na mesma pasta que os outros arquivos.

12
12
12
2017-09-30 15:23:29 +0000

O ffmpeg com paleta method pode ser executado num único comando, sem intermediário .png file.

ffmpeg -y -ss 30 -t 3 -i input.flv -filter_complex \
"fps=10,scale=320:-1:flags=lanczos[x];[x]split[x1][x2]; \
[x1]palettegen[p];[x2][p]paletteuse" output.gif

Isto pode ser feito graças ao filtro split .

11
11
11
2015-05-28 10:55:51 +0000

fez um guião, testou e trabalha.

utilização:

./avi2gif.sh ./vokoscreen-2015-05-28_12-41-56.avi

HAVE PHUN :)

vim avi2gif.sh

#!/bin/sh

INPUT=$1

# default settings, modify if you want.

START_AT_SECOND=0; # in seconds, if you want to skip the first 30 seconds put 30 here

LENGTH_OF_GIF_VIDEO=9999999; # in seconds, how long the gif animation should be

echo "Generate a palette:"
ffmpeg -y -ss $START_AT_SECOND -t $LENGTH_OF_GIF_VIDEO -i $INPUT -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png

echo "Output the GIF using the palette:"
ffmpeg -ss $START_AT_SECOND -t $LENGTH_OF_GIF_VIDEO -i $INPUT -i palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" $INPUT.gif

btw: vokoscreen ](http://www.kohaupt-online.de/hp/) é uma EXCELENTE ferramenta de captura de ecrã para Linux :)

OBRIGADO Michael Kohaupt :) Rock steady.

algumas estatísticas de tamanho de ficheiro:

5.3M = vokoscreen-2015-04-28_15-43-17.avi -> vokoscreen-2015-05-28_12-41-56.avi.gif = 1013K

veja os resultados aqui.

10
10
10
2016-12-09 17:34:16 +0000

Linux/Unix/macOS

Seguindo @LordNeckbeard approach com o comando ffmpeg, encontre a seguinte função Bash útil que pode ser adicionada ao seu ficheiro ~/.bash_profile:

# Convert video to gif file.
# Usage: video2gif video_file (scale) (fps)
video2gif() {
  ffmpeg -y -i "${1}" -vf fps=${3:-10},scale=${2:-320}:-1:flags=lanczos,palettegen "${1}.png"
  ffmpeg -i "${1}" -i "${1}.png" -filter_complex "fps=${3:-10},scale=${2:-320}:-1:flags=lanczos[x];[x][1:v]paletteuse" "${1}".gif
  rm "${1}.png"
}

Uma vez carregada a função (manualmente ou a partir de . ~/.bash_profile), deverá ter o novo comando video2gif.

Exemplo de utilização:

video2gif input.flv

ou:

video2gif input.flv 320 10

Escala para 320 de largura com 10 frames por segundo.

Também pode especificar um formato de vídeo diferente (como mp4).


macOS

Pode tentar GIF Brewery app que pode criar GIFs a partir de ficheiros de vídeo.


Alternativamente existem vários websites que estão a fazer conversão online sem custos.

9
9
9
2017-11-14 23:01:37 +0000

A resposta seleccionada assume que deseja escalar o vídeo de origem e alterar os seus fps no gif produzido. Se não precisa de fazer isto, os seguintes trabalhos:

src="input.flv"
dest="output.gif"
palette="/tmp/palette.png"

ffmpeg -i $src -vf palettegen -y $palette
ffmpeg -i $src -i $palette -lavfi paletteuse -y $dest

Isto veio a calhar quando eu queria um gif que recriasse fielmente o vídeo de origem que eu estava a utilizar.

6
6
6
2017-04-21 15:36:34 +0000

Para utilizadores do windows: criar video2gif.bat ficheiro no directório windows com estes conteúdos:

@echo off
set arg1=%1
set arg2=%arg1:~0,-4%
ffmpeg -y -i %arg1% -vf fps=10,scale=-1:-1:flags=lanczos,palettegen %TEMP%\palette.png
ffmpeg -i %arg1% -i %TEMP%\palette.png -filter_complex "fps=10,scale=-1:-1:flags=lanczos[x];[x][1:v]paletteuse" %arg2%.gif
del /f %TEMP%\palette.png

E depois em qualquer lugar onde o possa usar seja como este exemplo:

video2gif myvideo.mp4

Depois tem myvideo.gif no directório actual. Se myvideo.gif existir, pergunta de si para o substituir.

EDIT:

Sugiro que use este script batch https://github.com/NabiKAZ/video2gif

4
4
4
2016-06-23 22:31:26 +0000

Abaixo está o ficheiro batch para utilizadores Windows:

gifenc.bat:

set start_time=0
set duration=60
set palette="c:\temp\palette.png"
set filters="fps=15,scale=-1:-1:flags=lanczos"
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -vf "%filters%,palettegen" -y %palette%
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -i %palette% -lavfi "%filters% [x]; [x][1:v] paletteuse" -y %2

Fonte: GIF de alta qualidade com FFmpeg: Extraindo apenas uma amostra

Se quiser usar apenas uma variável de entrada e ter o nome de saída tem apenas a extensão GIF (pronuncia-se JIF), então use esta:

set start_time=0
set duration=60
set palette="c:\temp\palette.png"
set filters="fps=15,scale=-1:-1:flags=lanczos"
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -vf "%filters%,palettegen" -y %palette%
set var1=%1
set var2=%var1:~0,-4%
ffmpeg -v warning -ss %start_time% -t %duration% -i %1 -i %palette% -lavfi "%filters% [x]; [x][1:v] paletteuse" -y %var2%.gif
3
3
3
2018-04-15 23:48:54 +0000

Como adicionar uma entrada no menu de contexto do windows 7/10 “clique com o botão direito do rato” para converter o seu ficheiro de vídeo para gif

Algumas das outras respostas mencionaram o script video2gif , que eu utilizei. Mas, pode usar qualquer script.

Para criar a opção de menu de contexto, precisa de editar o seu registo. Abra um prompt de comando powershell, rodando c/ admin privs. Execute estes comandos:

$key = "Registry::HKEY_CLASSES_ROOT# Como adicionar uma entrada no menu de contexto do windows 7/10 "clique com o botão direito do rato" para converter o seu ficheiro de vídeo para gif 

Algumas das outras respostas mencionaram o script [ video2gif ]&003, que eu utilizei. Mas, pode usar qualquer script. 

Para criar a opção de menu de contexto, precisa de editar o seu registo. Abra um prompt de comando powershell, rodando c/ admin privs. Execute estes comandos: 


*\shell\Run Video2Gif"
New-Item -Path $key"\Command" -Value "C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin\video2gif.bat `"%1`"" -Force

Agora quando clicar com o botão direito do rato num ficheiro terá a opção “Run Video2Gif”!

btw Instalei ffmpeg em `C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static# Como adicionar uma entrada no menu de contexto do windows 7/10 “clique com o botão direito do rato” para converter o seu ficheiro de vídeo para gif

Algumas das outras respostas mencionaram o script [ video2gif ]&003, que eu utilizei. Mas, pode usar qualquer script.

Para criar a opção de menu de contexto, precisa de editar o seu registo. Abra um prompt de comando powershell, rodando c/ admin privs. Execute estes comandos:

$key = "Registry::HKEY_CLASSES_ROOT# Como adicionar uma entrada no menu de contexto do windows 7/10 "clique com o botão direito do rato" para converter o seu ficheiro de vídeo para gif 

Algumas das outras respostas mencionaram o script [ video2gif ]&003, que eu utilizei. Mas, pode usar qualquer script. 

Para criar a opção de menu de contexto, precisa de editar o seu registo. Abra um prompt de comando powershell, rodando c/ admin privs. Execute estes comandos: 


*\shell\Run Video2Gif"
New-Item -Path $key"\Command" -Value "C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin\video2gif.bat `"%1`"" -Force

Agora quando clicar com o botão direito do rato num ficheiro terá a opção “Run Video2Gif”!

btw Instalei ffmpeg em e coloquei o script video2gif.bat no diretório bin dir mesmo ao lado de ffmpeg.exe. Também adicionei C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin ao meu windows PATH, mas acho que não é necessário.

Se quiser a opção de poder fornecer algumas bandeiras / args de linha de comando extra ao script, então faça um novo ficheiro com o nome video2gif-prompt.bat, e peça ao registo para o referir em vez de video2gif.bat:

@echo off
set /p inp=Enter extrta args, if desired:
C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin\video2gif.bat %* %inp%

Você ainda pode simplesmente carregar em enter para obter rapidamente as predefinições.