FFmpeg: собираем gif

Что же делать, если захотелось собрать гифку?

Вырезаем нужное место из файла. Аудиодорожка на нужна, а перекодировка в x264 потребовалась в качестве удобного решения для странного поведения клипа: первые несколько секунд видео был черный экран — видимо ключевой кадр не попад в клип или ещё что-то, но не суть, работает и так.

$ ffmpeg -i ./input.mkv -ss 0:53:51 -t 5 -c:v libx264 clip.mkv

Далее у нас два пути. Говорят, что для повышения качества лучше не использовать стандартную палитру gif, а сперва сгенерировать палитру для клипа и потом уже с ней конвертировать видео в gif.

$ ffmpeg -i ./clip.mkv -vf fps=15,scale=700:-1:flags=lanczos,palettegen palette.png
$ ffmpeg -i ./clip.mkv -i palette.png -filter_complex "fps=15,scale=700:-1:flags=lanczos[x];[x][1:v]paletteuse" output_palette.gif

  • fps=15 выбрал по аналогии со значением для таймлапсов. Можно указывать как -vf fps=X, а можно сразу на уровне ffmpeg через -r x.
  • scale=700:-1 задает итоговый размер файла по горизонтали с сохранением пропорций.

Или же можно сразу собрать со стандартой палитрой.

$ ffmpeg -i ./clip.mkv -vf fps=15,scale=700:-1 -y output.gif

Странно, но в первом случае размер файла получился 13Мб (палитра), а во втором — 4.1Мб. Разнице в качестве не заметил, но, видимо, нужно смотреть на более полноцветном примере.

Даже 4.1Мб как-то много для 5 секунд, так что можно попробовать соптимизировать. Попробовал gifsicle:

gifsicle -O3 ./output.gif -o ./output_optim.gif

-03 — самый крутой метод оптимизации из трёх. Тем не менее, результата это не дало — два предыдущих файла потеряли 2.5% и меньше.