![Как намеренно добавить задержку к входному потоку с помощью ffmpeg](https://rvso.com/image/1703363/%D0%9A%D0%B0%D0%BA%20%D0%BD%D0%B0%D0%BC%D0%B5%D1%80%D0%B5%D0%BD%D0%BD%D0%BE%20%D0%B4%D0%BE%D0%B1%D0%B0%D0%B2%D0%B8%D1%82%D1%8C%20%D0%B7%D0%B0%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D1%83%20%D0%BA%20%D0%B2%D1%85%D0%BE%D0%B4%D0%BD%D0%BE%D0%BC%D1%83%20%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D1%83%20%D1%81%20%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E%20ffmpeg.png)
У меня есть фреймграббер, который я подключаю к ПК с Windows. Устройство ввода захвата — 1080p, 60 кадров в секунду, 4:4:4 raw video. Я хочу использовать это в тестовой настройке, где я позволяю пользователю работать с существующим приложением Windows и ввожу сжатие изображения, уменьшенное разрешение уменьшает частоту кадров. Идея состоит в том, чтобы узнать об опыте пользователя и позволить пользователю оценить различные настройки. Моя идея состоит в том, чтобы использовать ffmpeg для получения входного потока RAW и вводить задержку, перекодировать в MJPEG и добавлять различные уровни JPEG и добавлять задержку. Хотя я уже могу получить доступ к устройству захвата, изменить разрешение и уменьшить частоту кадров, я не уверен, возможно ли вообще вводить задержку, поскольку в большинстве случаев люди либо хотят ввести задержку видео, чтобы учесть задержку звука, либо хотят уменьшить задержку видео, а не намеренно добавлять задержку видео :-) Вот как я сейчас обрабатываю поток:
ffmpeg -f dshow -i video="framegrabber_capture_1" -vf format=yuv420p,scale=1280x1024,fps=5 -f sdl test
Примечание: мне нужно только чистое видео, звук в тестовой настройке не нужен.
Я не понял, как перекодировать в MJPEG, но, думаю, это выполнимо. Чего я вообще не смог найти, так это информации о задержке видео, поскольку это также означало бы, что поток где-то кэшируется. Было бы здорово, если бы кто-нибудь указал мне правильное направление.
Спасибо!
Дж.
решение1
FFmpeg не предназначен для задержки отображаемого видео, поскольку FFmpeg не является видеоплеером.
Мы можем заставить FFmpeg задержать видео, присоединив короткое видео перед видео с камеры, используяконкатфильтр.
Мы также должны добавитьв реальном временифильтр, заставляющий FFmpeg согласовывать скорость вывода со скоростью ввода (без него FFmpeg отправляет видео максимально быстро).
При кодировании MJPEG мы не можем использовать -f sdl test
, мы передаем вывод FFmpeg в FFplay для отображения видео.
Пример задержки захваченного видео на 5 секунд:
ffmpeg -an -f dshow -rtbufsize 1G -i video="framegrabber_capture_1" -filter_complex "color=white:size=1280x1024:rate=5:duration=5[w];[0:v]scale=1280x1024,setsar=1,fps=5[v0];[w][v0]concat,realtime=limit=10" -c:v mjpeg -pix_fmt yuvj420p -f mjpeg pipe: | ffplay pipe:
-rtbufsize 1G
- увеличить размер входного буфера до 1 Гбайт (позволяет хранить «много» входных видеокадров).color=white:size=1280x1024:rate=5:duration=5[w]
- Создает синтетическое белое видео длительностью 5 секунд и частотой 5 кадров в секунду. Сохраняет в[w]
.[0:v]scale=1280x1024,setsar=1,fps=5
- Масштабировать входное видео и задать частоту кадров. Сохранить в[v0]
.[w][v0]concat
- Объедините 5-секундное белое видео с масштабированным входным видео (5-секундное белое видео идет первым).realtime=limit=10
- Замедляет скорость вывода до скорости ввода (limit=10
— предел паузы).-c:v mjpeg -f mjpeg
- кодировать выходное видео с помощью кодека MJPEG и сохранять его в формате контейнера MJPEG.pipe:
- Использовать stdout в качестве вывода.| ffplay pipe:
передать канал stdout из FFmpeg в канал stdin FFplay (использовать как вход).
Примечание:
задержка неточная, поскольку имеется дополнительная встроенная задержка.
Мы можем (попытаться) улучшить точность задержки, используя более высокую частоту кадров и добавив setpts=0
в команду FFplay:
ffmpeg -an -f dshow -rtbufsize 1G -i video="Microsoft® LifeCam HD-3000" -filter_complex "color=white:size=1280x1024:rate=25:duration=5[w];[0:v]scale=1280x1024,setsar=1,fps=25[v0];[w][v0]concat,realtime=limit=10" -c:v mjpeg -pix_fmt yuvj420p -f mjpeg pipe: | ffplay -vf setpts=0 pipe: