Работа с комнатами¶
Описание¶
Web Call Server позволяет внедрить видеочат, который будет работать в большинстве современных веб-браузеров без установки дополнительного ПО, а также на мобильных устройствах, в ваш веб-проект.
Поддерживаемые платформы и браузеры¶
Chrome | Firefox | Safari | Edge | |
---|---|---|---|---|
Windows | ✅ | ✅ | ❌ | ✅ |
Mac OS | ✅ | ✅ | ✅ | ✅ |
Android | ✅ | ✅ | ❌ | ✅ |
iOS | ✅ | ✅ | ✅ | ✅ |
Поддерживаемые кодеки¶
- Видео: H.264, VP8
- Аудио: Opus, G.711
Функции¶
- Видеочат
- Текстовый чат
- Видеоконференция
- Видеоконференция с отображением экрана пользователя
Схема работы¶
- Браузер участника 1 соединяется с сервером по Websocket и отправляет команду
join
- Браузер участника 1 может передавать поток по WebRTC для публикации в чат-комнате и получать потоки, опубликованные в комнате
- Браузер участника 2 соединяется с сервером при помощи Flash и отправляет команду
join
- Браузер участника 2 может передавать поток по RTMP для публикации в чат-комнате и получать потоки, опубликованные в комнате
Тестирование¶
Тест видеоконференции¶
-
Для теста используем:
- демо-сервер
demo.flashphoner.com
- веб-приложение Conference для организации видеоконференции
- демо-сервер
-
Откройте веб-приложение
Conference
. В полеLogin
введите произвольное имя пользователя, напримерtest
:
-
Нажмите кнопку
Join
. Установится соединение с сервером, отобразится надписьESTABLISHED
, будет автоматически создана чат-комната:
Внизу экрана отобразится изображение с веб-камеры, текстовый чат и ссылка на комнату для приглашения других пользователей:
-
Скопируйте ссылку на чат-комнату и откройте ее в другой вкладке браузера. Введите имя пользователя, которое должно отличаться от имени создателя чат-комнаты, например,
test2
, и нажмите кнопкуJoin
. На странице будет показано изображение с веб-камеры участникаtest
(слева) и с веб-камеры участникаtest2
(внизу):
-
Введите в окне текстового чата участника
test2
сообщение и нажмите кнопкуSend
:
-
На вкладке участника
test
введите ответное сообщение:
-
Убедитесь, что ответ получен:
-
Для выхода из-чат-комнаты нажмите кнопку
Leave
Тест видеочата¶
-
Для теста используем:
- демо-сервер
demo.flashphoner.com
- веб-приложение Two Way Video Chat для организации видеочата
- демо-сервер
-
Откройте веб-приложение Two Way Video Chat. В поле
Login
введите произвольное имя пользователя, напримерtest
:
-
Нажмите кнопку
Join
. Установится соединение с сервером, отобразится надписьESTABLISHED
, будет автоматически создана чат-комната. Будет показано изображение с веб-камеры:
Внизу экрана отобразится текстовый чат и ссылка на комнату для приглашения других пользователей:
-
Скопируйте ссылку на чат-комнату и откройте ее в другой вкладке браузера. Введите имя пользователя, которое должно отличаться от имени создателя чат-комнаты, например,
test2
, и нажмите кнопкуJoin
. На странице будет показано изображение с веб-камеры пользователяtest
крупно и с веб-камеры пользователяtest2
(внизу слева):
-
Введите в окне текстового чата сообщение и нажмите кнопку
Send
:
-
На вкладке пользователя test введите ответное сообщение:
-
Убедитесь, что ответ получен:
8 Для выхода из-чат-комнаты нажмите кнопку Leave
Тест видеоконференции с отображением экрана компьютера¶
-
Для теста используем:
- демо-сервер
demo.flashphoner.com
- веб-приложение Two Way Video Chat and Screen Sharing для организации видеоконференции
- браузер Chrome
- демо-сервер
-
Откройте веб-приложение Two Way Video Chat and Screen Sharing. В поле
Login
введите произвольное имя пользователя, напримерtest
. Нажмите кнопкуJoin
. Установится соединение с сервером, отобразится надписьESTABLISHED
, будет автоматически создана чат-комната. Будет показано изображение с веб-камеры:
-
Скопируйте ссылку на чат-комнату и откройте ее в другой вкладке браузера. Введите имя пользователя, которое должно отличаться от имени создателя чат-комнаты, например,
test2
, и нажмите кнопкуJoin
. На странице будет показано изображение с веб-камеры
-
Нажмите кнопку
Share
и разрешите браузеру доступ к экрану или к окну приложения:
-
На вкладке пользователя
test
отобразится экран или окно приложения, к которому был разрешен доступ:
-
Для выхода из-чат-комнаты нажмите кнопку
Leave
Последовательность выполнения операций¶
Ниже описана последовательность вызовов при использовании примера Conference
-
Установка участником 1 соединения с сервером
RoomApi.connect()
code
connection = RoomApi.connect({urlServer: url, username: username}).on(SESSION_STATUS.FAILED, function(session){ setStatus('#status', session.status()); onLeft(); }).on(SESSION_STATUS.DISCONNECTED, function(session) { setStatus('#status', session.status()); onLeft(); }).on(SESSION_STATUS.ESTABLISHED, function(session) { setStatus('#status', session.status()); joinRoom(); });
-
Получение участником 1 от сервера события, подтверждающего успешное соединение
SESSION_STATUS.ESTABLISHED
code
-
Вход в чат-комнату участника 1
Session.join()
code
-
Получение участником 1 от сервера события, описывающего состояние комнаты
ROOM_EVENT.STATE
code
connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){ var participants = room.getParticipants(); console.log("Current number of participants in the room: " + participants.length); if (participants.length >= _participants) { console.warn("Current room is full"); $("#failedInfo").text("Current room is full."); room.leave().then(onLeft, onLeft); return false; } setInviteAddress(room.name()); if (participants.length > 0) { var chatState = "participants: "; for (var i = 0; i < participants.length; i++) { installParticipant(participants[i]); chatState += participants[i].name(); if (i != participants.length - 1) { chatState += ","; } } addMessage("chat", chatState); } else { addMessage("chat", " room is empty"); } publishLocalMedia(room); onJoined(room); ... });
-
Публикация медиапотока участником 1
Room.publish()
code
-
Получение участником 1 от сервера события, подтверждающего успешную публикацию потока
STREAM_STATUS.PUBLISHING
code
-
Отправка участником 1 потока по WebRTC
-
Установка участником 2 соединения с сервером
-
Получение участником 2 от сервера события, подтверждающего успешное соединение
-
Вход в чат-комнату участника 2
-
Получение участником 2 от сервера события, описывающего состояние комнаты
-
Получение участником 1 от сервера события о присоединении участника 2
ROOM_EVENT.JOINED
code
connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){ ... }).on(ROOM_EVENT.JOINED, function(participant){ installParticipant(participant); addMessage(participant.name(), "joined"); }).on(ROOM_EVENT.LEFT, function(participant){ ... }).on(ROOM_EVENT.PUBLISHED, function(participant){ ... }).on(ROOM_EVENT.FAILED, function(room, info){ ... }).on(ROOM_EVENT.MESSAGE, function(message){ ... });
-
Получение участником 2 потока, опубликованного участником 1
-
Публикация медиапотока участником 2
-
Получение участником 2 от сервера события, подтверждающего успешную публикацию потока
-
Отправка участником 2 потока по WebRTC и получение его участником 1
-
Выход участника 1 из чат-комнаты
Room.leave()
code
-
Получение участниками комнаты от сервера события о выходе участника 1
ROOM_EVENT.LEFT
code
connection.join({name: getRoomName()}).on(ROOM_EVENT.STATE, function(room){ ... }).on(ROOM_EVENT.JOINED, function(participant){ ... }).on(ROOM_EVENT.LEFT, function(participant){ //remove participant removeParticipant(participant); addMessage(participant.name(), "left"); }).on(ROOM_EVENT.PUBLISHED, function(participant){ ... }).on(ROOM_EVENT.FAILED, function(room, info){ ... }).on(ROOM_EVENT.MESSAGE, function(message){ ... });
Запись потоков, опубликованных участниками конференции¶
Видеопотоки, опубликованные каждым из участников конференции, могут быть записаны. Для этого необходимо установить параметр record
в true
при публикации потока:
Поток от каждого участника записывается в отдельный файл. Особенность этих файлов при дальнейшей обработке в том, что публикация начинается не одновременно.
Синхронизация потоков, опубликованных участниками комнаты¶
Warning
Данная возможность не поддерживается, начиная со сборки 5.2.142. Используйте микширование или запись потоков в один файл.
Для того, чтобы дать возможность объединить потоки участников, потоки комнаты могут быть синхронизированы по первому опубликованному потоку. Эта возможность включается при помощи параметра в файле flashphoner.properties
Например, если участник User1
начал публиковать поток в 00:00:10, а участник User2
в 00:00:55, то второй пользователь получит в начале записи 45 секунд пустого видео (черный экран и тишина). Таким образом, файлы записи потоков User1.mp4
и User2.mp4
будут одинаковы по времени, и их можно будет объединить.
Объединение синхронизированных записей потоков при помощи ffmpeg¶
Синхронизированные файлы записей потоков могут быть объединены при помощи ffmpeg с сохранением хронологического порядка. Для этого при создании потока на стороне сервера фиксируется его сдвиг относительно времени создания комнаты. Записанные таким образом файлы потоков объединяются командой (пример для двух участников)
ffmpeg -i stream1.mp4 -i stream2.mp4 -filter_complex "[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid];[0:a][1:a]amerge[a]" -map [vid] -map "[a]" -ac 2 -strict -2 -c:v libx264 -crf 23 -preset veryfast output.mp4
Здесь
stream1
- поток первого участникаstream2
- поток второго участника
Запись потоков комнаты в один файл с последующим микшированием¶
В сборке WCS 5.2.1012 и сборке WebSDK 2.0.190 добавлена возможность записывать все потоки комнаты в один файл, с его автоматическим микшированием по окончании конференции. Для этого первый участник при создании комнаты должен указать опцию record
:
В этом случае все потоки в комнате будут записаны в один файл. При завершении комнаты запись также будет завершена, и автоматически запустится скрипт, указанный в настройке
который смикширует потоки в соответствии с настройками микшера, заданными в файле /usr/local/FlashphonerWebCallServer/conf/offline_mixer.json
, по
умолчанию
Тестирование записи комнаты¶
-
Для теста используем:
- ваш WCS сервер, напримерtest1.flashphoner.com
- веб-приложение Conference -
Откройте пример Conference в браузере, введите имя участника
Alice
и взведите переключательRecord
-
Нажмите
Join
. Начнется публикация потока
-
В другом окна браузера откройте ссылку из поля
Invite
-
Введите имя пользователя
Bob
и нажмитеJoin
-
Bob
присоединился к комнате
-
Нажмите
Leave
в окне пользователяAlice
и в окне пользователяBob
-
Микширование может занять продолжительное время, в зависимости от длительности записи, производительности процессора и жесткого диска сервера. По его окончании, загрузите файл из каталога
/usr/local/FlashphonerWebCallServer/records
или откройте в браузере по ссылке
Завершение комнаты¶
Комната существует на сервере до тех пор, пока в ней есть хотя бы один участник. Когда последний участник вызывает функцию Room.leave()
, комната завершается.
Если последний участник обновляет страницу или теряет соединение с сервером без вызова функции Room.leave()
, комната остается активной в течение времени, заданного настройкой в миллисекундах
По умолчанию, время составляет 60 секунд. По истечении этого времени, комната завершается.
Настройки контроля Websocket соединения в комнате¶
В сборке WebSDK 2.0.251 доступны следующие настройки контроля Websocket соединения в комнате на стороне клиента.
Максимальное время установки соединения:
connection = RoomApi.connect({urlServer: url, username: username, timeout: 1000}).on(SESSION_STATUS.FAILED, function(session){
...
});
Настройки обмена контрольными пакетами:
connection = RoomApi.connect({urlServer: url, username: username, receiveProbes: 5, pingInterval: 5000}).on(SESSION_STATUS.FAILED, function(session){
...
});
Известные проблемы¶
1. При обмене текстовыми сообщениями необходимо кодирование не-латинских символов¶
Симптомы
При отправке сообщения, содержащего не-латинские символы, эти символы преобразуются в знаки вопроса при получении
Решение
Использовать функции JavaScript encodeURIComponent()
при отправке сообщения
var participants = room.getParticipants();
for (var i = 0; i < participants.length; i++) {
participants[i].sendMessage(encodeURIComponent(message));
}
и decodeURIComponent()
при его получении
2. Следует избегать быстрого последовательного вызова Room.leave()
и затем Session.join()
¶
При быстром вызове Room.leave()
и затем Session.join()
для одного и того же участника возможна отправка серверу команды join
, в то время как сервер еще не обработал предыдущую команду leave
для этого пользователя
Симптомы
При вызове Session.join()
сразу после Room.leave()
клиент получает сообщение
Решение
Использовать интервал не менее 1 секунды между последовательными вызовами Room.leave()
и Session.join()