FFMPEG сгенерировать анимацию(gif) из двух проходов

Все никак не удается…

Создать анимацию(gif) одно дело, а вот склеить два гиф файла, совсем другое.

Что я делаю
ffmpeg -y -i /2000.mp4 -c:v libwebp -lossless 0 -ss 20 -t 2 -filter_complex "[0:v] fps=8,setpts=1.8*PTS,scale=-2:200" -f webp /animation1.webp

ffmpeg -y -i /2000.mp4 -c:v libwebp -lossless 0 -ss 40 -t 2 -filter_complex "[0:v] fps=8,setpts=1.8*PTS,scale=-2:200" -f webp /animation2.webp

Таким образом создаю анимированное изображение с 20 по 22 секунду и с 40 по 42 секунду. У нас 2 файла. Вопрос в том, как и верно склеить?

А лучше всего на лету выполнить два прохода и на выходе получить один файл. Пытаюсь выполнить следующим образом.

ffmpeg -y -i /2000.mp4 -c:v libwebp -lossless 0 -ss 20 -t 2 -filter_complex "[0:v] fps=8,setpts=1.8*PTS,scale=-2:200" -f webp null && ffmpeg -i /2000.mp4 -c:v libwebp -lossless 0 -ss 40 -t 2 -filter_complex "[0:v] fps=8,setpts=1.8*PTS,scale=-2:200" /animation3.webp

Сохраняет только второй проход… :sleepy:

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

Гугл советует -vf или через -filter-complex.

Но у меня что-то не получилось это нормально совместить с


Еще можно попробовать в сторону пайпов покопать (передача вывода другому процессу), типа как тут, но это наверно не особо поможет тут.

так может быть, пойти другим путём:
сначала через

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

хотя, конечно, тут получается через временный файл…

хм, без fps=8 вроде бы работает.

Но для видео отсюда https://sample-videos.com/ при вырезании 5+4 сек получилось 2.4 МБ, видимо потому что большой fps, для gif вроде бы обычно меньше используют.

ffmpeg -y -i SampleVideo.mp4 -c:v libwebp -lossless 0 -vf "select='between(t,1,6)+between(t,17,21)',setpts=N/FRAME_RATE/TB,scale=-2:200" -f webp animation.webp

По третьей ссылке выше вывод ffmpeg направляют в ImageMagick, можно так попробовать.

ffmpeg -y -i /2000.mp4 -c:v libwebp -lossless 0 -vf "[0:v] fps=5, select=\'between(t,10,12)+between(t,150,152)+between(t,250,251)\',setpts=N/FRAME_RATE/TB,scale=-2:200" -f webp /animation.webp

У меня так работает, вес файла 300kb. Не много но и не мало, хотелось бы мах 200 кб получить. В любом случаи это лучший вариант

Так а если эту гифку вручную из кадров делаем, вмещаемся в 200 кБ?

В таком случаи, проще пожалуй fps уменьшить до 2 и получиться тоже самое. Плавности совсем не будет. Можно попробовать. Но тогда временный файлы придется создавать, а затем их удалять…

Так размер файла, насколько понимаю, не от плавности и длительности зависит. А от размера кадров.

И от их количества ) что и есть плавность.

Быть может правильней поступить, просто плотность пикселей(качество) уменьшить. Только не совсем понимаю как это сделать. Возможно просто размер изображения уменьшить, а через css растягивать его в блоке.

Не совсем так.
Плавность зависит от длительности отображения кадра и длительности паузы между кадрами…

о, оказывается есть флаг -r для указания фпс вывода.

Добавил его и стало 1 МБ вместо 2.4 :slight_smile:

ffmpeg -y -i SampleVideo.mp4 -c:v libwebp -lossless 0 -vf "select='between(t,1,6)+between(t,17,21)',setpts=N/FRAME_RATE/TB,scale=-2:200" -f webp -r 10 animation.webp

Гугл советует сгенерировать палитру для уменьшения размера файла.

https://cassidy.codes/blog/2017/04/25/ffmpeg-frames-to-gif-optimization/

Хотя хз работает ли это для webp.

Еще для webp есть параметр qscale.

Добавил, и уменьшилось на 200 КБ.

ffmpeg -y -i SampleVideo.mp4 -c:v libwebp -lossless 0 -vf "select='between(t,1,6)+between(t,17,21)',setpts=N/FRAME_RATE/TB,scale=-2:200" -f webp -r 10 -qscale 50 animation.webp

1 лайк

-r 10 -qscale 50

C данными настройками ужалось на 50кб, с -r 10 -qscale 40 на 60-70. Что весьма неплохо и в качестве не столь сильно потерял, fps удалось увеличить с 5 на 6. В общем файл весит 155кб, считаю это хорошим результатом.