Converta milhares de .pngs em .gif animado, `convert` usa muita memória


29

Muitas das perguntas sobre como criar um gif animado a partir de um conjunto de imagens png sugerem o uso de uma variante do convertcomando ImageMagick :

convert -delay 2 -loop 0 *.png animated.gif

No entanto, tenho alguns milhares de imagens e, portanto, convertconsome toda a minha memória, troca e depois trava. Que software alternativo existe, que é mais consciente da memória? Eu poderia usar outro formato aberto se .gifnão for suportado e prefiro uma ferramenta CLI.


1
Que tal dividir os arquivos * .png em partes gerenciáveis? Digamos que todos os nomes de arquivos começam com um dígito e depois convert -delay 2 -loop 0 0*.png animated.gifconvertem apenas os arquivos que começam com um '0'. E assim por diante.
21415 Jos Jos

2
Então cada arquivo .png está na ordem de 1 Mb? Nesse caso, tudo o que consigo pensar é primeiro converter os arquivos .png em uma resolução ou profundidade de cores mais baixa, para torná-los menores.
21415 Jos Jos

10
Você diz que poderia usar outro formato aberto. Parece-me que gif não é exatamente o melhor formato para milhares de quadros. Você já pensou em codificar um vídeo com Ogg Theora?
rekado

1
Talvez dê uma olhada no gifsicle , se você realmente deseja usar o GIF? (Embora, como já foi dito, este não é o GIF foi feito para, OGG seria uma escolha melhor.)
wchargin

1
Ré. "para onde está indo toda a memória": 65 Kb é o tamanho do arquivo de uma imagem compactada. Quando descompactada, a imagem ocupa aproximadamente 4 x largura x altura bytes; portanto, uma imagem de 1024x768 levaria aproximadamente 3 MB de RAM. Multiplique isso por "alguns milhares" e você verá onde a memória está indo ...
Sergey

Respostas:


33

Parece que você está tentando fazer um vídeo. Se for esse o caso, eu usaria um formato de vídeo adequado.

Nesse caso, eu usaria o ffmpeg para converter os arquivos PNG individuais em um vídeo H.264. Como o ffmpeg é feito para trabalhar com vídeos que podem durar horas, não deve haver nenhum problema com milhares de imagens. Usar H.264 em vez de gif animado resultará em uma grande melhoria na qualidade da imagem.

Algo assim deve funcionar para você:

 ffmpeg -framerate 1/2 -i img%04d.png -c:v libx264 -r 30 out.mp4
  • -framerate 1/2: Define a taxa de quadros para metade do FPS ou 2 segundos por quadro.
  • -i img%04d.png: Isto diz ffmpeg para ler os arquivos img0000.pngembora img9999.png.
  • -c:v libx264: Use o codec de vídeo libx264.
    • Você pode especificar os parâmetros de compactação de vídeo aqui, se desejar:
    • -crf <number>: Configuração de qualidade. 0 a 51. 23 é o padrão. 0 é uma codificação sem perdas verdadeira, que terá uma largura de banda bastante alta. 18 é quase visualmente sem perdas.
  • -r 30: Defina a taxa de quadros de saída para 30 FPS. Cada uma das imagens de entrada será duplicada para tornar a saída o que você especificar aqui. Você pode deixar esse parâmetro desativado e o arquivo de saída estará na taxa de quadros de entrada, mas o filme resultante não foi exibido corretamente quando eu tentei agora.
  • out.mp4: Nome do arquivo de saída.

Referências:


1
Boa expansão da resposta de Frantique do dia anterior.
Elder Geek

Aqui está um simples benchmark ffmpeg vs ImageMagick com dados de teste concretos: askubuntu.com/questions/648244/…
Ciro Santilli escreveu:

11

Pessoalmente, eu o lançaria em um número limitado de arquivos em vez de todos de uma vez. Por exemplo, algo como isto:

#!/usr/bin/env bash

## Collect all png files in the files array
files=( *png )
## How many should be done at once
batch=50

## Read the array in batches of $batch
for (( i=0; $i<${#files[@]}; i+=$batch ))
do
    ## Convert this batch
    convert -delay 2 -loop 0 "${files[@]:$i:$batch}" animated.$i.gif
done

## Now, merge them into a single file
convert  animated.*.gif all.gif

8

Use -limit memory 1GiBpara limitar a quantidade de memória convertutilizada.

Milhares de imagens criariam um GIF enorme que a maioria dos computadores terá dificuldade em exibir. Eu mantenho meus GIFs animados abaixo de 200 imagens, quando possível. Quanto menos, melhor. Se você numerar suas imagens, esse comando excluirá as imagens numeradas ímpares rm *[13579].png.

Então, aqui está o meu fluxo de trabalho típico para criar um GIF animado a partir de uma cena de filme:

avconv -ss 00:26:00 -i someMovie.mpg %5d.png
rm  *[13579].png
convert -limit memory 1GiB -loop 0 -layers optimize -resize 400 *.png output.gif

1
Obrigado, essa solução funciona bem. Também pode ser necessário aumentar os limites de memória permitidos em /etc/ImageMagick-6/policy.xml, consulte github.com/ImageMagick/ImageMagick/issues/… para obter mais informações
Louis Gagnon

4

Eu poderia usar outro formato aberto se .gifnão for suportado

Talvez o APNG seja útil para você. É suportado por alguns navegadores , incluindo Firefox, mas no momento excluindo Chrome e IE. Como é apenas uma extensão PNG, é muito simples converter PNGs em APNG. A ferramenta apngasm pode fazer isso. Mas o formato é tão simples que recentemente escrevi um montador de APNG para o Sage. Adaptar esse código seria uma alternativa.


Eu também gostaria de salientar que o APNG não é padrão e, apesar de existir há 7 anos, ainda é muito obscuro.
Pharap

Para uma demonstração científica, na qual você pode escolher o navegador usado, isso ainda pode ser uma solução simples e robusta.
MvG 15/01

Depende de quem tem que ver a demonstração. Não seria muito bom entregar cópias para os espectadores e, em seguida, dois terços precisam sair e baixar o Firefox apenas para visualizá-lo. Não é o tipo de impressão que gostaria de causar se estivesse fazendo uma demonstração científica importante. Se o objetivo é apenas ser visto como parte da demonstração, é justo o suficiente, mas pode não ser adequado para outras situações.
Pharap

3

Se você possui milhares de png-s, o formato anigif é estranho. Eu faria dessa maneira, usando avconv:

 avconv -i "%d.png" -r 25 -c:v libx264 -crf 20 -pix_fmt yuv420p animated.mov

Essa abordagem tem o benefício adicional de que você poderá posteriormente mixar áudio de voz ou música, o que é impossível com o Graphics Interchange Format.
Elder Geek

2

gifsicle é um utilitário de linha de comando para lidar com animações GIF. Se você estiver disposto a trocar memória por velocidade, poderá usar a opção --conserve-memory.


Deixe-me colocar desta forma: gifsicle já tem uma pegada menor do que ImageMagick - se você achar que ele ainda usa muita memória para a tarefa em mãos, em seguida, você pode usar --conserve-memory
codehead

Ah, acho que interpretei mal o que você estava dizendo, que o comutador usaria mais memória, o que não faz muito sentido. deixa pra lá.
precisa saber é o seguinte

2

Além de outras respostas: como você deseja produzir um arquivo GIF, suponho que você queira exibir a imagem em uma página da web. Nesse caso, eu não me incomodaria em converter seus PNGs. Basta pesquisar no Google por "apresentação de slides em javascript" e usar um dos milhões de scripts gratuitos. Ou escreva você mesmo, isso é realmente trivial.

Os benefícios de fazê-lo desta maneira são:

  • apenas uma imagem é carregada no navegador a qualquer momento, a apresentação de slides inicia rapidamente e não consome muita RAM na máquina do usuário.

  • a solução é dimensionada para milhões de imagens. Ou bilhões, se você for paciente o suficiente para assistir a todos :)

  • Você pode adicionar controles à sua página para pausar, retroceder, alterar o atraso ou ir para um quadro específico.


Obrigado Sergey. Na verdade, isso não é para exibição em uma página da web. 1 para a ideia, no entanto.
dotancohen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.