271

Я конвертирую 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%

Благодарю.

12 ответов12

402

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 если хотите .

84

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

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 без оптимизации, чтобы быть уверенным.

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

31

Начиная с 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

15

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

Запуск ./gifenc.sh input.mov output.gif 720 10 выводит GIF с разрешением 10 кадров в секунду и шириной 720p из фильма, который вы ему дали. Возможно, вам придется выполнить 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 установлен, и скрипт находится в той же папке, что и другие файлы.

11

Ответ от @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
9

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

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

./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

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

8

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-файлы из видеофайлов.


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

7

ffmpeg с палитрой метод может работать в одной команде, без промежуточного файла .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 фильтру.

5

Выбранный ответ предполагает, что вы хотите масштабировать исходное видео и изменять его 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

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

4

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

Для пользователей 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

2

Как добавить пункт контекстного меню 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 в каталог bin рядом с ffmpeg.exe . Я также добавил C:\dev\ffmpeg\ffmpeg-3.4.2-win64-static\bin в мой PATH Windows, но я не думаю, что вам это нужно.

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .