Comments 21
вещать с произвольного источника, скажем ffmpeg, прямо в браузер?
или можно напрямую дать WebRTC в зубы ссылку на RTP поток принимать без посредников?
Если смотреть на эту задачу с точки зрения сети, то получается так:
Допустим на одном компьютере 192.168.1.10 у вас ffmpeg и он умеет WebRTC (не знаю так ли это, не тестировали), но допустим, ffmpeg умеет вести себя как Chrome и является WebRTC-пиром.
Допустим на втором компьютере 192.168.1.11 установлен Chrome (WebRTC-браузер).
Чтобы «вещать прямо в браузер», вам нужно видеотрафик так или иначе передать с устройства 192.168.1.10 на 192.168.1.11 по TCP или UDP протоколу.
Тогда браузер сможет принять видеопоток, декодировать и отобразить в плеере и вещание состоится.
Чтобы передать трафик, нужно открыть как минимум 1 порт и там и там.
Допустим, передавать будем по UDP и открываем порты .10:3310 и .11:3311 соответственно.
Ок, порты забиндили. Теперь эти два устройства должны друг другу как-то сообщить о своих портах. И здесь два варианта:
- Использовать третье устройство — посредник, через которого можно обменяться информацией о портах.
- Сделать этим посредником условный ffmpeg.
После того, как устройства .10 и .11 обменялись портами, у них есть все необходимое для установки соединения и передачи трафика.
Т.е. ответ на вопрос — да, можно вещать напрямую из источника в браузер.
Для этого источник должен:
1) Поддерживать WebRTC-стек.
2) Выступать сигнальным сервером для обмена SDP (портами).
3) Кодировать видео один раз и тиражировать браузерам копии.
Фактически, ваш источник должен быть сервером, умеющим захватывать сырое видео с камеры, подцепленной к нему через USB или другой интерфейс.
Понятно что такое вещание будет нормально работать только внутри локальной сети, т.к. если потоков тиражируется много, то они просто не пролезут в глобальную сеть. Т.е. из локальной сети вы сможете вытащить ну 10 толстых потоков на 10 браузеров снаружи, и на этом все.
Поэтому для общего случая и для продакшена рабочий вариант — доставить поток на внешний сервер и оттуда этот поток уже распространять по браузерам. В локальной сети тоже самое, только сервер устанавливается локально.
Из этого и следует невозможность дать WebRTC в зубы ссылку — браузер открывает свои порты, и требует нормальной аутентификации и нормального шифрования. Поэтому вам требуется полноценный WebRTC стек.
Но как я уже понял проблема даже не в этом, а в том что в WebRTC, поверх UDP и TCP, еще лежит SCTP — со своими каналами и т.д., а это уже нестандартный транспорт со всеми вытекающими…
SCTP вообще ни при чем, его как-раз и можно опустить за ненадобностью.
Вообще, если есть ffmpeg в качестве источника, то проще воспользоваться hls или mpd. Один модуль для nginx, простая настройка, ну и плюс библиотка для mpd на клиенте.
WebRTC нужен, если критична маленькая задержка или требуется видео от пользователя.
А куда вы будете вещать?Еще раз. Я сейчас не утверждаю что так устроен WebRTC, я рассуждаю гипотетически. Для того что бы вещать по RTP нужно только открыть порт на клиенте и вещать туда. В конце концов, можно жестко выставить порт на клиенте и источнике (я не собираюсь это делать на практике, мне просто хотелось бы разобрать стек WebRTC по косточкам).
SCTP вообще ни при чем, его как-раз и можно опустить за ненадобностью.А вот это очень интересно. Просто у меня сложилось ощущение что SCTP там прибит гвоздями и без него никак. Т.е. вы хотите сказать что можно использовать любой другой транспорт? А каким образом и где это настраивается, вы могли бы подсказать?
Вообще, если есть ffmpeg в качестве источника, то проще воспользоваться hls или mpd. Один модуль для nginx, простая настройка, ну и плюс библиотка для mpd на клиенте.В моем случае не проще, т.к.:
WebRTC нужен, если критична маленькая задержка или требуется видео от пользователя.
1. MSE, с некоторого времени, требует что бы в потоке границы сегментов были строго по IDR, а у меня в потоках IDR может не быть по несколько десятков минут.
2. Мои потоки запросто могут «подрываться», а из-за MSE, восстановление возможно только со следущего IDR.
Короче у меня вещание идет не с «жесткой» заранее приготовленной копии, а с реальных камер или эфирных кабелей.
Просто у меня сложилось ощущение что SCTP там прибит гвоздями и без него никак. Т.е. вы хотите сказать что можно использовать любой другой транспорт? А каким образом и где это настраивается, вы могли бы подсказать?
В WebRTC SCTP используется не для видео/аудио, а для передачи данных. Видео же гонится по обычному UDP или TCP.
просто хотелось бы разобрать стек WebRTC по косточкам
Я писал свой WebRTC сервер, для видео/аудио, могу вкратце пояснить:
1. Сначала обмениваемся SDP друг с другом, поясняем, кто какие кодеки умеет, какие будут использоваться логины/пароли для ICE
2. Обмениваемся ip и портами, как локальными, так и внешними — STUN/TURN.
3. После чего, начинаем посылать ICE пакеты друг другу по полученным адресам
4. Как только будет коннект по каким-либо ip, начинаем передачу ключей шифрования для трафика.
5. После чего берем обычные RTP пакеты, шифруем их SRTP полученными в предыдущем пункте ключами, и отправляем по ip/port, полученными в результате ICE-коннекта из пункта 3.
Все это вполне реализуемо самому. Если не хочется заморачиваться — берем чужой медиасервер (например kurento), отправляем на него RTP-поток, забираем с него по WebRTC.
SDP это протокол описания, а как происходит сам обмен?
Как я понимаю, ICE — Interactive Connectivity Establishment — это протокол или просто некая стандартизированная процедура?
Если я всегда нахожусь в локальной сети, могу ли я избежать работы с STUN/TURN серверами или это не обойти и это обязательно?
ICE — это протокол.
Если вы всегда в локальной сети, то STUN необязателен. TURN тем более. Даже если вы укажете STUN сервера, то коннект пойдет через локальные ip адреса, у них приоритет выше.
Скорось подключения вырастит, но неравномернось загрузки также возрастет. Уменьшая размер чанка вы потеряете на ожидании каждого следущего, т. к. в дело вступит задержка round-trip.
Поэтому мы не можем задать точное время чанка. Мы можем указать, например «не менее 2 секунд». В этом случае мы дождемся от Хрома по WebRTC ключевого кадра, проверим прошло ли две секунды, и если прошло, то нарежем чанк.
Мы не можем принудить браузер высылать ключевые фреймы в жестком интервале 2 секунды. Но можем каждые две секунды просить у браузера ключевой кадр через PLI фидбэк, и для этого есть специальная настройка. Браузер может дать, а может и не дать по запросу. Чаще дает.
Поэтому, в общем случае, без транскодинга, мы можем управлять только нижней границей длины HLS чанка.
В любом случае, уменьшение длины чанков не спасает внутри CDN, а с одним сервером такой проблемы нет. Вне зависимости от размера чанков, даже если бы мы транскодировали поток и нарезали чанки по 1 секунде, в CDN между запросом плей листа и доставкой потока с Origin-сервера пройдет время и плеер перестанет играть поток. Поэтому пока рабочий вариант — только прелоадер первому зрителю.
должно пройти какое-то время для того чтобы заказать этот стрим с Origin сервера, получить его на Edge и приступить к HLS нарезке
не очень понятно, зачем нарезать hls на edge серверах, это же оверхед – будет одна и та же обработка на разных серверах
почему не нарезать на одном сервере (источнике), а edge использовать как прокси, которые будут забирать чанки с этого одного сервера, заодно и не надо будет заказывать поток, можно его проксировать сразу при запросе, и проблем с фризами не будет
В данном случае HLS нарезается только на Edge серверах, а между Origin и Edge бегает WebRTC по UDP, что дает меньшую задержку по сравнению с проксированием HLS. Поэтому нет и оверхеда: Origin работает только на публикацию, Edge - только на раздачу зрителям. Можно еще и транскодирование вынести на отдельные железные сервера (транскодинг желателен для WebRTC стримов, чтобы выровнять FPS и keyframe интервал, HLS плееры к этим параметрам критичны, особенно native в Safari.
между Origin и Edge бегает WebRTC по UDP
а если источник в RTMP? или у вас только WebRTC?
что дает меньшую задержку по сравнению с проксированием HLS
у HLS и так задержка минимум несколько секунд, лишние 100-200мс на проксирование я думаю погоды не сделают
Поэтому нет и оверхеда: Origin работает только на публикацию, Edge — только на раздачу зрителям
Как я понимаю, у вас на Edge ведь горизонтальное масштабирование, то есть разные зрители одного стрима могут быть на разных Edge серверах?
Я про этот оверхэд и говорил, в плане архитектуры – что у вас одинаковая нарезка делается в нескольких местах, а можно сделать в одном.
Или у вас один стрим идет только на один Edge сервер, и все его зрители сидят на этом сервере? Тогда вопрос снимается.
а если источник в RTMP? или у вас только WebRTC?
внутри CDN только WebRTC или SRT, от источника публикации это не зависит
у HLS и так задержка минимум несколько секунд
у Low Latency HLS (который у нас уже реализован, кстати) задержка около трех секунд, что сопоставимо с RTMP и WebRTC over TCP
Как я понимаю, у вас на Edge ведь горизонтальное масштабирование, то есть разные зрители одного стрима могут быть на разных Edge серверах?
да, это так.
но эта архитектура затачивалась под WebRTC зрителей в первую очередь. как правило, мы рекомендуем выделять в CDN отдельные Edge сервера под WebRTC и HLS зрителей, это позволяет избежать лишнего транскодинга аудио на Edge.
и мы даем не готовое решение, а конструктор. т.е. разработчик может выделить HLS Edge, и уже с него проксировать.
внутри CDN только WebRTC или SRT, от источника публикации это не зависит
а качество не страдает от транскодинга? я когда игрался с WebRTC и Pion у меня сложилось впечатление, что он не заточен под поток высокого качества и там норма выпадение кадров и понижение качества
а CDN же на проверенных линиях, там по идее внутри не должно быть плавающей скорости, нестабильного канала и прочего, для чего делался WebRTC
у Low Latency HLS (который у нас уже реализован, кстати) задержка около трех секунд, что сопоставимо с RTMP и WebRTC over TCP
ну вот, если задержка на проксирование 100 мс (и это большая, она скорее меньше будет), то от 3 сек это будет 3%, не думаю что об этом стоит беспокоится, и насколько понимаю 3 сек это в идеальном варианте, на практике у LL-HLS и 5-10 сек спокойно может быть
и у UDP тоже ведь есть задержка, хотя и меньше, то есть в итоге разница будет еще меньше, порядка 1%
и мы даем не готовое решение, а конструктор. т.е. разработчик может выделить HLS Edge, и уже с него проксировать.
ну я просто говорю, что проблему первого зрителя можно было решить проще, сделав одно место где готовится HLS, вместо вынесения этого на Edge, заодного и нагрузка бы снизилась на Edge
del
Проблема первого зрителя, или непростая конвертация WebRTC видеопотоков в HLS