Как мне конвертировать видео в GIF с использованием ffmpeg с приемлемым качеством?

Я конвертирую FLV фильм в GIF файл с ffmpeg.

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

Это прекрасно работает, но выходной GIF-файл имеет очень низкое качество.

Любые идеи, как я могу улучшить качество конвертированного GIF?

Вывод команды:

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%

Благодарю.

15 ответов

Решение

ffmpeg Теперь можно выводить более качественный GIF. Если вы используете более старую сборку, рассмотрите возможность загрузки последней статической сборки или компиляции ffmpeg,

ffmpeg пример

GIF с ffmpeg
203K

Этот пример пропустит первые 30 секунд ввода и создаст 3 секунды вывода. Он масштабирует выходные данные до 320 пикселей в ширину и автоматически определяет высоту, сохраняя соотношение сторон. palettegen а также paletteuse фильтры будут генерировать и использовать пользовательскую палитру, созданную из вашего источника.

  1. Создайте палитру:

    ffmpeg -y -ss 30 -t 3 -i input.flv \
    -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
    
  2. Выведите GIF, используя палитру:

    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
    

Посмотрите Высокое качество GIF с FFmpeg для многих других примеров и опций.


convert пример

Другой метод командной строки - экспортировать фильм в кадры, используя ffmpeg затем сделайте GIF с convert из ImageMagick (или GraphicsMagick).

ffmpeg и конвертировать
246k

  1. Экспорт кадров:

     mkdir frames
     ffmpeg -i input -vf scale=320:-1:flags=lanczos,fps=10 frames/ffout%03d.png
    
  2. Тогда используйте convert (или же gm convert если вы предпочитаете GraphicsMagick), чтобы сделать анимированный GIF:

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

С convert Вы можете контролировать задержку между кадрами с -delay при желании

Если вы предпочитаете избегать промежуточных файлов изображений, команды, предоставляемые LordNeckBeard, могут передаваться между ffmpeg и ImageMagick's convert так что никаких промежуточных файлов не требуется:

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

-f image2pipe говорит ffmpeg разделить видео на изображения и сделать его пригодным для распространения, и -vcodec ppm указывает формат вывода ppm (по какой-то причине, если формат png, либо convert не читает все изображения из канала, или ffmpeg не выводит их все). - для обеих команд указывает, что канал будет использоваться для вывода и ввода соответственно.

Чтобы оптимизировать результат без сохранения файла, вы можете передать вывод из convert с точностью до секунды 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

gif:- говорит convert передать свой вывод в виде данных в формате GIF и -layers Optimize говорит второй convert выполнять optimize-frame а также optimize-transparancy методы (см. Введение в ImageMagick по оптимизации анимации). Обратите внимание, что выход из -layers Optimize может не всегда обеспечивать меньший размер файла, поэтому вы можете попробовать сначала преобразовать его в gif без оптимизации, чтобы быть уверенным.

Помните, что в течение всего этого процесса все находится в памяти, поэтому вам может понадобиться достаточно памяти, если изображения достаточно велики.

Начиная с ffmpeg 2.6, мы можем сделать еще лучше:

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

Ответ от @Stephane очень хороший. Но он получит предупреждение, как Buffer queue overflow, dropping. для некоторого видео, и сгенерированный gif выпал какой-то кадр

Вот лучшая версия с fifo фильтр, чтобы избежать Buffer queue overflow когда используешь paletteuse фильтр. Используя split Фильтр, чтобы избежать создания промежуточной палитры 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

Я сделал собственную версию скрипта, которая также параметрирует выходное разрешение и частоту кадров.

Бег ./gifenc.sh input.mov output.gif 720 10 будет выводить 720p шириной 10 GPS GIF из фильма, который вы дали. Возможно, вам придется сделать chmod +x gifenc.sh для файла.

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

Вы можете прочитать подробности на моем Github

Предположения: ffmpeg установлен, и скрипт находится в той же папке, что и другие файлы.

Linux/Unix/ MacOS

Следуя @LordNeckbeard подход с ffmpeg Команда, пожалуйста, найдите следующую полезную функцию Bash, которая может быть добавлена ​​в ваш ~/.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"
}

После загрузки функции (вручную или из . ~/.bash_profile), вы должны иметь новый video2gif команда.

Пример использования:

video2gif input.flv

или же:

video2gif input.flv 320 10

Масштаб до 320 с шириной 10 кадров в секунду.

Вы также можете указать другой формат видео (например, mp4).


Macos

Вы можете попробовать приложение GIF Brewery, которое может создавать GIF-файлы из видеофайлов.


В качестве альтернативы есть несколько сайтов, которые делают онлайн-конвертацию бесплатно.

Выбранный ответ предполагает, что вы хотите масштабировать исходное видео и изменять его fps в произведенном gif. Если вам не нужно это делать, работает следующее:

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

Это пригодилось, когда я хотел подарить подарок, который точно воссоздает исходное видео, которое я использовал.

ffmpeg с помощью метода palette можно запустить в одной команде, без посредников .png файл.

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

Это можно сделать благодаря split фильтр.

Сделал скрипт, протестировал и работает.

использование:

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

ИМЕЙТЕ ФАН:)

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

кстати: vokoscreen - ОТЛИЧНЫЙ инструмент для захвата экрана для Linux:)

СПАСИБО МНОГО Майкл Кохаупт:) Рок устойчиво.

некоторая статистика по размеру файла:

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

увидеть результаты здесь.

Для пользователей Windows:
Создайте video2gif.bat файл в каталоге Windows с этим содержанием:

@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

И тогда везде, где вы можете использовать это, как этот пример:

video2gif myvideo.mp4

Тогда у вас есть myvideo.gif в текущем каталоге.
Если myvideo.gif существует, вопрос от вас, чтобы перезаписать его.

РЕДАКТИРОВАТЬ:

Я предлагаю использовать этот пакетный скрипт: https://github.com/NabiKAZ/video2gif

Команды ffmpeg:

  1. Запустите эту команду, чтобы ffmpeg смог найти хорошую палитру:

    ffmpeg -y -i foo.mp4 -vf fps=30,scale=320:-1:flags=lanczos,palettegen palette.png
    
  2. Выполните эту команду, чтобы преобразовать файл mp4 в gif:

    ffmpeg -y -i foo.mp4 -i palette.png -filter_complex "fps=30,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" foo.gif
    

Возможно, вы захотите настроить частоту кадров и масштаб. Чем меньше размер, тем лучше размер файла.

Создание простой функции псевдонима

Вы также можете создать подобную функцию псевдонима. Я добавил это в свой .bashrc или же .bash_profile:

function makegif {
  ffmpeg -y -i $1 -vf fps=30,scale=320:-1:flags=lanczos,palettegen palette.png
  ffmpeg -y -i $1 -i palette.png -filter_complex "fps=30,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" $1.gif
}

А потом просто makegif foo

Примечание. Конечно, вам понадобится ffmpeg. Скачайте здесь https://www.ffmpeg.org/download.html или brew install ffmpeg

Как добавить пункт контекстного меню Windows 7/10 "щелкнуть правой кнопкой мыши", чтобы преобразовать ваш видеофайл в GIF

В некоторых других ответах упоминался скрипт video2gif, который я использовал. Но вы можете использовать любой скрипт.

Чтобы создать опцию контекстного меню, вам нужно отредактировать ваш реестр. Откройте командную строку powershell, запустив w / admin privs. Выполните эти команды:

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

Теперь, когда вы щелкнете правой кнопкой мыши по файлу, у вас будет опция "Запустить Video2Gif"!

кстати я установил ffmpeg в C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\ и положить video2gif.bat Сценарий в мусорном ведре прямо рядом с ffmpeg.exe, Я также добавил C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin к моим окнам PATH, но я не думаю, что вам нужно.

Если вы хотите иметь возможность предоставлять некоторые дополнительные флаги / аргументы командной строки для скрипта, то создайте новый файл с именем video2gif-prompt.batи сделать так, чтобы реестр ссылался на него вместо 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%

Вы все еще можете просто нажать Enter, чтобы быстро получить значения по умолчанию.

Ниже приведен пакетный файл для пользователей 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

Источник: высококачественный GIF с FFmpeg: извлечение только образца

Если вы просто хотите использовать одну входную переменную и иметь имя выхода, имеющее только расширение GIF (произносится JIF), используйте вместо этого:

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

ImageMagick может сделать это просто:

      convert in.mp4 out.gif

Ты можешь сделать:

      ffmpeg -i input.mp4 output.gif
Другие вопросы по тегам