Функции SFU с поддержкой Simulcast¶
Описание¶
В сборке 5.2.1056 добавлена поддержка WebRTC Selective Forwarding Unit (SFU) с возможностью публикации и проигрывания любого количества потоков в одном WebRTC соединении (Simulcast). Основные области применения:
- публикация потока в нескольких качествах (например, 720p, 480p, 360p) с возможностью автоматического и ручного переключения качества
- организация видео и аудио чат-комнат
Поддерживаемые платформы и браузеры¶
Chrome | Firefox | Safari | Edge | |
---|---|---|---|---|
Windows | ✅ | ✅ | ❌ | ✅ |
Mac OS | ✅ | ✅ | ✅ | ✅ |
Android | ✅ | ✅ | ❌ | ✅ |
iOS | ✅ (iOS 14.4) | ✅ | ✅ | ✅ |
Поддерживаемые кодеки¶
WebRTC video:
WebRTC audio:
- Opus
Принципы реализации¶
Поскольку одним из случаев применения SFU являются видео и аудио конференции, на стороне сервера введена новая сущность - комната. Установив соединение с сервером, пользователь подключается к комнате и может публиковать свои потоки, а также проигрывать все потоки в данной комнате. За пределами комнаты потоки, опубликованные в ней, недоступны.
Конфигурация комнаты¶
Пример объекта, задающего конфигурацию комнаты:
Здесь
url
- Websocket URL WCS-сервераname
- уникальное имя комнатыpin
- пин-кодnickName
- имя пользователя в комнате
Публикация потоков в комнате¶
Пользователь может добавлять и удалять видео и аудио потоки. При добавлении может быть указан набор качеств, и поток будет опубликован в этих качествах. Каждое качество имеет следующие характеристики:
- максимальный битрейт
- коэффициент масштабирования по отношению к разрешению оригинального потока (в сторону уменьшения)
При проигрывании потока пользователю доступны все качества, либо те из них, которые умещаются в канал подписчика. Например, при публикации потока 720p с качествами 720p 900 kbps, 360p 500 kbps и 180p 200 kbps, подписчик может получать только 360p и 180p, если его канала до сервера недостаточно для получения 720p.
Пример настройки публикации медиапотоков в комнате
"media": {
"audio": {
"tracks": [{
"source": "mic",
"channels": 1
}]
},
"video": {
"tracks": [{
"source": "camera",
"width": 1280,
"height": 720,
"codec": "H264",
"encodings": [
{ "rid": "h", "active": true, "maxBitrate": 900000 },
{ "rid": "m", "active": true, "maxBitrate": 300000, "scaleResolutionDownBy": 2 }
]
}]
}
}
Здесь
audio
- конфигурация аудиодорожекvideo
- конфигурация видеодорожекsource
- источник публикации: camera, screen, micchannels
- количество каналов аудиоwidth
,height
- исходная ширина и высота картинки видеоcodec
- кодек видео:H264
илиVP8
encodings
- набор качеств, с которыми поток будет опубликован
Параметры качества указываются в соответствии с описанием RTCRtpEncodingParameters.
Настройка сервера¶
Публикация H264¶
По умолчанию, даже если в параметрах публикации задан кодек H264, в комнате будут публиковаться потоки VP8. Чтобы публиковать H264, необходимо:
- исключить все кодеки, кроме H264, чтобы убрать их из SDP
- ограничить минимальный битрейт публикации
- ограничить используемые профили кодирования H264
codecs_exclude_sfu=alaw,ulaw,g729,speex16,g722,mpeg4-generic,telephone-event,flv,mpv,vp8,h265
webrtc_cc_min_bitrate=1000000
profiles=42e01f,640028
Отметим, что публикация и проигрывание большого числа VP8 потоков в нескольких качествах потребляет ресурсы клиентского ПК. Если ресурсов не хватает, следует предпочесть H264, поскольку большинство браузеров поддерживают аппаратное ускорение для данного кодека.
Краткое руководство по тестированию¶
-
Откройте пример SFU client в браузере, например https://demo.flashphoner.com:8888/client2/sfu/client/main.html, введите URL сервера, имя комнаты, пин-код и имя пользователя, нажмите Enter
-
Поток пользователя
User1
публикуется в комнатеROOM1
Статистика отправки качества 720p
Статистика отправки качества 360p
-
Откройте страницу примера в другом браузере или в другом окне браузера, введите URL сервера и параметры комнаты такие же, как на шаге 3, имя пользователя
User2
-
Поток пользователя
User2
проигрывается в окнеUser1
Мониторинг потоков в комнате¶
Для мониторинга потоков в комнате используется REST API
REST-запрос должен быть HTTP/HTTPS POST запросом в таком виде:
- HTTP:
http://wcs:8081/rest-api/sfu/stats
- HTTPS:
https://wcs:8444/rest-api/sfu/stats
Здесь:
wcs
- адрес WCS-сервера8081
- стандартный REST / HTTP порт WCS-сервера8444
- стандартный HTTPS портrest-api
- обязательная часть URL/sfu/stats
- используемый REST-метод
REST-методы и статусы ответа¶
/sfu/stats¶
Показать текущую статистику комнаты
Request example¶
POST /rest-api/mixer/startup HTTP/1.1
Host: localhost:8081
Content-Type: application/json
{
"roomName":"ROOM1"
}
Response example¶
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json
{
"participants": [
{
"nickName": "User1",
"outgoingTracks": [
{
"id": "9de9107c-ce5f-4d6b-b7d6-ea233d691d09",
"codec": "opus",
"bitrate": 0,
"sampleRate": 48000,
"channels": 2,
"alive": true,
"type": "AUDIO"
},
{
"id": "237dcef9-c66d-4c72-bd43-0c91aaea3b7e",
"composite": true,
"tracks": {
"h send": {
"id": "237dcef9-c66d-4c72-bd43-0c91aaea3b7e",
"codec": "H264",
"width": 1280,
"height": 720,
"fps": 30,
"bitrate": 157976,
"alive": true,
"type": "VIDEO"
},
"m send": {
"id": "237dcef9-c66d-4c72-bd43-0c91aaea3b7e",
"codec": "H264",
"width": 640,
"height": 360,
"fps": 30,
"bitrate": 263952,
"alive": true,
"type": "VIDEO"
}
}
}
],
"incomingTracks": {
"3c2dcd1c-7acd-4b90-8871-331be80cade0": "h send"
}
},
{
"nickName": "User2",
"outgoingTracks": [
{
"id": "3c2dcd1c-7acd-4b90-8871-331be80cade0",
"composite": true,
"tracks": {
"h send": {
"id": "3c2dcd1c-7acd-4b90-8871-331be80cade0",
"codec": "H264",
"width": 1280,
"height": 720,
"fps": 30,
"bitrate": 238688,
"alive": true,
"type": "VIDEO"
},
"m send": {
"id": "3c2dcd1c-7acd-4b90-8871-331be80cade0",
"codec": "H264",
"width": 640,
"height": 360,
"fps": 30,
"bitrate": 265368,
"alive": true,
"type": "VIDEO"
}
}
}
],
"incomingTracks": {
"9de9107c-ce5f-4d6b-b7d6-ea233d691d09": null,
"237dcef9-c66d-4c72-bd43-0c91aaea3b7e": "h send"
}
}
]
}
Return codes¶
Code | Reason |
---|---|
200 | OK |
400 | Bad request |
500 | Internal error |
Параметры¶
Параметр |
Описание |
Пример |
---|---|---|
roomName |
Имя комнаты |
|
participants | Список участников комнаты | [] |
nickName |
Имя пользователя |
|
outgoingTracks | Список потоков, публикуемых пользователем | [] |
incomingTracks | Список потоков, проигрываемых пользователем | {} |
id | Идентификатор медиасессии | 9de9107c-ce5f-4d6b-b7d6-ea233d691d09 |
codec | Видео или аудио кодек | H264 |
width | Ширина картинки видео | 1280 |
heigth | Высота картинки видео | 720 |
fps | FPS видео | 30 |
bitrate | Битрейт видео или аудио, бит/с | 265368 |
sampleRate | Частота дискретизации аудио, Гц | 48000 |
channels | Количество каналов аудио | 2 |
alive | Поток активен | true |
type | Тип потока | VIDEO |
composite | Поток включает несколько дорожек | true |
tracks | Список дорожек в композитном потоке | {} |
Действия над SFU потоками на сервере¶
В сборке 5.2.1068 добавлена возможность отображения SFU потоков как обычных WebRTC потоков на сервере. Эта возможность включается настройкой
При этом для каждого участника будет создан поток с именем {room}-{participant}-VIDEO
для видео потока и {room}-{participant}-AUDIO
для аудио. Эти потоки видны в статистике
-----Stream Stats-----
...
streams_viewers=ROOM1-User1-AUDIO/0;ROOM1-User1-VIDEO/0
streams_synchronization=ROOM1-User1-AUDIO/0;ROOM1-User1-VIDEO/0
могут быть проиграны с сервера
записаны по REST API или добавлены в микшер.
При публикации экрана создается поток с именем {room}-{participant}-VIDEO-screen
, например
-----Stream Stats-----
...
streams_viewers=ROOM1-User1-AUDIO/0;ROOM1-User1-VIDEO-screen/0;ROOM1-User1-VIDEO/0
streams_synchronization=ROOM1-User1-AUDIO/0;ROOM1-User1-VIDEO-screen/0;ROOM1-User1-VIDEO/0
Если поток опубликован в нескольких качествах, на WCS будет доступен поток в максимальном качестве, которое публикуется в настоящее время, например 720p. Если это качество перестает публиковаться (например, ухудшается канал участника), будет произведено автоматическое переключение на следующее доступное качество, например 360p.
Ограничения¶
Если участник публикует более одного потока с камеры, на WCS будет доступен только один поток.
Поддержка TURN¶
Поскольку для публикации и проигрывания аудио и видео дорожек в браузере используется стандартный объект RTCPeerConnection
, работа через TURN сервер настраивается при создании этого объекта. Например, по умолчанию потоки в примере SFU Two Way Streaming публикуются напрямую:
Если необходимо использовать TURN сервер, например, встроенный TURN сервер WCS, код должен быть изменен следующим образом:
let connectionConfig = {
iceServers: [
{
urls: 'turn:wcs:3478?transport=tcp',
credential: 'coM77EMrV7Cwhyan',
username: 'flashphoner'
}
],
iceTransportPolicy: "relay"
};
pc = new RTCPeerConnection(connectionConfig);
...
Здесь:
wcs
- адрес WCS сервера;flashphoner
- имя пользователя встроенного TURN сервера по умолчанию;coM77EMrV7Cwhyan
- пароль встроенного TURN сервера по умолчанию
В этом случае медиа трафик пойдет через TURN сервер, встроенный в WCS.
VP9 support¶
Начиная со сборки WCS 5.2.1908 и SFU SDK build 2.0.268, при публикации и проигрывании SFU медиатрафика поддерживается кодек VP9
Для тех случаев, в которых кодек VP9 не поддерживается другой стороной (например, SIP звонки), он должен быть исключен
codecs_exclude_sip=mpeg4-generic,flv,mpv,h265,vp9
codecs_exclude_sip_rtmp=opus,g729,g722,mpeg4-generic,vp8,vp9,mpv,h265
Чтобы включить использование кодека VP9 для SFU, необходимо исключить для этого сценария кодеки H264 и VP8
codecs_exclude_sfu=alaw,ulaw,g729,speex16,g722,mpeg4-generic,telephone-event,h265,flv,mpv,vp8,h264,h265
Кодек VP9 дает возможность использовать SVC (одновременную публикацию нескольких качеств) на стороне браузера, указывая нужный scalabilityMode в настройках кодирования
{
"room": {
...
},
"media": {
"audio": {
"tracks": [
]
},
"video": {
"tracks": [{
"source": "camera",
"width": 1280,
"height": 720,
"codec": "vp9",
"encodings": [
{
"rid": "nonsense",
"active": true,
"scalabilityMode": "L1T3"
}
]
}]
}
}
}
В данном случае будет опубликована видео дорожка в одном разрешении (L1) с тремя FPS (T3). Полный список возможных режимов приведен здесь.
Ограничения¶
-
Не рекомендуется совмещать Simulcast (публикацию нескольких профилей кодирования) и SVC, поскольку такое сочетание может не поддерживаться браузером.
-
Для захвата экрана доступна публикация только в одном разрешении (L1), другие настройки игнорируются. Данное поведение зафиксировано на уровне WebRTC библиотеки и не зависит от используемого браузера.
Известные проблемы¶
1. При публикации потока с окна на экране вкладка браузера Chrome может закрыться¶
Публикация потока, захваченного с какого-либо из окон на экране в нескольких качествах, и сворачивание этого окна приводит к закрытию вкладки браузера Chrome
Симптомы
При сворачивании окна, которое захватывается в данный момент, вкладка Chrome, с которой производится публикация, закрывается
Решение
Баг в Chromium, приводивший к закрытию вкладки при публикации потока с экрана в нескольких качествах, был исправлен в версии Chrome 98.0.4736.0