![](https://habrastorage.org/files/57a/e36/91b/57ae3691b4204dbba9aa8810e014acbd.png)
В предыдущей статье мы описывали принципы разработки видеочата между браузером и Android — устройством. Теперь же попробуем усложнить задачу и заимплементить трехсторонний видеочат на следующих платформах: Google Chrome на десктопе, Android приложение на планшете, и iOS приложение для Apple iPhone.
Напомним два основных принципа построения видеочата:
- Каждый подключившийся пользователь может отправить (опубликовать) свой видеопоток на сервер.
- Пользователи знают имена видеопотоков друг-друга и имеют возможность их воспроизвести.
Таким образом, в видеочате из трех участников, каждому из участников придется воспроизводить по два видеопотока.
![](https://habrastorage.org/files/60d/c35/4d2/60dc354d2f2f42608d4c8ba81621c8b2.jpg)
Последовательность из девяти действий выглядит как показано ниже. Сначала участники публикуют свои видеопотоки, потом воспроизводят потоки друг друга.
Публикуют потоки
1. Alice: session.createStream({name:"stream_alice"}).publish();
2. Boris: session.createStream({name:"stream_boris"}).publish();
3. Anna: session.createStream({name:"stream_anna"}).publish();
Играют потоки
4. Alice: session.createStream({name:"stream_anna"}).play();
5. Alice: session.createStream({name:"stream_boris"}).play();
6. Boris: session.createStream({name:"stream_alice"}).play();
7. Boris session.createStream({name:"stream_anna"}).play();
8. Anna: session.createStream({name:"stream_alice"}).play();
9. Anna: session.createStream({name:"stream_boris"}).play();
От разработчика в данном случае требуется организовать передачу названий и статусов видеопотоков участникам видеочата. Это можно сделать на любой подходящей технологии, например PHP, websockets, Node.js и т.д., так как передача имени видеопотока ничем не отличается от передачи обычного текстового сообщения от одного пользователя к другому.
У потока может быть три основных статуса: PUBLISHING, PLAYING, STOPPED
Для успешного воспроизведения, запрашиваемый поток должен быть в активном статусе PUBLISHING.
![](https://habrastorage.org/files/114/611/109/1146111096154aef95808a40cb255e19.jpg)
На этой схеме показано, как именно можно реализовать обмен именами и статусами потоков, в упрощенном варианте, когда Алиса демонстрирует свой видеопоток Борису и Анне. Такая процедура занимает 8 шагов, и может быть названа сигналингом, т.к. В результате этой процедуры проводится согласование:
- Алиса отправляет видеопоток на WCS-сервер.
- Алиса получает от сервера подтверждение в виде статуса PUBLISHING
- Алиса отправляет Борису сообщение, о том, что ее поток готов к воспроизведению.
- Алиса отправляет Анне сообщение, о том, что ее поток готов к воспроизведению.
- Анна воспроизводит видеопоток с WCS-сервера.
- Анна получает подтверждение статус PLAYING.
- Борис воспроизводит видеопоток с WCS-сервера.
- Борис получает подтверждение статус PLAYING.
В результате может быть реализован произвольный сценарий взаимодействия: с подключением двух и более пользователей к чату, с подключением просто зрителей, и т.д.
Комнаты
Организовать обмен именами видеопотоков и их статусами не так уж и сложно технически, но это требует определенных трудозатрат и работы с кодом.
С другой стороны, для такой задачи напрашивается какое-то универсальное решение, которое могло бы помочь пользователям быстро согласовать потоки и попасть в чат. Такое решение называется Комнаты или Room API.
Действительно, если двое или более пользователей взаимодействуют в одном контексте, то это похоже на комнату. Внутри комнаты пользователи видят видеопотоки друг-друга, знают кто находится в комнате и могут обмениваться сообщениями, в том числе и приватными.
Таким образом, имеем четыре объекта, которые полностью покрывают работу с комнатами:
- Room — комната
- Stream — видеопоток
- Participant — участник
- Message — сообщение
![](https://habrastorage.org/files/ac0/a01/728/ac0a017285d64b3aadae45027e8242eb.jpg)
Room API дает возможность кроссплатформенно использовать перечисленные выше абстракции: Room, Stream, Participant и Message для реализации следующих функций:
Подключение
- Пользователь может подключиться к комнате.
- Пользователь задает название комнаты при подключении.
- Если комната с таким названием существует, то пользователь попадает в эту комнату.
- Если комнаты с таким названием нет, то создается новая комната и пользователь попадает во вновь созданную комнату.
- Пользователь получает уведомления о подключениях / отключениях других участников.
- Пользователь может получить список участников.
Стриминг
- Пользователь может опубликовать видеопоток внутри комнаты.
- Пользователь получает уведомления о статусах видеопотоков других участников.
- Пользователь может воспроизвести видеопоток внутри комнаты.
Сообщения
- Пользователи могут обмениваться сообщениями внутри комнаты
- Пользователи могут обмениваться изображениями или другим контентом, если он упакован в текстовый формат
- Сообщение можно отправить одному или нескольким участникам
Room API
Для Web платформы, комнаты были реализованы в виде JavaScript — модуля со следующими основными функциями:
1. Получаем соединение с сервером.
var connection = Flashphoner.roomApi.connect({urlServer: "wss://host:8443", username: "Alice"});
2. Входим в комнату.
connection.join({name: "room1"});
3. Получаем список участников комнаты.
var participants = room.getParticipants();
4. Отправляем свой видеопоток в комнату.
room.publish({
display: document.getElementById("localDisplay"),
constraints: constraints,
record: false,
receiveVideo: false,
receiveAudio: false
});
5. Воспроизводим поток участника.
participant.getStreams()[0].play(document.getElementById(pDisplay))
6. Следим за участниками комнаты:
connection.on(ROOM_EVENT.JOINED, function(participant){...});
connection.on(ROOM_EVENT.LEFT, function(participant){...});
connection.on(ROOM_EVENT.PUBLISHED, function(participant){...});
JOINED — к комнате присоединился новый участник
LEFT — участник вышел
PUBLISHED — участник опубликовал свой видеопоток
7. Получаем сообщения от других участников.
connection.on(ROOM_EVENT.MESSAGE, function(participant){...});
8. Отправляем приватное сообщение конкретному участнику
participants[i].sendMessage(message);
9. Отправляем сообщение всем участникам сразу.
var participants = room.getParticipants();
for (var i = 0; i < participants.length; i++) {
participants[i].sendMessage(message);
}
}
Таким образом, реализация комнат дает простой обмен сообщениями и статусами всех подключенных к комнате участников.
Ограничения Room API
Вся логика при работе с комнатами ложится на клиента. Сервер управляет только только базовым функционалом комнаты:
- уведомления о подключении / отключении пользователей в комнате
- уведомления о создании / отключении видеопотоков пользователями внутри комнаты
- маршрутизация сообщений указанным участникам
Таким образом, аутентификация, права доступа, роли участников (модератор, зритель, ведущий), и другая логика, должны быть реализованы на клиенте и / или стороннем бэк-энде. Комнаты лишь помогают произвести быстрый обмен информацией о видеопотоках и статусах.
Комнаты для Web, Android, iOS
В каждой из SDK (Web, Android, iOS) для работы с сервером, есть API для работы с комнатами.
Примеры входа в комнату:
Web SDK
connection.join({name: "room1"});
Android SDK
Room room = roomManager.join(roomOptions);
iOS SDK
room = [roomManager join:options];
Таким образом в одну и ту же комнату может войти три участника с трех разных платформ:
- Web — браузер
- Мобильное приложение для Android
- Мобильное приложение для iOS
Тестовые приложения для работы с комнатами
Ниже мы приведем три тестовых приложения для работы с комнатами. Каждое из них имеет открытый код и может быть собрано из исходников.
Каждое из следующих приложений позволяет обмениваться видеопотоками и сообщениями трём участникам:
- Conference for Web
- Conference for Android
- Conference for iOS
Conference for Web
Код этого приложения доступен для скачивания здесь.
В HTML-коде можно найти два div-элемента
<div id="participant1Display" class="display"></div>
<div id="participant2Display" class="display"></div>
Эти элементы отвечают за отображение видео участников.
div — элемент localDisplay отвечает за отображение видео, захваченного с камеры.
<div id="localDisplay" class="fp-localVideo"></div>
С помощью кнопок Join / Leave можно войти и выйти из комнаты соответственно. С помощью Stop / Start можно отправить видео в комнату или остановить вещание. Поле Login должно быть уникальным, т.к. идентифицирует участника.
![](https://habrastorage.org/files/76b/79f/ba8/76b79fba8b574b4fb92fb9492fdd657c.jpg)
Следующий элемент интерфейса — это текстовый чат. Этот чат отображает сообщения полученные или отправленные другими пользователями, а также отображает информацию о событиях, происходящих в комнате.
![](https://habrastorage.org/files/056/781/d42/056781d4247b40d39c86283ada7afcdf.jpg)
И последний элемент — это ссылка на приглашение. Если пользователь вошел первым, создается новая комната. В данном случае с именем roomName=room-fb41b7. Если второй пользователь укажет этот же roomName, он попадет в ту же комнату. В приложении Conference for Web приглашения реализованы генерацией ссылки входа, содержащей roomName в качестве параметра. В версиях приложения для Android и iOS, имя комнаты указывается напрямую в интерфейсе.
![](https://habrastorage.org/files/9a3/2dd/ef3/9a32ddef317b44ae811938fe2718c90d.png)
Таким образом, тестовое приложение Conference for Web реализует все заложенные выше функции комнат и позволяет нескольким пользователям подключиться к одной и той же комнате и обмениваться видеопотоками и текстовыми сообщениями.
Ниже на скриншоте показано как работает комната с тремя участниками. Было открыто три вкладки браузера Google Chrome и на каждой из вкладок было инициировано подключение к комнате.
![](https://habrastorage.org/files/26c/f66/5ba/26cf665baedc401ca966e3df71144a90.png)
Conference for Android
Код этого приложения доступен для скачивания здесь.
В приложении можно ввести имя комнаты прямо из UI. В остальном приложение очень похоже на Conference for Web, которое было описано выше и имеет те же элементы интерфейса:
- Кнопки Leave / Join для входа и выхода из комнаты.
- Два видео окна для воспроизведения видео участников.
- Одно видео окно для отображения захвата видео с камеры.
- Текстовый чат с системной информацией и сообщениями участников
![](https://habrastorage.org/files/481/728/096/4817280966fc47eea014790a1bf4c026.jpg)
Conference for iOS
Код приложения доступен для скачивания здесь.
Интерфейс приложения для iOS уже практически ничем не отличается от приложения под Android, с точностью до названия кнопок и контролов.
В итоге мы сделали тест и собрали все три платформы в одной комнате с номером 3119d6.
Браузер Google Chrome — это заяц, который выбирается из норы:
![](https://habrastorage.org/files/3ee/e89/353/3eee89353e504c84a7a69cdac62daf36.png)
Android 5.1.1 на планшете Asus — это цветочный горшок.
![](https://habrastorage.org/files/aab/774/251/aab77425163e41a8bf42cf40351afad8.png)
iOS 10.1.1 на iPhone 6 — это Фикус Бенджамина на подоконнике.
![](https://habrastorage.org/files/a8d/1df/bf7/a8d1dfbf7bf1470597f3773664c54691.png)
Ниже показан полный скриншот с iOS — устройства:
![](https://habrastorage.org/files/38d/c02/28e/38dc0228e2e14460be6590bd8486f869.png)
Таким образом, мы завершили тестирование и обзор всех трех приложений, построенных на основе Room API, и можем переходить к исходному коду и сборке.
![](https://habrastorage.org/files/80b/37c/892/80b37c892d2948289dc0a1a112d75430.png)
Сборка приложения Conference for iOS из исходников
В предыдущей статье мы показывали как собрать пример видеочата под андроид и объясняли как устроен код видеочата в браузере.
Здесь покажем как собрать пример Conference for iOS и опишем основные куски кода примера.
Первым делом нужно обзавестись Mac-железом и установить последний Xcode.
Процедура сборки требует установки Cocoapods, скачивания кода примеров и SDK для iOS. Собирать будем в терминале, а потом откроем проект в Xcode.
1. Устанавливаем Cocoapods
sudo gem install cocoapods
2. Скачиваем все примеры с github
git clone https://github.com/flashphoner/wcs-ios-sdk-samples.git
3. Скачиваем iOS SDK
wget https://flashphoner.com/downloads/builds/flashphoner_client/wcs-ios-sdk/WCS-iOS-SDK-2.3.0.tar.gz
4. Распаковываем архив
tar -xvzf WCS-iOS-SDK-2.3.0.tar.gz
![](https://habrastorage.org/files/af9/b76/a9c/af9b76a9c1c5441dac8ec70f58b29f27.png)
5. Копируем папку FPWCSApi2.framework в примеры
cp -R FPWCSApi2.framework wcs-ios-sdk-samples
6. Запускаем сборку.
./build_example.sh
Если сборка прошла успешно, в терминале выводится **ARCHIVE SUCCEDED**
![](https://habrastorage.org/files/ed3/b0a/604/ed3b0a6040a641c5a550df5bbc89a0f4.png)
После того как примеры собраны из консоли с помощью Cocoapods, подтянуты и сконфигурированы все зависимости и дальнейшие сборки примеров можно проводить непосредственно из Xcode.
7. Открываем WCSExample.xcworkspace в Xcode
![](https://habrastorage.org/files/a83/edf/ba9/a83edfba9c7b45b895ebaf5f412bca99.png)
8. Выбираем Generic iOS Device в целях сборки. Запускаем сборку примера Conference из меню Product / Build и дожидаемся завершения.
![](https://habrastorage.org/files/2de/3fa/e88/2de3fae888c64dc58030d3dd33f8574b.png)
9. Подключаем iPhone по USB и запускаем собранное приложение Conference. В консоли появляется отладочная информация.
![](https://habrastorage.org/files/840/7e3/075/8407e3075f1346289197570b1589157c.png)
10. На экране iPhone появляется приложение Conference
![](https://habrastorage.org/files/bcc/196/f1e/bcc196f1edf24ae9999f550d3fb7fb66.png)
Таким образом, мы собрали мобильное приложение Conference для iOS из исходников и использовали iOS SDK версии 2.3.0 + Cocoapods для этой сборки. В результате мы смогли запустить это приложение на iPhone 6, подключенном по USB к Mac, на котором производилась эта сборка.
Код для Web, Android, iOS видеочатов
Выше мы привели примеры приложений для трех платформ, которые используют Room API и обмениваются видеопотоками внутри созданной комнаты. Попытаемся кратко перечислить основные куски кода, отвечающие за работу видеочата в каждой из этих трех платформ:
Web | Android | iOS | |
Код | JavaScript | Java | Objective-C |
Основной код | conference.js | ConferenceActivity.java | ViewController.m |
Подключение к серверу |
|
|
|
Подключение к комнате |
|
|
|
Получение списка участников |
|
|
|
Отправка видеопотока в комнату |
|
|
|
Воспроизводим видеопоток участника |
|
|
|
Отслеживаем присоединение новых участников к комнате |
|
|
|
Отслеживаем покидание участниками комнаты |
|
|
|
Отслеживаем публикацию видеопотока участником комнаты |
|
|
|
Получаем входящее сообщение от других участников |
|
|
|
Отправляем сообщение одному из участников |
|
|
|
Итого получаем по 10 основных конструкций на каждую из платформ. Каждую из перечисленных конструкций вы сможете найти в соответствующем файле с кодом.
Все три приложения Web, iOS и Android были протестированы с последней сборкой Web Call Server 5 — сервера для видеочатов и low-latency трансляций с поддержкой технологии WebRTC.
Ссылки
Web Call Server — сервер для WebRTC видеочатов
EC2 launch — запуск готового образа на Amazon EC2
Install — установка сервера на VPS или Dedicated хост
Cocoapods — менеджер зависимостей для сборки
Web SDK | Android SDK | iOS SDK | |
SDK | html | html | html |
Скачать SDK | tar.gz | aar | tar.gz |
Пример приложения чата с комнатами | WCS demo | Google Play | Только Ad hoc |
Основной файл кода примера | Conference.js | ConferenceActivity.java | ViewController.m |
Исходный код всех примеров | github | github | github |
Описание процедуры сборки примеров из исходного кода | html | html | html |
Описание кода примера с комнатами Conference | html | html |