Convierta miles de .pngs a .gif animado, `convert` usa demasiada memoria

29

Muchas de las preguntas sobre cómo crear un gif animado a partir de un conjunto de imágenes png sugieren utilizar una variante del convertcomando ImageMagick :

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

Sin embargo, tengo algunos miles de imágenes y, por lo tanto, convertuso toda mi memoria, intercambio y luego se bloquea. ¿Qué software alternativo existe, que es más consciente de la memoria? Podría usar otro formato abierto si .gifno es compatible, y prefiero una herramienta CLI.

dotancohen
fuente
1
¿Qué tal dividir los archivos * .png en fragmentos manejables? Digamos que todos los nombres de archivo comienzan con un dígito, luego convert -delay 2 -loop 0 0*.png animated.gifconvertirán solo los archivos que comienzan con un '0'. Y así.
Jos
2
Entonces, ¿cada .png está en el orden de 1 Mb? En ese caso, todo lo que puedo pensar es convertir primero los archivos .png a una resolución o profundidad de color más baja, para hacerlos más pequeños.
Jos
10
Dices que podrías usar otro formato abierto. Me parece que gif no es exactamente el mejor formato para miles de cuadros. ¿Has considerado codificar un video con Ogg Theora?
rekado
1
Tal vez eche un vistazo a gifsicle , si realmente quiere usar GIF? (Aunque, como otros han dicho, esto no es lo que se hizo para el GIF; OGG sería una mejor opción.)
wchargin
1
Re. "donde va toda la memoria": 65 Kb es el tamaño de archivo de una imagen comprimida. Cuando se descomprime, la imagen toma aproximadamente 4 x ancho x alto bytes, por lo que una imagen de 1024x768 tomaría ~ 3Mb de RAM. Multiplique eso por "unos pocos miles" y verá a dónde va el recuerdo ...
Sergey

Respuestas:

33

Parece que estás intentando hacer un video. Si ese es el caso, entonces usaría un formato de video adecuado.

En este caso, usaría ffmpeg para convertir los archivos PNG individuales a un video H.264. Dado que ffmpeg está hecho para trabajar con videos que pueden durar horas, no debería tener ningún problema con sus miles de imágenes. El uso de H.264 en lugar de gif animados dará como resultado una gran mejora en la calidad de la imagen.

Algo como esto debería funcionar para usted:

 ffmpeg -framerate 1/2 -i img%04d.png -c:v libx264 -r 30 out.mp4
  • -framerate 1/2: Esto establece la velocidad de fotogramas a la mitad de FPS, o 2 segundos por fotograma.
  • -i img%04d.png: Sin img0000.pngembargo, esto le dice a ffmpeg que lea los archivos img9999.png.
  • -c:v libx264: Utilice el códec de video libx264.
    • Puede especificar los parámetros de compresión de video aquí, si lo desea:
    • -crf <number>: Configuración de calidad. 0 a 51. 23 es el valor predeterminado. 0 es una verdadera codificación sin pérdidas, que tendrá un ancho de banda bastante alto. 18 es casi sin pérdidas visuales.
  • -r 30: Establezca la velocidad de fotogramas de salida a 30 FPS. Cada una de las imágenes de entrada se duplicará para hacer que la salida sea lo que especifique aquí. Puede dejar este parámetro desactivado y el archivo de salida estará en la velocidad de fotogramas de entrada, pero la película resultante no se mostró correctamente cuando lo probé en este momento.
  • out.mp4: Nombre del archivo de salida.

Referencias

David Yaw
fuente
1
Agradable expansión de Frantique respuesta del día anterior.
Élder Geek
Aquí hay un punto de referencia simple de ffmpeg vs ImageMagick con datos de prueba concretos: askubuntu.com/questions/648244/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
11

Personalmente, lo lanzaría en un número limitado de archivos en lugar de todos a la vez. Por ejemplo, algo como esto:

#!/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
terdon
fuente
8

Use -limit memory 1GiBpara limitar la cantidad de convertusos de memoria .

Miles de imágenes crearían un gran GIF que la mayoría de las computadoras tendrán dificultades para mostrar. Mantengo mis GIF animados por debajo de 200 imágenes cuando es posible. Cuanto menos mejor. Si numera sus imágenes, este comando eliminará las imágenes impares rm *[13579].png.

Así que aquí está mi flujo de trabajo típico para crear un GIF animado de una escena de película:

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
PLA
fuente
1
Gracias, esa solución funciona bien. También puede ser necesario aumentar los límites de memoria permitidos en /etc/ImageMagick-6/policy.xml, consulte github.com/ImageMagick/ImageMagick/issues/… para obtener más información
Louis Gagnon
4

Podría usar otro formato abierto si .gifno es compatible

Quizás APNG te sea ​​útil. Es compatible con algunos navegadores , incluido Firefox, pero actualmente excluye Chrome e IE. Como es solo una extensión PNG, es muy simple convertir PNG a APNG. La herramienta de apngasm puede hacer eso. Pero el formato es tan simple que recientemente escribí un ensamblador APNG para Sage. Adaptar ese código sería una alternativa.

MvG
fuente
También me gustaría señalar que APNG no es estándar y, a pesar de haber existido durante 7 años, todavía es muy oscuro.
Pharap
Para una demostración científica, en la que puede elegir el navegador que se utiliza, esta podría ser una solución simple y sólida.
MvG
Depende de quién tiene que ver la demostración. No sería muy bueno entregar copias a los espectadores y luego dos tercios tienen que salir y descargar Firefox solo para verlo. No es el tipo de impresión que me gustaría dar si estuviera haciendo una demostración científica importante. Si solo está destinado a ser visto como parte de la demostración, entonces es lo suficientemente justo, pero puede no ser adecuado para otras situaciones.
Pharap
3

Si tiene miles de png-s, el formato anigif es extraño. Lo haría de esta manera, usando avconv:

 avconv -i "%d.png" -r 25 -c:v libx264 -crf 20 -pix_fmt yuv420p animated.mov
Frantique
fuente
Este enfoque tiene el beneficio adicional de que más tarde podría mux en voz en off o audio de música que es imposible con el formato de intercambio de gráficos.
Élder Geek
2

gifsicle es una utilidad de línea de comandos para manejar animaciones GIF. Si está dispuesto a cambiar la memoria por velocidad, puede usar su conmutador --conserve-memory.

cabeza de código
fuente
Permítanme decirlo de esta manera: gifsicle ya tiene una huella más pequeña que ImageMagick - si usted encuentra que todavía utiliza demasiada memoria para la tarea en cuestión, a continuación, puede utilizar la memoria --conserve-
codehead
Ohh, creo que leí mal lo que estabas diciendo, que el interruptor usaría más memoria, lo que no tiene mucho sentido. no importa.
curiousdannii
2

Además de otras respuestas: dado que desea producir un archivo GIF, supongo que desea mostrar la imagen en una página web. Si es así, no me molestaría en convertir sus PNG en absoluto. Simplemente busque en google "presentación de diapositivas de javascript" y use uno de los millones de scripts gratuitos. O escriba el suyo, esto es realmente trivial.

Los beneficios de hacerlo de esta manera son:

  • solo se carga una imagen en el navegador en cualquier momento, la presentación de diapositivas se inicia rápidamente y no consume mucha RAM en la máquina del usuario.

  • La solución se escala a millones de imágenes. O miles de millones, si eres lo suficientemente paciente como para verlos a todos :)

  • Puede agregar controles a su página para pausar, rebobinar, cambiar el retraso o ir a un cuadro en particular.

Sergey
fuente
Gracias Sergey De hecho, esto no es para mostrar en una página web. +1 para la idea, sin embargo.
dotancohen