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

3

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

Вычисление палитры занимает большую часть времени выполнения с помощью следующей команды (взятой из ответа по многоцепочечному фильтру здесь: Как эффективно создать лучший палитра GIF из видео прямо из Интернета ):

ffmpeg -y -threads 8 -r 24 -f image2 -start_number 1 -i "frames.%04d.jpg" -filter_complex "fps=24,scale=150:-1:flags=fast_bilinear,split=2 [a][b]; [a] palettegen [pal] fifo [b]; [b] [pal] paletteuse" output.gif

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

Rjak
источник
1
Ваша команда синтаксически неверна; вам не хватает [b] этикетка. В любом случае, использование быстрой палитры примерно на 200⨉ медленнее, если судить по быстрому тесту. Не использовать его вообще не вариант для вас?
slhck
@slhck Я нахожу документы ffmpeg по этому материалу довольно сложными, но я придумал это для устранения палитры: ffmpeg -y -r 24 -f image2 -start_number 1 -i "frames.%04d.jpg" -filter:v "scale=150:-1:flags=fast_bilinear" output.gif Две проблемы с этим: 1) он сэкономил только 13 секунд (59 секунд вместо 72), и 2) я не уверен на 100%, что эта команда полностью исключает вычисления палитры (только то, что вычисление палитры, которое я указывал ранее, не включено ).
Rjak
1
Да, это в основном то, что я имел в виду. Извините за то, что не был таким явным, я думал, что вы знали, что делает команда фильтра, которую вы использовали. В моих тестах отсутствие палитры в целом ускорило команду существенно , Что привело вас к первоначальному выводу, что фактическая кодировка заняла всего 5 секунд?
slhck
Наблюдение за выходом, что, вероятно, не очень хороший показатель. Когда я запускаю команду без генерации палитры, индикатор «текущий кадр» немедленно раскручивается, и мы начинаем обрабатывать кадры. Когда я запускаю его с генерацией палитры, текущий кадр находится в 0 примерно за 5 секунд до окончания обработки, а затем очень быстро проходит весь кадр.
Rjak
1
Да, это также то, что я наблюдаю, но тогда это намного быстрее. Но я думаю, это зависит от продолжительности видео. Если честно, я не знаю, есть ли более быстрый способ генерировать GIF, чем просто делать ffmpeg -i <input> <scale> <output.gif>,
slhck

Ответы:

2

Ваше использование palettegen / paletteuse фильтры замедляют выполнение команды. Простой способ получить менее качественный GIF:

ffmpeg -f image2 -i "frames.%04d.jpg" output.gif

С дополнительным масштабированием:

ffmpeg -f image2 -i "frames.%04d.jpg" -vf scale=150:-1 output.gif

Вы также можете удалить кадры в выходном GIF-файле, то есть сэмплировать кадры, чтобы не все из них были обработаны. Например. иметь только 1 FPS выход, используя fps фильтр:

ffmpeg -i "frames.%04d.jpg" -vf "fps=fps=1,scale=150:-1" output.gif
slhck
источник
Я думаю, что в последнем примере есть опечатка ... должна быть `-vf" fps = 1, scale = 150: -1 ". Время выполнения второго примера составляет 68,48 с. Указание fps = 1 приводит к 1 GPS GIF, но источник составляет 120 кадров в секунду, поэтому результат воспроизводится слишком медленно, а время выполнения недостаточно улучшено (59,44 с). Я экспериментирую с использованием загрузчика concat и заставляю ffmpeg читать каждый N-й кадр. При этом, если я сэмплирую каждый 5-й кадр, используя масштабирование Ланцоша и генерацию палитры кадров, временное качество выглядит великолепно, качество цвета выглядит великолепно, и команда выполняется менее чем за 8 секунд.
Rjak
Поделюсь всем этим в комментарии здесь, как только я полностью проверил и у меня есть сроки выполнения.
Rjak
@Rjak Первый вариант fps фильтр назван fpsтак что это эквивалентно. Если ваш источник 120fps, вам нужно указать -framerate 120 -i "frames…"потому что по умолчанию для ввода 24.
slhck
1

Мне было поручено сократить количество времени, необходимое для создания анимированного GIF-файла, как можно ближе к 30 кадрам в длину при ширине 150 пикселей. Большинство сгенерированных нами последовательностей имеют размер менее 1000 кадров. У нас была последовательность кадров 15000, и наши узлы рендеринга принимали 17 минут чтобы создать этот ~ 30-кадр GIF, который неприемлемо медленный.

Мы использовали ffmpeg в качестве демультиплексора и добавили imagemagick. После нескольких часов экспериментов я пришел к следующим выводам:

  • Количество входных кадров, которые вы просите обработать ffmpeg: Вдали самый впечатляющий вклад с точки зрения скорости исполнения. Если использовать опцию concat demuxer для пропуска входных кадров, это даст наибольшую разницу в производительности. Взяв каждый 5-й кадр, я смог сократить общее время вычислений до 1 минута 45 секунд с высококачественным масштабированием Ланцоша и вычислением палитры для каждого кадра. Создание нашего 30-кадрового предварительного просмотра теперь занимает менее 1 секунды ,

  • Алгоритм масштабирования был следующим по значимости фактором, влияющим на производительность (но далекая секунда). Использование fast_bilinear вместо lanczos сэкономило 150 секунд вычислительного времени на всех 15 000 кадров.

  • Наименее влиятельной переменной были вычисления палитры, и это варьировалось в зависимости от алгоритма масштабирования. Более 15 000 кадров с использованием lanczos, мы сэкономили около 17 секунд времени выполнения, если исключили вычисления палитры. Используя fast_bilinear, мы сэкономили около 75 секунд времени выполнения.

Поскольку алгоритм масштабирования и вычисления палитры были незначительны, мы в итоге сохранили их с высочайшим качеством. Мы сократили время вычислений с 17 минут до 1 секунды, в основном, указав ffmpeg пропускать чтение входных файлов.

КЛЮЧЕВОЙ TAKEAWAY: ПРОХОДНЫЕ КАДРЫ И ПРОХОДНЫЕ КАДРЫ

Причина, по которой наш процесс занял так много времени, заключается в том, что удаление кадров не помогает времени выполнения при использовании демультиплексора image2. Если вы гадите с -r флаг и fps Фильтр, вы будете влиять на количество кадров, которые появляются в конечном GIF, но ffmpeg, кажется, все еще что-то делает со всеми 15 000 входных кадров.

Единственный способ пропустить входные кадры ffmpeg - использовать concat демультиплексор.

Вот как я теперь генерирую высококачественные анимированные GIF-эскизы на своем компьютере разработчика менее чем за 1 секунду, пропуская входные кадры:

# create text file which describes the ~30 input frames we want ffmpeg to process
seq -f "file 'left_frames.%04g.jpg'" 10000 500 25000 > tmp.txt

# generate the animated gif using ffmpeg only
ffmpeg -f concat -i tmp.txt -filter_complex "scale=150:-1:flags=lanczos,split=2 [a][b]; [a] palettegen [pal]; [b] fifo [b]; [b] [pal] paletteuse" output.gif
Rjak
источник