Цель состоит в создании нескольких выходных файлов, которые отличаются только битрейтом из одного исходного файла. Решения для этого, которые были задокументированы, работали, но имели неэффективность. Решение, которое я обнаружил, чтобы быть наиболее эффективным, не было документировано нигде, что я мог видеть. Я размещаю его здесь для обзора и спрашиваю, знают ли другие о дополнительных оптимизации, которые могут быть сделаны.
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
Кто-нибудь видит потенциальные проблемы с этим, или знает лучший метод?