Я перекодирую видеозапись с камеры видеонаблюдения в реальном времени из формата MJPEG в MPEG2, используя ffmpeg
.
К сожалению, машина, выполняющая перекодирование, не может с этим справиться (100% загрузка ЦП), однако она "достаточно хороша", и меня не смущают случайные пропущенные кадры. Но по какой-то причине ffmpeg
не пропускаются ни одного кадра, поэтому использование памяти продолжает расти, поскольку процесс отстает от входящих кадров, а затем у машины заканчивается память, и видео начинает сильно искажаться.
Есть ли способ заставить ffmpeg
отбрасывать кадры более агрессивно? Проблемы возникают, когда использование памяти достигает 1,9 ГБ, поэтому я попытался monit
перезапустить процесс, когда память превышает 1,5 ГБ, однако затем он перезапускается каждые 10 минут, что нарушает предпочтительную 15-минутную длину каждого перекодированного файла.
Вот команда, которую я использую:
ffmpeg -overrun_nonfatal 1 -y -i udp://1.2.3.4
-c mpeg2video -b:v 2M -vf transpose=2
-preset ultrafast -an -r 30
out.mkv
На странице руководства говорится, что эту -r
опцию можно использовать в качестве выходной опции для пропуска кадров, однако я делаю это, и оказывается, что она пропускает кадры только для соответствия выходной частоте кадров (здесь 30 кадров в секунду), а не для того, чтобы догнать входной поток.
-vsync
Похоже, что эта опция делает то же самое, пытаясь соответствовать частоте кадров, а не минимизировать буферизацию.
-frame_drop_threshold
выглядит более многообещающе, но, опять же, похоже, речь идет об отбрасывании кадров, чтобы соответствовать временным меткам, а не о попытке соответствовать кодированию в реальном времени.
Есть ли какая-то другая опция, которую я могу использовать, чтобы указать, ffmpeg
что нужно пропускать кадры по мере необходимости, чтобы не использовать так много памяти? Я думаю, что это должно быть в опциях реального времени/потоковой передачи/низкой задержки, но я не могу ничего найти!
решение1
Я обнаружил, что это проблема для моей среды при захвате с камеры и потоковой передаче FULL HD, и когда сеть сталкивается с узким местом, ffmpeg rtbufsize заполняется довольно быстро, и ffmpeg начинает пропускать кадры. Это похоже на решение вашей проблемы.
Библиотека libavformat предоставляет несколько общих глобальных параметров, которые можно задать для всех мультиплексоров и демультиплексоров:
rtbufsize
целое число (вход)Установите максимальный объем памяти, используемый для буферизации кадров в реальном времени.
Источник:Документация по форматам FFmpeg
Если вам нужен ограниченный буфер размером 150 МБ, попробуйте сделать следующее:
ffmpeg -rtbufsize 150M -overrun_nonfatal 1 -y -i udp://1.2.3.4 -c mpeg2video -b:v 2M -vf transpose=2 -preset ultrafast -an -r 30 out.mkv
Это значит, что пока машина не справляется, она начинает заполнять поступающими данными оперативную память, тем самым заполняя буфер, который, достигнув предела, начнет активно пропускать кадры.