FFMPEG производительность нескольких выходов (один экземпляр против нескольких экземпляров)
2862
shalin
Я работаю над созданием нескольких закодированных потоков из одного файла ввода (.mp4). Входной поток не имеет аудио. Каждый кодированный поток создается путем обрезки различной части входного сигнала, а затем кодируется с одинаковой скоростью передачи данных в 32-ядерной системе.
Сценарий 1 (с использованием одного экземпляра ffmpeg)
ffmpeg -i input.mp4 \
-фильтр: v обрезать = iw / 2: ih / 2: 0: 0 -c: v libx264 -b: v 5M out_1.mp4 \
-фильтр: v обрезать = iw / 2: ih / 2: iw / 2: 0 -c: v libx264 -b: v 5M out_2.mp4 \
-фильтр: v обрезать = iw / 2: ih / 2: 0: ih / 2 -c: v libx264 -b: v 5M out_3.mp4
В этом случае я предполагаю, что ffmpeg будет декодировать ввод только один раз, и он будет предоставлен всем фильтрам обрезки. Пожалуйста, поправьте меня, если это не правильно.
Сценарий 2 (использование нескольких экземпляров ffmpeg и, следовательно, трех отдельных процессов)
ffmpeg -i input.mp4 -filter: v crop = iw / 2: ih / 2: 0: 0 -c: v libx264 -b: v 5M out_1.mp4
ffmpeg -i input.mp4 -filter: v crop = iw / 2: ih / 2: iw / 2: 0 -c: v libx264 -b: v 5M out_2.mp4
ffmpeg -i input.mp4 -filter: v crop = iw / 2: ih / 2: 0: ih / 2 -c: v libx264 -b: v 5M out_3.mp4
В моем случае мне действительно нужно кодировать еще большее количество потоков, обрезая различные разделы входного видео. Я показываю три здесь, чтобы сделать этот пример проще.
Теперь, с точки зрения производительности fps, я вижу, что сценарий 2 работает лучше. Он также использует процессор по максимуму (загрузка процессора более 95%). В сценарии 1 меньше кадров в секунду, а загрузка ЦП намного ниже (около 65%). Кроме того, в этом случае, когда я увеличиваю количество потоков, которые должны быть закодированы, загрузка ЦП не увеличивается линейно. это почти в 1,5 раза, когда я иду от одного потока к двум. Но после этого приращения очень низкие (вероятно, 10% и даже меньше с большим количеством потоков).
Итак, мой вопрос: я хочу использовать один экземпляр ffmpeg, потому что он позволяет избежать многократного декодирования, а также, потому что мой ввод может быть как 4K или даже больше. Что я должен сделать, чтобы улучшить загрузку ЦП (> 90%) и, следовательно, улучшить производительность fps? Кроме того, почему загрузка ЦП не увеличивается линейно с количеством потоков, которые должны быть закодированы? Почему один экземпляр ffmpeg не работает так же хорошо, как несколько экземпляров? Мне кажется, что с одним экземпляром ffmpeg все кодировки действительно не работают параллельно.
Изменить: Вот самый простой способ, которым я могу воспроизвести и объяснить проблему, если все не так ясно. Имейте в виду, что это только для экспериментальных целей, чтобы понять проблему.
Одиночный экземпляр: ffmpeg -y -i input.mp4 -c: v libx264 -x264opts threads = 1 -b: v 1M -f ноль - -c: v libx264 -x264opts потоков = 1 -b: v 1M -f ноль - - c: v libx264 -x264opts threads = 1 -b: v 1M -f ноль -
Несколько экземпляров: ffmpeg -y -i input.mp4 -c: v libx264 -x264opts threads = 1 -b: v 1M -f ноль - | ffmpeg -y -i input.mp4 -c: v libx264 -x264opts threads = 1 -b: v 1M -f ноль - | ffmpeg -y -i input.mp4 -c: v libx264 -x264opts threads = 1 -b: v 1M -f ноль -
Обратите внимание, что я ограничиваю x264 одним потоком. В случае одного экземпляра я бы ожидал, что ffmpeg сгенерирует 1 поток кодирования для каждого кодирования x264 и выполнит их параллельно. Но я вижу, что полностью используется только одно ядро процессора, что заставляет меня поверить, что одновременно выполняется только один сеанс кодирования. С другой стороны, в случае нескольких экземпляров, я вижу, что три ядра процессора полностью используются, что, я думаю, означает, что все три кодировки работают параллельно.
Я действительно надеюсь, что некоторые эксперты могут подключиться и помочь с этим.
Кстати, я провел обширный поиск по вышеуказанной теме, и ни один из постов не говорит о том, почему отдельный экземпляр не работает так хорошо. самый близкий пост, который я мог найти, был этот (https://stackoverflow.com/questions/12465914/how-to-optimize-ffmpeg-w-x264-for-multiple-bitrate-output-files), но без вида детали, которые я ищу.
shalin 7 лет назад
0
3 ответа на вопрос
1
aergistal
Менее очевидная проблема заключается в том, что в зависимости от вашего ввода / вывода или фильтров ffmpegможет потребоваться внутреннее преобразование формата пикселей, и в некоторых случаях это становится узким местом при использовании параллельных выходов, если они выполняются для каждого потока отдельно.
Идея состоит в том, чтобы сделать преобразование формата пикселя один раз, если это возможно, например:
Одинаковые фильтры, применяемые ко всем выходам, также должны использоваться только один раз. Некоторые фильтры могут нуждаться в определенном формате пикселей.
По другим причинам смотрите небольшую заметку внизу вики :
Параллельное кодирование
Вывод и повторное кодирование несколько раз в одном и том же процессе FFmpeg обычно замедляют работу до «самого медленного кодера» в вашем списке. Некоторые кодировщики (например, libx264) выполняют свое кодирование «в потоке и в фоновом режиме», поэтому они эффективно допускают параллельное кодирование, однако аудиокодирование может быть последовательным и стать узким местом и т. Д. Похоже, что если у вас есть какие-либо последовательные кодировки, FFmpeg будет рассматривать его как «настоящий серийный», и, следовательно, ваш FFmpeg может использовать не все доступные ядра.
0
Akumaburn
Я сам заметил это с небольшим размером видео / буфера по умолчанию.
Попробуйте увеличить размер буфера до 50M или до половины размера файла, в зависимости от того, что меньше.
Также обратите внимание, что параметр bufsize обозначается в единицах k, так что это будет что-то вроде -bufsize 50000k
поэтому я изменил командную строку, добавив bufsize следующим образом: ffmpeg -i input.mp4 -filter: v crop = iw / 2: ih / 2: 0: 0 -c: v libx264 -b: v 5M ** - bufsize 50000k ** out_1.mp4 -фильтр: v обрезать = iw / 2: ih / 2: iw / 2: 0 -c: v libx264 -b: v 5M ** - bufsize 50000k ** out_2.mp4 -фильтр: v crop = iw / 2: ih / 2: 0: ih / 2 -c: v libx264 -b: v 5M ** - bufsize 50000k ** out_3.mp4 **, но я не вижу какого-либо улучшения производительности fps или процессора использование **
shalin 7 лет назад
0
Странно, но использование процессора значительно улучшилось с увеличением размера буфера. Какова продолжительность вашего видеофайла / размер файла?
Akumaburn 7 лет назад
0
Я пробовал это в зависимости от размера файла (от 100 МБ до 1 ГБ) и длительности (от 1 минуты до 10 минут). Я действительно не понимаю, почему размер файла / продолжительность будет иметь какое-либо влияние на это. Разрешение входного кадра, которое я пробовал, составляет 1080p, 4K и выше.
shalin 7 лет назад
1
Я проверял это сам, непосредственно с libx264, хотя и не через командную строку ffmpeg. Может быть, ffmpeg ожидает другой формат? Что произойдет, если вы попробуете -bufsize 50M, какая разница?
Akumaburn 7 лет назад
0
Даже 24 параллельных выхода здесь не показывают никаких проблем - процессор остается на уровне> 95% для всего процесса, почти не используется SSD (<5%) и ~ 75% оперативной памяти (на холостом ходу ~ 30% используются). (Проверенные вручную значения через Task-Manager)
Так что здесь есть несколько возможностей:
Вы используете старую версию FFmpeg
Что-то еще (HDD, RAM) является узким местом
Что-то не так с вашим файлом - я думаю, вряд ли
Что-то не так с вашим процессором - столь же маловероятно, поскольку вы заявляете, что он работает на полную мощность при использовании нескольких экземпляров ffmpeg)
попробуйте разные значения -threadsв вашем коде и посмотрите, будет ли это иметь значение.
Я использую облачный экземпляр Google с 64 процессорами и 416 ГБ оперативной памяти. Таким образом, мы можем легко исключить проблемы с процессором, оперативной памятью, жесткими дисками и т. Д. Я использовал это некоторое время, и у него очень стабильная и надежная производительность для всех тестов. У меня была версия FFMPEG, которой было около 6 месяцев, и я также попробовал последнюю версию 3.3.2, но это не помогло. Кроме того, я попытался изменить количество потоков без какого-либо успеха.
shalin 7 лет назад
0
Теперь вернемся к основному обсуждению, я попытался запустить вашу командную строку. При этом я получаю около 12 кадров в секунду при загрузке процессора менее 50%. Но когда я запускаю каждое кодирование как отдельный процесс ffmpeg, я могу приблизиться к 30 кадрам в секунду при почти 100% загрузке процессора. Помните, что у меня 64 ядра, поэтому рабочая нагрузка должна быть действительно параллельной и требовать значительных вычислительных ресурсов для полного использования. В вашем случае легко достичь 100% процессора, потому что у вас всего 4 ядра.
shalin 7 лет назад
1
Конечно, вы правы в том, что мои 4-ядерные установки не сопоставимы с вашими 64-ядерными - извините, я полностью пропустил предложение, объясняющее это. Примерно через 72 часа я смог протестировать его на процессоре i7-5820k, но я думаю, что это тоже не совсем сравнимо и потому бесполезно. Вы пробовали это с вышеупомянутым файлом? Кроме того, `-an` что-то меняет? Кроме этого, у меня нет идей - извините ...
flolilolilo 7 лет назад
0
да, я попробовал это с файлом, который вы мне дали. также -не ничего не меняет. Спасибо, что уделили нам время на это.
shalin 7 лет назад
0
Кстати, если у вас есть время, вы можете зайти в раздел «Правка» моего первоначального вопроса и попробовать оба варианта с вашим входным файлом. Я уверен, что вы можете воспроизвести то, что я пытаюсь объяснить, на вашей 4-х базовой платформе.
shalin 7 лет назад
0
Я проверил это и могу воспроизвести проблему с `-x264opts threads = 1`, однако этого следует ожидать, так как это уменьшает потоки. Как правило, следует использовать 1 поток на ядро (или более). Я позволил PowerShell создать несколько CSV с начальным и конечным временем тестов и RAM- + CPU-stats - это огромная куча данных. Я подал его на диаграмму в Excel и обнаружил, что: a) потоки `x264opts` более" эффективны ", чем` -threads`; б) все, что выше 1 потока, по крайней мере, имеет шансы получить 100% ЦП; в) больше потоков = больше используемой оперативной памяти d) авто (то есть ничего не сообщая о потоках) работает довольно хорошо.
flolilolilo 7 лет назад
0
(больше не могу редактировать мой последний комментарий). Но я знаю, что вы это знаете. Я был бы очень рад распространить свои результаты тестов (тем временем, я даже запустил их на своих 5820k), но я не знаю, как это сделать в рамках superuser.com, так как одна диаграмма должна быть 200cm Широкий, чтобы увидеть что-то ...
flolilolilo 7 лет назад
0