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

428
Rjak

Мы генерируем много миниатюрных 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 секунд. Я хотел бы максимально сократить время выполнения и желать пожертвовать большим качеством изображения ради скорости.

3
Ваша команда синтаксически неверна; вам не хватает метки `[b]`. В любом случае, использование быстрой палитры на 200⨉ медленнее, если судить по быстрому тесту. Не использовать его вообще не вариант для вас? slhck 5 лет назад 1
@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 5 лет назад 0
Да, это в основном то, что я имел в виду. Извините за то, что не был таким явным, я думал, что вы знали, что делает команда фильтра, которую вы использовали. В моих тестах полное отсутствие палитры фактически значительно ускорило выполнение команды *. Что привело вас к первоначальному выводу, что фактическое кодирование заняло всего 5 секунд? slhck 5 лет назад 1
Наблюдение за выходом, что, вероятно, не очень хороший показатель. Когда я запускаю команду без генерации палитры, индикатор «текущий кадр» немедленно раскручивается, и мы начинаем обрабатывать кадры. Когда я запускаю его с генерацией палитры, текущий кадр находится в 0 примерно за 5 секунд до окончания обработки, а затем очень быстро проходит весь кадр. Rjak 5 лет назад 0
Да, это также то, что я наблюдаю, но тогда это намного быстрее. Но я думаю, это зависит от длины видео. Честно говоря, я не знаю, есть ли более быстрый способ генерирования GIF, чем просто `ffmpeg -i `. slhck 5 лет назад 1
Да, это, кажется, кажется, я максимизирую это. Сейчас я работаю над другим методом, где мы пропускаем кадры, если клип достаточно длинный (например, если клип 15000 кадров, мы используем только каждый сотый кадр, чтобы мы получили анимированный GIF с 150 кадрами в нем). Препятствие заключается в том, что на самом деле я получаю 150-кадровый GIF, но он, похоже, выполняет вычисления на всех кадрах, которые я хочу пропустить, поэтому для его завершения требуется одинаковое количество времени! Получение этого с `-filter_complex" select = 'not (mod (n \, 100))', scale = 150: -1: flags = fast_bilinear "` Rjak 5 лет назад 0

2 ответа на вопрос

2
slhck

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

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

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

  • Количество входных фреймов, которые вы запрашиваете у ffmpeg для обработки, является BY FAR наиболее эффективным входом с точки зрения скорости выполнения. Если использовать опцию 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 

Похожие вопросы