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