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

Вопрос или проблема

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

GIF вывод из ffmpeg
183k

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

ffmpeg -ss 30 -t 3 -i input.mp4 \
    -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
    -loop 0 output.gif
  • Этот пример пропустит первые 30 секунд (-ss 30) входного файла и создаст выходной файл длиной 3 секунды (-t 3).
  • фильтр fps устанавливает частоту кадров. В примере используется скорость 10 кадров в секунду.
  • фильтр scale изменит размер выходного файла до 320 пикселей в ширину и автоматически определит высоту, сохраняя соотношение сторон. В этом примере используется алгоритм масштабирования lanczos scaling algorithm.
  • palettegen и paletteuse фильтры сгенерируют и используют пользовательскую палитру, созданную из вашего входного файла. У этих фильтров много опций, так что обратитесь к ссылкам для получения списка всех доступных опций и значений. Также смотрите раздел Расширенные опции ниже.
  • фильтр split позволит сделать все в одной команде и избегает необходимости создавать временный PNG файл палитры.
  • Управляйте зацикливанием с помощью опции -loop, но значения могут быть запутанными. Значение 0 означает бесконечное зацикливание, -1 означает отсутствие зацикливания, а 1 обратно зациклит один раз, что означает, что он будет воспроизводиться дважды. Поэтому значение 10 приведет к воспроизведению GIF 11 раз.

Расширенные опции

Фильтры palettegen и paletteuse имеют много дополнительных опций. Наиболее важные из них:

  • stats_mode (palettegen). Вы можете заставить фильтры сосредоточить палитру на общем изображении (full, что является значением по умолчанию), только на подвижных частях (diff) или на каждом отдельном кадре (single). Например, чтобы сгенерировать палитру для каждого отдельного кадра, используйте palettegen=stats_mode=single & paletteuse=new=1.

  • dither (paletteuse). Выберите алгоритм дотеризации. Есть три основных типа: детерминированный (bayer), диффузия ошибок (все остальные, включая значение по умолчанию sierra2_4a) и без дотеризации. Ваш GIF может выглядеть лучше, используя определенный алгоритм дотеризации или вообще без дотеризации. Если вы хотите попробовать bayer, обязательно протестируйте и опцию bayer_scale.

Смотрите Высококачественный GIF с FFmpeg для объяснений, примеры изображений и более подробной информации для продвинутого использования.

Также смотрите документацию palettegen и paletteuse для всех доступных опций и значений.


Пример ImageMagick convert

GIF вывод из ffmpeg
227k

Другой способ командной строки – это передать данные из ffmpeg в convert (или magick) из ImageMagick.

ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" -c:v pam \
    -f image2pipe - | \
    convert -delay 10 - -loop 0 -layers optimize output.gif

Опции ffmpeg:

  • -vf "fps=10,scale=320:-1:flags=lanczos" это filtergraph, использующий fps и scale фильтры. fps устанавливает частоту кадров в 10, а scale устанавливает размер на 320 пикселей вширь, высота автоматически определяется и использует значение, которое сохраняет соотношение сторон. В этом примере используется алгоритм масштабирования lanczos scaling algorithm.

  • -c:v pam выбирает кодировщик изображений pam. В примере выводится формат изображения PAM (Portable AnyMap), который является простым, безвредным RGB форматом, поддерживающим прозрачность (alpha) и поддерживаемым convert. Он быстрее для кодирования, чем PNG.

  • -f image2pipe выбирает мультиплексор image2pipe, потому что при выводе в системный канал ffmpeg должен сообщить, какой мультиплексор использовать.

Опции convert:

  • -delay См. раздел Установка частоты кадров ниже.

  • -loop 0 создает бесконечный цикл.

  • -layers optimize включит общий оптимизатор GIF. См. Оптимизация анимаций ImageMagick для получения более подробной информации. Не гарантируется, что он создаст меньший выходной файл, поэтому стоит попробовать и без -layers optimize и сравнить результаты.

Установка частоты кадров

Установите частоту кадров с помощью комбинации фильтра fps в ffmpeg и -delay в convert. Это может быть сложно, потому что convert просто получает необработанный поток изображений, поэтому никакая частота кадров не сохраняется. Во-вторых, значение -delay в convert выражается в тика (в одном секунде 100 тиков), а не в кадрах в секунду. Например, с fps=12.5 = 100/12.5 = 8 = -delay 8.

convert округляет значение -delay до целого числа, поэтому 8.4 дает 8, а 8.5 дает 9. Это фактически означает, что поддерживается только несколько частот кадров, когда устанавливается унифицированная задержка для всех кадров (можно установить конкретную задержку для каждого кадра, но это выходит за рамки данного ответа).

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

Наконец, браузеры и просмотрщики изображений могут реализовать минимальную задержку, поэтому ваша -delay также может быть проигнорирована.

Видео предоставлено Службой рыбы и дикой природы США, Национальный тренировочный центр сохранения.

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

ffmpeg -i input.flv -vf scale=320:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 10 -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 10 -loop 0 - gif:- | convert -layers Optimize - output.gif

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

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

Начиная с версии ffmpeg 2.6, мы можем даже добиться лучших результатов. Основываясь на Высококачественный GIF с FFmpeg:

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 создаст GIF шириной 720p и 10 fps из фильма, который вы предоставили. Возможно, вам нужно выполнить 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:

# Конвертировать видео в gif файл.
# Использование: video2gif video_file (масштаб) (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="https://superuser.com/questions/556029/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

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

Метод 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.

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

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

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

ПОЛУЧИТЕ УДОВОЛЬСТВИЕ 🙂

vim avi2gif.sh

#!/bin/sh

INPUT=$1

# настройки по умолчанию, измените если хотите.

START_AT_SECOND=0; # в секундах, если хотите пропустить первые 30 секунд, поставьте 30 здесь

LENGTH_OF_GIF_VIDEO=9999999; # в секундах, как долго должна быть анимация gif

echo "Генерация палитры:"
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 "Вывод GIF, используя палитру:"
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: создайте файл \Windows\video2gif.bat с этим содержимым:

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

Я предлагаю использовать этот универсальный пакетный скрипт.

Команды 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
    

Возможно, вам стоит настроить fps и scale. Меньший размер каждого приведет к лучшему размеру файла.

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

Вы также можете создать функцию псевдонима следующим образом. Я добавил это в свой .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 с правами администратора. Выполните следующие команды:

$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=Введите дополнительные аргументы, если хотите:
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

Мой простой трюк для конвертации в GIF – это фильтр NLmeans HandBrake/ffmpeg. В HandBrake просто отметьте опции NLMeans в вкладке конфигурации видео.

Это сглаживает грубое изображение GIF, делая его более сжимаемым. Выход выглядит лучше И имеет меньший размер.

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

ffmpeg -i input.mp4 output.gif

Простая функция Bash

Моя наиболее часто используемая командная оболочка в настоящее время

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

makeGif inputVideo.mp4

#DESC создать высококачественный gif из видео (особенно .mp4 или .mov)
makeGif () {
  if [ -z "$1" ]
  then
    echo "makeGif inputVideo [outputGif]"
    return 244
  fi
  vid="$1"

  if [ -z "$2" ]
  then
    # удалить расширение
    outputVideo="${vid%.*}.gif"
  else
    outputVideo="$2"
  fi

  ffmpeg -i "$vid" -vf "scale=1920:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=256[p];[s1][p]paletteuse=dither=floyd_steinberg" -loop 0 "$outputVideo"

  echo "GIF создан: $outputVideo"
}

Используя немного ответов каждого, вот bash скрипт с параметрами и только одной командой ffmpeg:

#!/bin/bash

# Значения по умолчанию
fps=15
scale=720

# Функция для отображения usage
usage() {
  echo "Использование: $0 [--fps <fps_value>] [--scale <scale_value>] <input_video.mp4>"
  echo "  --fps: Возможный. Установите кадры в секунду (по умолчанию: 15)"
  echo "  --scale: Возможный. Установите ширину вывода в пикселях (по умолчанию: 720)"
  exit 1
}

# Парсинг опциональных аргументов
while [[ "$#" -gt 0 ]]; do
  case "$1" in
  --fps)
    fps="$2"
    shift 2
    ;;
  --scale)
    scale="$2"
    shift 2
    ;;
  -*)
    echo "Неизвестный параметр: $1"
    usage
    ;;
  *)
    input_video="$1"
    shift
    ;;
  esac
done

# Проверьте, была ли предоставлена входная часть и оканчивается ли она на .mp4
if [[ -z "$input_video" || ! "$input_video" =~ \.mp4$ ]]; then
  echo "Ошибка: файл ввода должен быть указан и иметь расширение .mp4"
  usage
fi

# Имя выходного GIF файла
output_gif="${input_video%.mp4}.gif"

# Создаем GIF в одной команде с использованием split для палитры
echo "Создание GIF с fps=$fps и scale=$scale"
ffmpeg -i "$input_video" -vf "fps=$fps,scale=${scale}:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" "$output_gif"

echo "Конвертация завершена: $output_gif (fps=$fps, scale=$scale)"

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

mp4togif --fps 10 --scale 720 myvideo.mp4

–fps: Возможный. Установите кадры в секунду (по умолчанию: 15)
–scale: Возможный. Установите ширину вывода в пикселях (по умолчанию: 720)

Ответ или решение

Для конвертации видео в GIF с помощью ffmpeg с высоким качеством, существует несколько методов, оптимизирующих конечный результат. Основная цель состоит в том, чтобы минимизировать потери качества при преобразовании, и в этом помогут фильтры для генерации палитры.

Шаги для конвертации видео в GIF при помощи ffmpeg

  1. Подготовка: Убедитесь, что у вас установлена последняя версия ffmpeg. Это важно, так как в новых версиях исправлены ошибки и улучшены алгоритмы.

  2. Формат команд: Используем команду, которая включает фильтры для генерации палитры и применения её к выходному GIF.

Простой метод с использованием двух команд

Создайте палитру и примените её к видео. Например, если у вас есть файл input.mp4, вы можете использовать следующие команды:

# Генерация палитры
ffmpeg -i input.mp4 -vf "fps=15,scale=320:-1:flags=lanczos,palettegen" -y palette.png

# Применение палитры для создания GIF
ffmpeg -i input.mp4 -i palette.png -lavfi "fps=15,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" output.gif

Оптимизированный метод с использованием одного вызова

Вы также можете подсоединить оба процесса в одну команду, чтобы избежать создания временных файлов:

ffmpeg -i input.mp4 -filter_complex "fps=15,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -y output.gif

Объяснение параметров

  • fps=15: Устанавливает частоту кадров GIF в 15 кадров в секунду. Вы можете увеличить это значение для более плавного GIF, но и размер файла вырастет.
  • scale=320:-1: Устанавливает ширину в 320 пикселей, а высоту автоматически. Это позволяет сохранить соотношение сторон.
  • flags=lanczos: Указывает, что следует использовать метод Lanczos для изменения размера изображения. Этот алгоритм обеспечивает повышенное качество при интерполяции.
  • palettegen и paletteuse: Создают и используют палитру, что улучшает качество по сравнению с использованием стандартных параметров.

Дополнительные параметры для улучшения качества

  • Вы можете регулировать количество цветов в палитре с помощью параметра max_colors=256 (по умолчанию стоит 256), чем меньше цветов — тем меньше размер файла, но это может снизить качество.
  • Используйте алгоритмы дибинга при применении палитры, например, dither=floyd_steinberg, чтобы улучшить визуальное восприятие GIF.

Пример скрипта для автоматизации

Вы также можете создать Bash-скрипт для более удобного использования:

#!/bin/bash
input=$1
output="${input%.*}.gif"

ffmpeg -i "$input" -vf "fps=15,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" "$output"
echo "GIF создан: $output"

Сохраните этот код как convert_to_gif.sh, дайте ему права на выполнение и запускайте, указывая имя видео в качестве аргумента.

Заключение

Используя метод генерации палитры, вы сможете создать GIF с высоким качеством без значительных потерь. Экспериментируйте с настройками частоты кадров и разрешения для достижения наилучших результатов. Не забывайте, что размер конечного файла будет зависеть от выбранных вами параметров, так что выбирайте с умом.

Оцените материал
Добавить комментарий

Капча загружается...