Как создать анимированный GIF-файл из видео MP4 с помощью командной строки?

Я хочу сделать анимированный .gif от одного .mp4 видео. Я бы предпочел сделать это из командной строки, поэтому, пожалуйста, перечислите только инструменты командной строки.

ffmpeg 3.4.4 может сделать это непосредственно в Ubuntu 18.04

Вероятно, вы захотите использовать что-то вроде:

sudo apt install ffmpegwget -O opengl-rotating-triangle.mp4 https://github.com/cirosantilli/media/blob/master/opengl-rotating-triangle.mp4?raw=trueffmpeg \  -i opengl-rotating-triangle.mp4 \  -r 15 \  -vf scale=512:-1 \  -ss 00:00:03 -to 00:00:06 \  opengl-rotating-triangle.gif

opengl-rotating-triangle.gif

enter image description here

Информация об изображении: 426 КБ, 45 кадров, видимый размер 512x512, слились воедино, время преобразования на Lenovo P51: 0,5с.

Вышеупомянутое преобразование также сработало после ulimit -Sv 1000000 (Использование DRAM ограничено 1 ГБ), поэтому он "не потребляет огромные объемы памяти", как предыдущие попытки, которые я делал с Imagemagick, которые чуть не убили мою машину. 500 МБ, однако, не удалось, потому что ffmpeg не удалось загрузить свои общие библиотеки ... время обновить оперативную память ;-)?

Процедура генерации тестовых данных описано в этом посте.

Выходные данные имеют видимый шаблон расставления точек, который не так виден в приведенном ниже методе "ffmpeg + convert". Мы можем попытаться улучшить качество изображения с помощью методов, описанных в:

Например, используя palettegen фильтр:

ffmpeg \  -i opengl-rotating-triangle.mp4 \  -r 15 \  -vf "scale=512:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \  -ss 00:00:03 -to 00:00:06 \  opengl-rotating-triangle-palettegen.gif

opengl-rotating-triangle-palettegen.gif

enter image description here

Информация об изображении: 979K, 45 кадров, видимый размер 512x512, слились воедино, время преобразования на Lenovo P51: 3,5с.

Итак, мы видим, что:

  • точечный узор теперь гораздо менее заметен
  • Размер GIF-файла примерно удвоился. ЗАДАЧА: почему простой выбор палитры увеличивает размер изображения? Это потому, что теперь больше цветов, поэтому нам нужно больше битов на цвет? Как наблюдать за каждой палитрой?
  • время генерации было в 7 раз медленнее, вероятно, потому, что ffmpeg сначала просматривает все видео, чтобы определить оптимальную палитру

Мы могли бы также поиграть с задокументированными palettegen параметры, такие как palettegen=max_colors=16 для достижения компромиссов между различными размерами и качеством.

Разбивка аргументов

  • -ss 00:00:03 -to 00:00:06: время начала и окончания для вырезания видео.

    Нет, GIF-файлы - не лучший способ пират распространяйте видео в Интернете.

    Смотрите также: https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg

  • -vf scale=512:-1: сделайте вывод 512 пикселей по высоте и отрегулируйте ширину, чтобы сохранить соотношение сторон.

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

    Если вы уберете этот параметр, выходной GIF-файл будет иметь ту же высоту, что и входное видео.

    Исходную высоту видео можно найти, например, с помощью ffprobe: https://superuser.com/questions/595177/how-to-retrieve-video-file-information-from-command-line-under-linux/1035178#1035178 и в нашем случае это 1024 x 1024.

  • -r 15: выборка кадров в секунду.

    Например, исходное видео было 30 кадров в секунду, так что -r 15 означает, что ffmpeg будет выбирать один кадр из каждых 2 (= 30 / 15).

    Однако воспринимаемый выходной FPS настраивается в соответствии с входным, так что вы не заметите ускорения, только большую детализацию.

    Входной FPS можно найти с помощью ffprobe, а общее количество входных кадров можно найти с помощью mediainfo как объяснено в: https://superuser.com/questions/84631/how-do-i-get-the-number-of-frames-in-a-video-on-the-linux-command-line/1044894#1044894

    Я рекомендую этот вариант, потому что видеоформаты обычно имеют более высокую частоту кадров из-за большего разрешения. При меньших GIF-файлах меньшая частота кадров менее заметна, и поэтому мы можем пропустить некоторые кадры и сделать GIF-файлы меньшего размера.

Пример отснятого материала с видеокамеры

Если вы хотите увидеть качество результата видео с видеокамеры с Викисклада с помощью аналогичной команды:

wget https://upload.wikimedia.org/wikipedia/commons/f/f9/STS-132_Liftoff_Space_Shuttle_Atlantis.ogvffmpeg -i STS-132_Liftoff_Space_Shuttle_Atlantis.ogv -r 15 -vf scale=512:-1 \  -ss 00:00:17 -to 00:00:22 STS-132_Liftoff_Space_Shuttle_Atlantis.gif

STS-132_Liftoff_Space_Shuttle_Atlantis.gif

enter image description here

Информация об изображении: 1,3 МБ, 75 кадров, видимый размер 512x288, объединено (однако эффект минимален, поскольку отснятый материал с самого начала немного смещается), время преобразования на Lenovo P51: 2,3 секунды.

Вот версия с palettegen но только 2 секунды, чтобы соответствовать пределу загрузки 2 МБ:

enter image description here

Image info: 1.5MB, 30 frames, 512x288 apparent size, conversion time on a Lenovo P51: 43s.

Более прямой:

sudo apt-get install ffmpegffmpeg -i in.mp4 out.gif

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

До 18.04: ffmpeg + convert однострочный без промежуточных файлов

ffmpeg ранее не удавалось обрабатывать GIF-файлы. Лучшее, что у меня было, - это что-то вроде:

sudo apt-get install ffmpeg imagemagickffmpeg -i opengl-rotating-triangle.mp4 -r 15 -vf scale=512:-1 \  -ss 00:00:03 -to 00:00:06 -f image2pipe -vcodec ppm - |  convert -deconstruct -delay 5 -loop 0 - opengl-rotating-triangle-image-magick.gif

opengl-rotating-triangle-image-magick.gif

enter image description here

Информация об изображении: 995 КБ, 45 кадров, видимый размер 512x512, объединено.

Для отснятого материала шаттла "Атлантис" и аналогичного:

ffmpeg -i STS-132_Liftoff_Space_Shuttle_Atlantis.ogv -r 15 -vf scale=512:-1 \  -ss 00:00:17 -to 00:00:22 -f image2pipe -vcodec ppm - |  convert -deconstruct -delay 5 -loop 0 - STS-132_Liftoff_Space_Shuttle_Atlantis_512x.gif

результат получился более красивым, но конечный GIF-файл был значительно больше - 6,2 МБ, поэтому я не могу его загрузить.

Объяснение некоторых аргументов:

Даже если вы уменьшите высоту и частоту кадров, выходной GIF все равно может быть больше, чем видео, поскольку "реальные" видеоформаты, отличные от GIF, сжимаются по кадрам, в то время как GIF сжимает только отдельные кадры.

Прямой:

convert input.mp4 rpi2-bare-metal-blink.gif

работал, но чуть не убил мой компьютер из-за переполнения памяти и выдал вывод в 100 раз больше для моего входного файла размером 2 с 1 МБ. Может быть, однажды ImageMagick наверстает упущенное.

Смотрите также: https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality

Протестировано на Ubuntu 17.10.

Гифски

https://gif.ski/

Это еще один вариант, который был представлен моему вниманию и который требует интеллектуальных алгоритмов, так что давайте попробуем его.

Сначала нам нужно преобразовать видео в последовательность изображений, а затем передать это в gifsky, например:

sudo snap install gifskimkdir -p framesffmpeg \  -i opengl-rotating-triangle.mp4 \  -r 15 \  -vf scale=512:-1 \  -ss 00:00:03 -to 00:00:06 \  frames/%04d.pnggifski -o opengl-rotating-triangle-gifski.gif frames/*.png

opengl-rotating-triangle-gifski.gif

enter image description here

Информация об изображении: 954 Кб, 45 кадров, видимый размер 512x512, не объединено, время преобразования на Lenovo P51: 4,8 с.

И 2s STS:

enter image description here

Информация об изображении: 1,6 М, 30 кадров, видимый размер 512x288, не объединено, время преобразования на Lenovo P51: 2,8 с.

Так что для меня, субъективно, это, по-видимому, не принесло существенного преимущества по сравнению с ffmpeg palettegen.

Два шага:

  • Извлечение изображений из видео

    Создайте каталог с именем frames в том же каталоге, что и ваш .mp4 файл.Используйте команду:

    ffmpeg -i video.mp4  -r 5 'frames/frame-%03d.jpg'


    -r 5 stands for FPS value    for better quality choose bigger number    adjust the value with the -delay in 2nd step    to keep the same animation speed%03d gives sequential filename number in decimal form

    источник

  • Преобразование изображений в gif

    cd framesconvert -delay 20 -loop 0 *.jpg myimage.gif


    -delay 20 means the time between each frame is 0.2 seconds   which match 5 fps above.   When choosing this value       1 = 100 fps       2 = 50 fps       4 = 25 fps       5 = 20 fps       10 = 10 fps       20 = 5 fps       25 = 4 fps       50 = 2 fps       100 = 1 fps       in general 100/delay = fps-loop 0 means repeat forever

    Доктора: параметры преобразования gif

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

gifify это универсальная утилита на основе узлов, которая упрощает преобразование. Это зависит от nodejs, npm, ffmpeg, и imagemagick которые все доступны в репозиториях.

Как только у вас есть npm установленный вы можете установить gifify глобально с:

    npm install -g gifify

Видео может быть преобразовано в .GIF с:

    gifify video.mp4 -o video.gif

Вы также можете дополнительно установить начальную и конечную позиции в видео и добавить текстовую подпись:

    gifify clip.mp4 -o clip.gif --from 01:48:23.200 --to 01:48:25.300 --text 'we are the knights who say nip!'

❗️ Конвертация может занять несколько минут даже для небольших видеороликов.

записка: ffmpeg и imagemagick возможно, потребуется скомпилировать с некоторыми конкретными библиотеками (например, libass и fontconfig соответственно).

Я начал собирать воедино инструмент чтобы обеспечить упрощенный интерфейс для общих действий.

Вы можете конвертировать MP4 в GIF следующим образом:

$ npm install @mountbuild/mouse -g$ mouse convert input.mp4 -o output.gif -s 00:00:00 -e 00:00:03

Вы можете изменить время начала и окончания, а также --fps и --width также.

Для этого требуется установить ffmpeg.

Если ничего другого нет, ознакомьтесь с исходным кодом и посмотрите, как написать свой собственный скрипт, чтобы сделать это на JavaScript.

Вы можете использовать этот скрипт на Github, который использует FFMPEG и генерирует промежуточную цветовую палитру для улучшения качества изображения.