Как мне конвертировать видео в 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
пример
203K
Этот пример пропустит первые 30 секунд ввода и создаст 3 секунды вывода. Он масштабирует выходные данные до 320 пикселей в ширину и автоматически определяет высоту, сохраняя соотношение сторон. palettegen
а также paletteuse
фильтры будут генерировать и использовать пользовательскую палитру, созданную из вашего источника.
Создайте палитру:
ffmpeg -y -ss 30 -t 3 -i input.flv \ -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png
Выведите 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).
246k
Экспорт кадров:
mkdir frames ffmpeg -i input -vf scale=320:-1:flags=lanczos,fps=10 frames/ffout%03d.png
Тогда используйте
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
Ответ от @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:
Запустите эту команду, чтобы ffmpeg смог найти хорошую палитру:
ffmpeg -y -i foo.mp4 -vf fps=30,scale=320:-1:flags=lanczos,palettegen palette.png
Выполните эту команду, чтобы преобразовать файл 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