- PVSM.RU - https://www.pvsm.ru -

Разработка WebRTC видеочата между iOS, Android и браузером

Разработка WebRTC видеочата между iOS, Android и браузером - 1

В предыдущей статье [1] мы описывали принципы разработки видеочата между браузером и Android — устройством. Теперь же попробуем усложнить задачу и заимплементить трехсторонний видеочат на следующих платформах: Google Chrome на десктопе, Android приложение на планшете, и iOS приложение для Apple iPhone.

Напомним два основных принципа построения видеочата:

  1. Каждый подключившийся пользователь может отправить (опубликовать) свой видеопоток на сервер.
  2. Пользователи знают имена видеопотоков друг-друга и имеют возможность их воспроизвести.

Таким образом, в видеочате из трех участников, каждому из участников придется воспроизводить по два видеопотока.

Разработка WebRTC видеочата между iOS, Android и браузером - 2

Последовательность из девяти действий выглядит как показано ниже. Сначала участники публикуют свои видеопотоки, потом воспроизводят потоки друг друга.

Публикуют потоки

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.

Разработка WebRTC видеочата между iOS, Android и браузером - 3

На этой схеме показано, как именно можно реализовать обмен именами и статусами потоков, в упрощенном варианте, когда Алиса демонстрирует свой видеопоток Борису и Анне. Такая процедура занимает 8 шагов, и может быть названа сигналингом, т.к. В результате этой процедуры проводится согласование:

  1. Алиса отправляет видеопоток на WCS-сервер.
  2. Алиса получает от сервера подтверждение в виде статуса PUBLISHING
  3. Алиса отправляет Борису сообщение, о том, что ее поток готов к воспроизведению.
  4. Алиса отправляет Анне сообщение, о том, что ее поток готов к воспроизведению.
  5. Анна воспроизводит видеопоток с WCS-сервера.
  6. Анна получает подтверждение статус PLAYING.
  7. Борис воспроизводит видеопоток с WCS-сервера.
  8. Борис получает подтверждение статус PLAYING.

В результате может быть реализован произвольный сценарий взаимодействия: с подключением двух и более пользователей к чату, с подключением просто зрителей, и т.д.

Комнаты

Организовать обмен именами видеопотоков и их статусами не так уж и сложно технически, но это требует определенных трудозатрат и работы с кодом.

С другой стороны, для такой задачи напрашивается какое-то универсальное решение, которое могло бы помочь пользователям быстро согласовать потоки и попасть в чат. Такое решение называется Комнаты или Room API.

Действительно, если двое или более пользователей взаимодействуют в одном контексте, то это похоже на комнату. Внутри комнаты пользователи видят видеопотоки друг-друга, знают кто находится в комнате и могут обмениваться сообщениями, в том числе и приватными.

Таким образом, имеем четыре объекта, которые полностью покрывают работу с комнатами:

  • Room — комната
  • Stream — видеопоток
  • Participant — участник
  • Message — сообщение

Разработка WebRTC видеочата между iOS, Android и браузером - 4

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

Код этого приложения доступен для скачивания здесь [2].

В 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 должно быть уникальным, т.к. идентифицирует участника.

Разработка WebRTC видеочата между iOS, Android и браузером - 5

Следующий элемент интерфейса — это текстовый чат. Этот чат отображает сообщения полученные или отправленные другими пользователями, а также отображает информацию о событиях, происходящих в комнате.

Разработка WebRTC видеочата между iOS, Android и браузером - 6

И последний элемент — это ссылка на приглашение. Если пользователь вошел первым, создается новая комната. В данном случае с именем roomName=room-fb41b7. Если второй пользователь укажет этот же roomName, он попадет в ту же комнату. В приложении Conference for Web приглашения реализованы генерацией ссылки входа, содержащей roomName в качестве параметра. В версиях приложения для Android и iOS, имя комнаты указывается напрямую в интерфейсе.

Разработка WebRTC видеочата между iOS, Android и браузером - 7

Таким образом, тестовое приложение Conference for Web реализует все заложенные выше функции комнат и позволяет нескольким пользователям подключиться к одной и той же комнате и обмениваться видеопотоками и текстовыми сообщениями.

Ниже на скриншоте показано как работает комната с тремя участниками. Было открыто три вкладки браузера Google Chrome и на каждой из вкладок было инициировано подключение к комнате.

Разработка WebRTC видеочата между iOS, Android и браузером - 8

Conference for Android

Код этого приложения доступен для скачивания здесь [3].

В приложении можно ввести имя комнаты прямо из UI. В остальном приложение очень похоже на Conference for Web, которое было описано выше и имеет те же элементы интерфейса:

  • Кнопки Leave / Join для входа и выхода из комнаты.
  • Два видео окна для воспроизведения видео участников.
  • Одно видео окно для отображения захвата видео с камеры.
  • Текстовый чат с системной информацией и сообщениями участников

Разработка WebRTC видеочата между iOS, Android и браузером - 9

Conference for iOS

Код приложения доступен для скачивания здесь [4].

Интерфейс приложения для iOS уже практически ничем не отличается от приложения под Android, с точностью до названия кнопок и контролов.

В итоге мы сделали тест и собрали все три платформы в одной комнате с номером 3119d6.

Браузер Google Chrome — это заяц, который выбирается из норы:

Разработка WebRTC видеочата между iOS, Android и браузером - 10

Android 5.1.1 на планшете Asus — это цветочный горшок.

Разработка WebRTC видеочата между iOS, Android и браузером - 11

iOS 10.1.1 на iPhone 6 — это Фикус Бенджамина на подоконнике.

Разработка WebRTC видеочата между iOS, Android и браузером - 12

Ниже показан полный скриншот с iOS — устройства:

Разработка WebRTC видеочата между iOS, Android и браузером - 13

Таким образом, мы завершили тестирование и обзор всех трех приложений, построенных на основе Room API, и можем переходить к исходному коду и сборке.

Разработка WebRTC видеочата между iOS, Android и браузером - 14

Сборка приложения Conference for iOS из исходников

В предыдущей статье [1]мы показывали как собрать пример видеочата под андроид и объясняли как устроен код видеочата в браузере.

Здесь покажем как собрать пример Conference for iOS и опишем основные куски кода примера.

Первым делом нужно обзавестись Mac-железом и установить последний Xcode.

Процедура сборки требует установки Cocoapods [5], скачивания кода примеров и 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

Разработка WebRTC видеочата между iOS, Android и браузером - 15

5. Копируем папку FPWCSApi2.framework в примеры

cp -R FPWCSApi2.framework wcs-ios-sdk-samples

6. Запускаем сборку.

./build_example.sh

Если сборка прошла успешно, в терминале выводится **ARCHIVE SUCCEDED**

Разработка WebRTC видеочата между iOS, Android и браузером - 16

После того как примеры собраны из консоли с помощью Cocoapods, подтянуты и сконфигурированы все зависимости и дальнейшие сборки примеров можно проводить непосредственно из Xcode.

7. Открываем WCSExample.xcworkspace в Xcode

Разработка WebRTC видеочата между iOS, Android и браузером - 17

8. Выбираем Generic iOS Device в целях сборки. Запускаем сборку примера Conference из меню Product / Build и дожидаемся завершения.

Разработка WebRTC видеочата между iOS, Android и браузером - 18

9. Подключаем iPhone по USB и запускаем собранное приложение Conference. В консоли появляется отладочная информация.

Разработка WebRTC видеочата между iOS, Android и браузером - 19

10. На экране iPhone появляется приложение Conference

Разработка WebRTC видеочата между iOS, Android и браузером - 20

Таким образом, мы собрали мобильное приложение 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 [6] ConferenceActivity.java [7] ViewController.m [8]
Подключение к серверу
connection = Flashphoner.roomApi.connect({urlServer: url, username: username});
roomManager = Flashphoner.createRoomManager(roomManagerOptions);
roomManager = [FPWCSApi2 createRoomManager:options error:&error];
Подключение к комнате
connection.join({name: getRoomName()});
room = roomManager.join(roomOptions);
room = [roomManager join:options];
Получение списка участников
var participants = room.getParticipants();
room.getParticipants()
NSDictionary *participants = [room getParticipants];
Отправка видеопотока в комнату
room.publish({
display: document.getElementById("localDisplay"),
constraints: constraints,
record: false,
receiveVideo: false,
receiveAudio: false
});
stream = room.publish(localRenderer);
publishStream = [room publish:_localDisplay];
Воспроизводим видеопоток участника
participant.getStreams()[0].play(document.getElementById(pDisplay));
participant.play(participantView.surfaceViewRenderer);
[participant play:pv.display];
Отслеживаем присоединение новых участников к комнате
connection.on(ROOM_EVENT.JOINED, function(participant){...});
public void onJoined(final Participant participant){...};
[room on:kFPWCSRoomParticipantEventJoined participantCallback:^(FPWCSApi2Room *room, FPWCSApi2RoomParticipant *participant){...}]
Отслеживаем покидание участниками комнаты
connection.on(ROOM_EVENT.LEFT, function(participant){...});
public void onLeft(final Participant participant){...}
[room on:kFPWCSRoomParticipantEventLeft participantCallback:^(FPWCSApi2Room *room, FPWCSApi2RoomParticipant *participant){...}]
Отслеживаем публикацию видеопотока участником комнаты
connection.on(ROOM_EVENT.PUBLISHED, function(participant){...});
public void onPublished(final Participant participant){...}
[room on:kFPWCSRoomParticipantEventPublished participantCallback:^(FPWCSApi2Room *room, FPWCSApi2RoomParticipant *participant){...}]
Получаем входящее сообщение от других участников
connection.on(ROOM_EVENT.MESSAGE, function(participant){...});
public void onMessage(final Message message){...}
[room onMessageCallback:^(FPWCSApi2Room *room, FPWCSApi2RoomMessage *message){...}]
Отправляем сообщение одному из участников
participants[i].sendMessage(message);
participant.sendMessage(text);
[participant sendMessage:_messageBody.text];

Итого получаем по 10 основных конструкций на каждую из платформ. Каждую из перечисленных конструкций вы сможете найти в соответствующем файле с кодом.

Все три приложения Web, iOS и Android были протестированы с последней сборкой Web Call Server 5 — сервера для видеочатов и low-latency трансляций с поддержкой технологии WebRTC.

Ссылки

Web Call Server [9] — сервер для WebRTC видеочатов
EC2 launch [10] — запуск готового образа на Amazon EC2
Install [11] — установка сервера на VPS [12] или Dedicated хост
Cocoapods [5] — менеджер зависимостей для сборки

  Web SDK Android SDK iOS SDK
SDK html [13] html [14] html [15]
Скачать SDK tar.gz [16] aar [17] tar.gz [18]
Пример приложения чата с комнатами WCS demo [19] Google Play [20] Только Ad hoc
Основной файл кода примера Conference.js [6] ConferenceActivity.java [7] ViewController.m [8]
Исходный код всех примеров github [21] github [22] github [23]
Описание процедуры сборки примеров из исходного кода html [24] html [25] html [26]
Описание кода примера с комнатами Conference html [27] html [28]  

Автор: Flashphoner

Источник [29]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/android-development/251669

Ссылки в тексте:

[1] предыдущей статье: https://habrahabr.ru/company/flashphoner/blog/324914/

[2] здесь: https://github.com/flashphoner/flashphoner_client/tree/wcs_api-2.0/examples/demo/streaming/conference

[3] здесь: https://github.com/flashphoner/wcs-android-sdk-samples/tree/master/conference

[4] здесь: http://ttps://github.com/flashphoner/wcs-ios-sdk-samples/tree/master/WCSExample/Conference

[5] Cocoapods: https://cocoapods.org

[6] conference.js: https://github.com/flashphoner/flashphoner_client/blob/wcs_api-2.0/examples/demo/streaming/conference/conference.js

[7] ConferenceActivity.java: https://github.com/flashphoner/wcs-android-sdk-samples/blob/master/conference/src/main/java/com/flashphoner/wcsexample/conference/ConferenceActivity.java

[8] ViewController.m: https://github.com/flashphoner/wcs-ios-sdk-samples/blob/master/WCSExample/Conference/ViewController.m

[9] Web Call Server: https://flashphoner.com

[10] EC2 launch: https://aws.amazon.com/marketplace/pp/B01D1L5EAK

[11] Install: https://flashphoner.com/download/

[12] VPS: https://www.reg.ru/?rlink=reflink-717

[13] html: https://flashphoner.com/wcs-web-sdk

[14] html: https://flashphoner.com/wcs-android-sdk

[15] html: https://flashphoner.com/wcs-ios-sdk

[16] tar.gz: https://flashphoner.com/downloads/builds/flashphoner_client/wcs_api-2.0/flashphoner-api-0.5.18.1977-6db74501c8268c652a19522634836e0c7d35a6b5.tar.gz

[17] aar: https://flashphoner.com/downloads/builds/flashphoner_client/wcs-android-sdk/aar/wcs-android-sdk-1.0.1.26.aar

[18] tar.gz: https://flashphoner.com/downloads/builds/flashphoner_client/wcs-ios-sdk/WCS-iOS-SDK-2.3.0.tar.gz

[19] WCS demo: https://wcs5-eu.flashphoner.com/demo2/conference

[20] Google Play: https://play.google.com/store/apps/details?id=com.flashphoner.wcsexample.conference

[21] github: https://github.com/flashphoner/flashphoner_client/tree/wcs_api-2.0

[22] github: https://github.com/flashphoner/wcs-android-sdk-samples

[23] github: https://github.com/flashphoner/wcs-ios-sdk-samples

[24] html: https://flashphoner.com/docs/wcs5/wcs_docs/html/ru/wcs-developer-guide-2/index.html?quick_start_web_sdk.htm

[25] html: https://flashphoner.com/docs/wcs5/wcs_docs/html/ru/wcs-developer-guide-2/index.html?quick_start_android_sdk.htm

[26] html: https://flashphoner.com/docs/wcs5/wcs_docs/html/ru/wcs-developer-guide-2/index.html?quick_start_ios_sdk.htm

[27] html: https://flashphoner.com/docs/wcs5/wcs_docs/html/ru/wcs-developer-guide-2/index.html?video_conference_web_sdk.htm

[28] html: https://flashphoner.com/docs/wcs5/wcs_docs/html/ru/wcs-developer-guide-2/index.html?video_conference_android_sdk.htm

[29] Источник: https://habrahabr.ru/post/325444/