LINUX.ORG.RU

Задержки при перекодировании видеопотока в ffmpeg «на лету»

 ,


0

2

Стоит задача: получение потока от источника (отдает кодек H264), перекодирование в формат WebM (VP8, Vorbis) и раздача realtime на веб-странице. Использование сторонних плееров и плагинов не допускается (вывод в тег <video>). Критичен вопрос задержек видео, по сути - это живая трансляция по схеме «один ко многим».

Гуглил и пробовал различные технологии, по тем или иным причинам они не устраивают (HLS, DASH, nginx + rtmp_module), пробую сейчас ffmpeg с захватом /dev/video0 (для тестирования локально):

ffmpeg -i /dev/video0 -c:v libvpx -f webm -s 640x480 -an -
Запускаю ffmpeg как child_process в NodeJS, подхватываю stdout и раздаю его через небольшой express-сервер на том же NodeJS. Вот фрагмент:
http.createServer(function (req, res) {
    res.writeHead(200, {
        'Content-Type': 'video/webm',
        'Connection': 'keep-alive'
    });

    ffmpeg.stdout.pipe(res);
}).listen(httpPort);
Видео на страницу вывожу следующим образом:
<video autoplay preload="none">
   <source src="http://<IP-address>:<Port>/stream" type='video/webm;codecs="vp8,vorbis"' />
</video>
При этом видео проигрывается (Chrome, Firefox), как и требуется, но с очень значительной задержкой (от 5 секунд). По ощущениям - как будто поток где-то буферизуется и выдается с отставанием. Чем позже подключаешься к серверу, тем большее отставание он демонстрирует. Различные опции ffmpeg пробовал, ощутимой разницы не дали. Как я понимаю, на выделенном физическом компе вопрос производительности железа не стоит, сама процедура перекодирования занимает незначительное время, да и работает он не на пределе сил.

Вопрос: возможно ли с помощью ffmpeg решить эту задачу? Если да, то какие опции нужно подобрать, чтобы минимизировать задержку и приблизить выходной видеопоток к realtime? Если нет, то что можно использовать в данном случае?

По умолчанию ффмпег первых 5 секунд входного материала собирает для анализа свойств, а потом начинает обрабатывать. Отсюда типичная задержка в 5 секунд. До абсолютного нуля это свести крайне проблематично или даже невозможно, но до пренебрежимо малых величин можно свести, добавив опции "-analyzeduration 0 -probesize 32". В случае проблем дайте чуть большие значения этим параметрам (единицы измерения в доках указаны).

Andrey_Utkin ★★ ()
Ответ на: комментарий от Andrey_Utkin

Ничего не меняется. Значения подставлял разные, также пробовал все это дело пустить через ffserver - та же история, в самом лучшем случае задержка ~5 сек. Вот конфиг ffserver:

<Stream mystream.webm>
   Feed mystream.ffm
   Format webm
   VideoSize 640x480
   VideoCodec libvpx
   NoAudio
   AVOptionVideo flags +global_headers
</Stream>
на фид подаю:
ffmpeg -re -f v4l2 -i /dev/video0 -c:v libvpx -analyzeduration 0 -probesize 32 -f webm -an http://<IP>:<Port>/mystream.ffm
или так тоже:
ffmpeg -i /dev/video0 http://<IP>:<Port>/mystream.ffm

Пробовал воспроизводить /dev/video0 напрямую через VLC - задержки практически нет.

Быть может каким то образом кэширует браузер? Хотя я пробовал пропускать поток через nginx с добавлением Cache-Control: no-cache и т.д.

Как вообще решаются подобные задачи (realtime трансляция на сайт средствами HTML5)?

bpkarton ()
Ответ на: комментарий от bpkarton

Как вообще решаются подобные задачи (realtime трансляция на сайт средствами HTML5)?

Сторонние CDN-сервисы, собственные сервера с Wowza или аналогичным софтом. Я не слежу за практикой такой деятельности.

Я бы постарался локализовать, где появляется задержка. Попробуйте играть ваш http://<IP-address>:<Port>/stream не браузером, а ffplay и vlc (да хоть wget/curl), посмотрите, какая задержка там. Посмотрите, будет ли задержка, если все три агента (ffmpeg, nodejs, проигрыватель) находятся на локалхосте.

Andrey_Utkin ★★ ()

Используя связку ffserver + ffmpeg (на ноутбуке), варьируя параметр analyzeduration и конфиг ffserver, удалось получить задержку ~2 секунды при выводе видео (webm) в браузер (на компе в локальной сети). Загрузка ЦП ~30%. Думаю, что подбирая конфиги под конкретный случай, реально получить близкое к realtime изображение (звук пока не тестировал).

bpkarton ()