Я хочу сделать анимированный .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
Информация об изображении: 426 КБ, 45 кадров, видимый размер 512x512, слились воедино, время преобразования на Lenovo P51: 0,5с.
Вышеупомянутое преобразование также сработало после ulimit -Sv 1000000
(Использование DRAM ограничено 1 ГБ), поэтому он "не потребляет огромные объемы памяти", как предыдущие попытки, которые я делал с Imagemagick, которые чуть не убили мою машину. 500 МБ, однако, не удалось, потому что ffmpeg не удалось загрузить свои общие библиотеки ... время обновить оперативную память ;-)?
Процедура генерации тестовых данных описано в этом посте.
Выходные данные имеют видимый шаблон расставления точек, который не так виден в приведенном ниже методе "ffmpeg + convert". Мы можем попытаться улучшить качество изображения с помощью методов, описанных в:
- https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality
- https://stackoverflow.com/questions/42980663/ffmpeg-high-quality-animated-gif
Например, используя 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
Информация об изображении: 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
Информация об изображении: 1,3 МБ, 75 кадров, видимый размер 512x288, объединено (однако эффект минимален, поскольку отснятый материал с самого начала немного смещается), время преобразования на Lenovo P51: 2,3 секунды.
Вот версия с palettegen
но только 2 секунды, чтобы соответствовать пределу загрузки 2 МБ:
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
Информация об изображении: 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 МБ, поэтому я не могу его загрузить.
Объяснение некоторых аргументов:
-loop 0
: добавьте поле подсчета циклов расширения Netscape Gif в выходные данные. 0 означает бесконечный цикл, как описано в: http://www.vurdalakov.net/misc/gif/netscape-looping-application-extensioneog
,firefox
и все циклы chromium по умолчанию выполняются бесконечно даже без него, так что я не уверен, насколько это необходимо.-delay 5
: время ожидания перед показом следующего кадра в сотых долях секунды, как описано в: https://en.wikipedia.org/wiki/GIF#Animated_GIF байт 324. Итак100
означает 1 кадр в секунду,5
означает1 / 0.5 == 20FPS
.-deconstruct
: сжатие по кадрам с прямоугольными различиями, см. также: как я могу изменить размер анимированного GIF-файла с помощью ImageMagick?
Даже если вы уменьшите высоту и частоту кадров, выходной 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.
Гифски
Это еще один вариант, который был представлен моему вниманию и который требует интеллектуальных алгоритмов, так что давайте попробуем его.
Сначала нам нужно преобразовать видео в последовательность изображений, а затем передать это в 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
Информация об изображении: 954 Кб, 45 кадров, видимый размер 512x512, не объединено, время преобразования на Lenovo P51: 4,8 с.
И 2s STS:
Информация об изображении: 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 и генерирует промежуточную цветовую палитру для улучшения качества изображения.