Работа с комнатами¶
Описание¶
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.ESTABLISHEDcode
-
Вход в чат-комнату участника 1
Session.join()code
-
Получение участником 1 от сервера события, описывающего состояние комнаты
ROOM_EVENT.STATEcode
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.PUBLISHINGcode
-
Отправка участником 1 потока по WebRTC
-
Установка участником 2 соединения с сервером
-
Получение участником 2 от сервера события, подтверждающего успешное соединение
-
Вход в чат-комнату участника 2
-
Получение участником 2 от сервера события, описывающего состояние комнаты
-
Получение участником 1 от сервера события о присоединении участника 2
ROOM_EVENT.JOINEDcode
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.LEFTcode
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()