5

Я работаю над созданием нескольких закодированных потоков из одного файла ввода (.mp4). Входной поток не имеет аудио. Каждый кодированный поток создается путем обрезки различной части входного сигнала, а затем кодируется с одинаковой скоростью передачи данных в 32-ядерной системе.

Вот сценарии, которые я пытаюсь описать в википедии ffmpeg для создания нескольких выходов. https://trac.ffmpeg.org/wiki/Creating%20multiple%20outputs

Сценарий 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 и выполнит их параллельно. Но я вижу, что полностью используется только одно ядро процессора, что заставляет меня поверить, что одновременно выполняется только один сеанс кодирования. С другой стороны, в случае нескольких экземпляров, я вижу, что три ядра процессора полностью используются, что, я думаю, означает, что все три кодировки работают параллельно.

Я действительно надеюсь, что некоторые эксперты могут подключиться и помочь с этим.

3 ответа3

1

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

Идея состоит в том, чтобы сделать преобразование формата пикселя один раз, если это возможно, например:

-filter_complex '[0:v]format=yuv420p, split=3[s1][s2][s3]' \
-map '[s1]' ... \
-map '[s2]' ... \
-map '[s3]' ... \

Одинаковые фильтры, применяемые ко всем выходам, также должны использоваться только один раз. Некоторые фильтры могут нуждаться в определенном формате пикселей.

По другим причинам смотрите небольшую заметку внизу вики:

Параллельное кодирование

Вывод и повторное кодирование несколько раз в одном и том же процессе FFmpeg обычно замедляют работу до "самого медленного кодера" в вашем списке. Некоторые кодировщики (например, libx264) выполняют свое кодирование "в потоке и в фоновом режиме", поэтому они эффективно допускают параллельное кодирование, однако аудиокодирование может быть последовательным и стать узким местом и т.д. Похоже, что если у вас есть какие-либо последовательные кодировки , FFmpeg будет рассматривать его как "настоящий серийный", и, следовательно, ваш FFmpeg может использовать не все доступные ядра.

0

Я не могу воспроизвести вашу проблему. Настроить:

  • Последний Zeranoe static-build
  • Win10 pro
  • Процессор Intel i5-4210U (4 ядра, без HT)
  • 8 ГБ оперативной памяти DDR3
  • R/W к внутреннему SSD реактора Мушкина 1 ТБ
  • Видео для воспроизведения: http://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov (-ss 00:01:00.000 -to 00:01:25.000 потому что рендеринг все дело явно заняло бы вечность)

Мой код в Powershell:

# Measure time of FFMPEG process
$time = Measure-Command{
    ffmpeg -ss 00:01:00.000 -i .\ToS-4k-1920.mov `
    -to 00:00:25.000 -c:v libx264 -b:v 5M -y .\out_1.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_2.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:ih/2" -c:v libx264 -b:v 5M -y .\out_3.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_4.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_5.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_6.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_7.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_8.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_9.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_10.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_11.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_12.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:0" -c:v libx264 -b:v 5M -y .\out_13.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_14.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:0:ih/2" -c:v libx264 -b:v 5M -y .\out_15.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_16.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_17.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_18.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_19.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_20.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_21.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_22.mp4 `
    -to 00:00:25.000 -c:v libx264 -b:v 5M -y .\out_23.mp4 `
    -to 00:00:25.000 -vf "crop=iw/2:ih/2:iw/2:0" -c:v libx264 -b:v 5M -y .\out_24.mp4
}

Write-Host "Time spent: $time"

Результат:

  • $time: 00: 05: 52.7747482
  • Скорость ffmpeg: speed=0.0711x

Оба значения кажутся мне разумными.

Даже 24 параллельных выхода здесь не показывают никаких проблем - процессор остается на уровне> 95% для всего процесса, почти не используется SSD (<5%) и ~ 75% оперативной памяти (на холостом ходу ~ 30% используются). (Проверенные вручную значения через Task-Manager)

Так что здесь есть несколько возможностей:

  • Вы используете старую версию FFmpeg
  • Что-то еще (HDD, RAM) является узким местом
  • Что-то не так с вашим файлом - я думаю, вряд ли
  • Что-то не так с вашим процессором - столь же маловероятно, поскольку вы заявляете, что он работает на полную мощность при использовании нескольких экземпляров ffmpeg)
  • попробуйте разные значения -threads в вашем коде и посмотрите, будет ли это иметь значение.
0

Я сам заметил это с небольшим размером видео / буфера по умолчанию.

Попробуйте увеличить размер буфера до 50M или до половины размера файла, в зависимости от того, что меньше.

Также обратите внимание, что параметр bufsize обозначается в единицах k, так что это будет что-то вроде -bufsize 50000k

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .