Pregunta ¿Cómo convierto un video a GIF usando ffmpeg, con una calidad razonable?


Estoy convirtiendo .flv película a .gif archivo con 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 muy bien, pero el archivo de salida GIF tiene una calidad muy baja.

¿Alguna idea de cómo puedo mejorar la calidad del gif convertido?

Salida de comando:

ffmpeg -i input.flv -ss 00:00:00.000 -pix_fmt rgb24 -r 10 -s 320x240 -t 00:00:10.000  output.gif
ffmpeg version 0.8.5-6:0.8.5-0ubuntu0.12.10.1, Copyright (c) 2000-2012 the Libav developers
  built on Jan 24 2013 14:52:53 with gcc 4.7.2
*** THIS PROGRAM IS DEPRECATED ***
This program is only provided for compatibility and will be removed in a future release. Please use avconv instead.
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.flv':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2013-02-14 04:00:07
  Duration: 00:00:18.85, start: 0.000000, bitrate: 3098 kb/s
    Stream #0.0(und): Video: h264 (High), yuv420p, 1280x720, 2905 kb/s, 25 fps, 25 tbr, 50 tbn, 50 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
    Stream #0.1(und): Audio: aac, 44100 Hz, stereo, s16, 192 kb/s
    Metadata:
      creation_time   : 2013-02-14 04:00:07
[buffer @ 0x92a8ea0] w:1280 h:720 pixfmt:yuv420p
[scale @ 0x9215100] w:1280 h:720 fmt:yuv420p -> w:320 h:240 fmt:rgb24 flags:0x4
Output #0, gif, to 'output.gif':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2013-02-14 04:00:07
    encoder         : Lavf53.21.1
    Stream #0.0(und): Video: rawvideo, rgb24, 320x240, q=2-31, 200 kb/s, 90k tbn, 10 tbc
    Metadata:
      creation_time   : 1970-01-01 00:00:00
Stream mapping:
  Stream #0.0 -> #0.0
Press ctrl-c to stop encoding
frame=  101 fps= 32 q=0.0 Lsize=    8686kB time=10.10 bitrate=7045.0kbits/s dup=0 drop=149    
video:22725kB audio:0kB global headers:0kB muxing overhead -61.778676%

Gracias.


247


origen




Respuestas:


ffmpeg ahora puede producir un GIF de mayor calidad. Si está utilizando una versión anterior, considere descargando una construcción estática reciente o compilando ffmpeg.

ffmpeg ejemplo

gif with ffmpeg
203k

Este ejemplo omitirá los primeros 30 segundos de la entrada y creará una salida de 3 segundos. Escalará la salida a 320 píxeles de ancho y determinará automáticamente la altura conservando la relación de aspecto. los palettegen y paletteuse los filtros generarán y usarán una paleta personalizada generada a partir de su fuente.

  1. Genera una paleta

    ffmpeg -y -ss 30 -t 3 -i input.flv \
    -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
    
  2. Envía el GIF usando la paleta:

    ffmpeg -ss 30 -t 3 -i input.flv -i palette.png -filter_complex \
    "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" output.gif
    

Ver GIF de alta calidad con FFmpeg para muchos más ejemplos y opciones.


convert ejemplo

Otro método de línea de comando sería exportar la película a marcos usando ffmpeg luego haz el GIF con convert de ImageMagick (o GraphicsMagick).

ffmpeg and convert
246k

  1. Marcos de exportación:

     mkdir frames
     ffmpeg -i input -vf scale=320:-1:flags=lanczos,fps=10 frames/ffout%03d.png
    
  2. Entonces usa convert (o gm convert si prefieres GraphicsMagick) para hacer tu GIF animado:

     convert -loop 0 frames/ffout*.png output.gif
    

Con convert puede controlar la demora entre cuadros con -delay Si es deseado.


374



Se agregaron algunos ejemplos de resultados (sin embargo, solo cuadros). Aquí, el primer archivo es 4.1 MB, el segundo alrededor de 8 MB. - slhck
@LordNeckbeard, eres increíble! muchas gracias por -vf scale=320:-1,format=rgb8,format=rgb24 - Kamil Hismatullin
Por cierto, para el convert comando para la conversión de los marcos PNG que terminé usando convert -delay 5 -loop 0 -dither None -colors 80 "frames/ffout*.png" -fuzz "40%" -layers OptimizeFrame "output.gif", lo que reduce un poco el tamaño general del archivo - Wilf
Pienso que el convert comando debe estar usando -delay 10 (0.1 segundos entre fotogramas) para que coincida con -r 10 Velocidad de fotogramas (10 fps) a la que alimentas ffmpeg. Cuando uso -delay 5, Veo que el gif juega a doble velocidad. - Jack O'Connor
De acuerdo, lo tengo, lo usé scale=0:-1, entonces cuando configura la escala 0, tomará la escala del video. - Mousa Alfhaily


Si prefiere evitar los archivos de imagen intermedios, los comandos proporcionados por LordNeckBeard se pueden canalizar entre ffmpeg y ImageMagick's convert para que no se requieran archivos intermedios:

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

los -f image2pipe le dice a ffmpeg que divida el video en imágenes y lo haga adecuado para ser canalizado, y -vcodec ppm especifica que el formato de salida sea ppm (por alguna razón, si el formato es png, convert no lee todas las imágenes de la tubería, o ffmpeg no las emite todas). los - para ambos comandos especifica que se usará una tubería para la salida y la entrada, respectivamente.

Para optimizar el resultado sin guardar un archivo, puede canalizar el resultado de convert a un segundo convert mando:

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

los gif:- dice convert para canalizar su salida como datos formateados gif y -layers Optimize dice el segundo convert actuar optimize-frame y optimize-transparancy métodos (ver ImageMagick Introducción a la optimización de la animación) Tenga en cuenta que la salida de -layers Optimize es posible que no siempre proporcione un tamaño de archivo más pequeño, por lo que es posible que primero desee intentar convertirlo a un archivo .gif sin optimización.

Recuerde que durante todo este proceso, todo está en la memoria, por lo que puede necesitar suficiente memoria si las imágenes son bastante grandes.


79



Este conjunto de comandos también funciona con avconv - raphael
Debería unir los últimos dos comandos de conversión: convert -delay 5 -loop 0 -layers Optimize - output.gif - Clément
¿Parece que el archivo gif se ejecuta a 2 veces la velocidad del video original? - Titan
@Titan cree que es el -r 10 en el primer comando y el -delay 5 en el segundo. Cambié el retraso a 10 también y parece jugar normalmente ahora. - Steven Huang
También puede evitar archivos de imagen intermedios utilizando el split filtrar en ffmpeg. No hay necesidad de canalizar nada en absoluto: ffmpeg -ss 30 -t 3 -i "input.flv fps=10,scale=320:-1:flags=lanczos,split[x][z];[z]palettegen[y];[x][y]paletteuse" output.gif - Ajedi32


A partir de ffmpeg 2.6, podemos hacerlo aún mejor:

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 


29





Hice mi propia versión del script, que también parametriza la resolución de salida y la velocidad de fotogramas.

Corriendo ./gifenc.sh input.mov output.gif 720 10 dará salida a 720p de ancho a 10 fps GIF de la película que le diste. Es posible que tengas que hacer chmod +x gifenc.sh para el archivo.

#!/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"

Puedes leer los detalles en mi Github

Suposiciones: ffmpeg está instalado, y la secuencia de comandos está en la misma carpeta que los otros archivos.


13



Muchas gracias por tu guion. ¡Acabo de probarlo y funciona genial! - orschiro


hizo un guión, probado y funciona.

uso:

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

TENER 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

por cierto: vokoscreen es una EXCELENTE herramienta ScreenCapturing para Linux :)

MUCHAS GRACIAS Michael Kohaupt :) Rock estable.

algunas estadísticas de tamaño de archivo:

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

ver el resultados aquí.


7





La respuesta de @Stephane es muy buena. Pero recibirá una advertencia como Buffer queue overflow, dropping. para algunos videos, y los generados gif tiene un cuadro caído

Aquí hay una mejor versión con fifo filtro para evitar Buffer queue overflow cuando usas paletteuse filtrar. Mediante el uso split filtrar para evitar la creación del archivo PNG de la paleta intermedia.

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

7





Linux / Unix / macOS

Siguiendo Enfoque @LordNeckbeard con ffmpeg comando, encuentre la siguiente función Bash útil que se puede agregar a su ~/bash_profile archivo:

# 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"
}

Una vez que se carga el archivo (. ~/.bash_profile), deberías tener nuevos video2gif mando.

Ejemplo de uso:

video2gif input.flv

o:

video2gif input.flv 320 10

Escala a 320 de ancho con 10 cuadros por segundo.

También puede especificar un formato de video diferente (como mp4).


Mac OS

Puedes probar GIF Brewery aplicación que puede crear GIF a partir de archivos de video.


Alternativamente, hay varios sitios web que están realizando conversiones en línea de forma gratuita.


6



Tangencial / offtopic: para cualquiera que se pregunte por qué Community editó esto, fue para HTTPSify el enlace en la primera línea de la respuesta. (¡La transición de HTTPS de Stack Overflow está en marcha!) - i336_


los ffmpeg con paleta método se puede ejecutar en un solo comando, sin intermediarios .png archivo.

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

Esto se puede hacer gracias a la split filtrar.


6