Подтвердить что ты не робот

Как оптимизировать ffmpeg w/x264 для нескольких файлов вывода битрейта

Цель состоит в создании нескольких выходных файлов, которые отличаются только битрейтом из одного исходного файла. Решения для этого, которые были задокументированы, работали, но имели неэффективность. Решение, которое я обнаружил, чтобы быть наиболее эффективным, не было документировано нигде, что я мог видеть. Я размещаю его здесь для обзора и спрашиваю, знают ли другие о дополнительных оптимизации, которые могут быть сделаны.

Source file       MPEG-2 Video (Letterboxed) 1920x1080 @>10Mbps
                  MPEG-1 Audio @ 384Kbps
Destiation files  H264 Video 720x400 @ multiple bitrates
                  AAC Audio @ 128Kbps
Machine           Multi-core Processor

Качество видео при каждом битрейте важно, поэтому мы работаем в режиме 2-pass с предустановленным "средним"

VIDEO_OPTIONS_P2 = -vcodec libx264 -preset medium -profile:v main -g 72 -keyint_min 24 -vf scale=720:-1,crop=720:400

Первый подход заключался в том, чтобы кодировать их все в параллельных процессах

ffmpeg -y -i $INPUT_FILE $AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 250k -threads auto -f mp4 out-250.mp4 &
ffmpeg -y -i $INPUT_FILE $AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 500k -threads auto -f mp4 out-500.mp4 &
ffmpeg -y -i $INPUT_FILE $AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 700k -threads auto -f mp4 out-700.mp4 &

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

Надеемся, что генерация всех кодов в одной команде ffmpeg позволит оптимизировать повторяющиеся шаги.

ffmpeg -y -i $INPUT_FILE \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 250k -threads auto -f mp4 out-250.mp4 \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 500k -threads auto -f mp4 out-500.mp4 \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 700k -threads auto -f mp4 out-700.mp4

Однако время кодирования было почти идентично предыдущему многопроцессорному подходу. Это заставляет меня думать, что все шаги снова выполняются в двух экземплярах.

Чтобы заставить ffmpeg читать, декодировать и масштабировать только один раз, я помещал эти шаги в один процесс ffmpeg и передавал результат в другой процесс ffmpeg, который выполнял кодировку. Это улучшило общее время обработки на 15-20%.

INPUT_STREAM="ffmpeg -i $INPUT_FILE -vf scale=720:-1,crop=720:400 -threads auto -f yuv4mpegpipe -"

$INPUT_STREAM | ffmpeg -y -f yuv4mpegpipe -i - \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 250k -threads auto out-250.mp4 \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 500k -threads auto out-500.mp4 \
$AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2 -b:v 700k -threads auto out-700.mp4

Кто-нибудь видит потенциальные проблемы с этим, или знает лучший метод?

4b9b3361

Ответ 1

Если вы применяете параметры аудио/видео к выходному каналу первого процесса, вы можете сэкономить некоторый процессор, так как он заменит 3 кодирования на один.

ffmpeg -i $INPUT_FILE -vf scale=720:-1,crop=720:400 $AUDIO_OPTIONS_P2 $VIDEO_OPTIONS_P2  -f yuv4mpegpipe -\
    | ffmpeg -y -f yuv4mpegpipe -i - \
          -b:v 250k out-250.mp4 \
          -b:v 500k out-500.mp4 \
          -b:v 700k out-700.mp4

Это рекомендуемый способ для старых версий ffmpeg. Там более новый метод (не проверял его), доступный с начала этого месяца: http://ffmpeg.org/trac/ffmpeg/wiki/Creating%20multiple%20outputs

Ответ 2

Я думаю, что тип OP больше хочет использовать фильтры один раз, кодируя несколько раз. Используемый метод хорош, хотя вы можете получить больше скорости с фильтром "tee", см. Также недавнее дополнение к нижней части http://ffmpeg.org/trac/ffmpeg/wiki/Creating%20multiple%20outputs "Множественные кодировки для одного входа"