Об особенностях технологии разработки видео чатов и конференций WebRTC на Android.
Поможет разработчикам, начинающим интересоваться темой. Полезно управляющим и владельцам бизнеса, задумавшимся о разработке Android приложения с видеосвязью. В коде не разберетесь, но узнаете варианты разработки с плюсами и минусами, получите представление о задачах для программиста.
Вкратце о WebRTC
WebRTC — технология разработки видео чатов и конференций. Она позволяет создавать peer-to-peer соединение между мобильными устройствами и браузерами для передачи медиа потоков. Более подробную информацию, как она устроена и об общих принципах работы можно найти в нашей статье про WebRTC простым языком.
2 способа реализации видеосвязи с WebRTC на Android
- Самый простой и быстрый вариант — воспользоваться одним из множества коммерческих проектов, например, Twilio или LiveSwitch. Они предоставляют свои SDK для различных платформ и реализуют функциональность из коробки, но имеют минусы. Они платные и функционал ограничен: вы сможете сделать только те функции, которые в них есть, а не любые, какие придумаете.
- Другой вариант — использовать одну из существующих библиотек. Этот подход требует большего количества кода, но сэкономит деньги и даст большую гибкость в реализации функциональности. В этой статье мы рассмотрим второй вариант, а в качестве библиотеки используем https://webrtc.github.io/webrtc-org/native-code/android/
Создание соединения
Создание WebRTC-соединения состоит из двух этапов:
- Установка логического соединения — устройства должны договориться о формате данных, кодеках и т.п.
- Установка физического соединения — устройства должны знать адреса друг друга
Для начала отметим, что на этапе инициирования соединения, для обмена данными между устройствами, используется сигнальный механизм. В качестве сигнального механизма может выступать любой канал передачи данных — например, сокеты.
Предположим, мы хотим установить видеосвязь между двумя устройствами. Для этого нужно установить логическое соединение между ними.
Логическое соединение
Логическое соединение устанавливается с использованием Session Description Protocol (SDP), для этого один пир:
- Создает объект PeerConnection
- Формирует на SDP-offer — объект, содержащий данные о предстоящей сессии, и при помощи сигнального механизма отправляет его собеседнику.
В свою очередь, другой пир:
- Также создает объект PeerConnection
- При помощи сигнального механизма получает SDP-offer, отравленный первым пиром, и сохраняет его у себя
- Формирует SDP-answer и отправляет его обратно, также при помощи сигнального механизма
Первый пир, получив SDP-answer, сохраняет его у себя
После успешного обмена объектами SessionDescription, логическое соединение считается установленным.
Физическое соединение
Теперь необходимо установить физическое соединение между устройствами, что чаще всего является нетривиальной задачей. Обычно устройства в интернете не имеют публичных адресов, поскольку располагаются за роутерами и межсетевыми экранами. Для решения этой проблемы в WebRTC используется технология ICE (Interactive Connectivity Establishment).
Важной составляющей ICE являются Stun и Turn сервера. Они служат одной цели - установке связи между устройствами, которые не имеют публичных адресов.
Stun-сервер
Устройство делает запрос к Stun-серверу и в ответ получает свой публичный адрес. Далее, при помощи сигнального механизма отправляет его собеседнику. После того, как собеседник проделает то же самое, устройства узнают расположение друг друга в сети и будут готовы к передаче данных друг другу.
Turn-сервер
В некоторых случаях роутер может иметь ограничение “Symmetric NAT”. Это ограничение не позволит установить прямое соединение между устройствами. В этом случае используется Turn-сервер. Он выступает в качестве посредника и все данные идут через него. Подробнее можно почитать в документации по WebRTC от Mozilla.
Как мы увидели, STUN и TURN сервера играют важную роль в установке физического соединения между устройствами. Именно для этой цели мы, при создании объекта PeerConnection, передаем список с доступными ICE-серверами.
Для установки физического соединения один пир генерирует ICE-кандидаты - объекты, содержащие информацию о том, как устройство может быть найдено в сети, и отправляет их через сигнальный механизм собеседнику
Далее второй пир, через сигнальный механизм получая ICE-кандидаты первого пира, сохраняет их у себя. При этом он также генерирует свои ICE-кандидаты и отправляет их обратно
Теперь, когда пиры обменялись своими адресами, можно приступать к передаче и приему данных.
Получение данных
Библиотека, после установки логического и физического соединений с собеседником, вызовет колбэк onAddTrack и передаст в него объект MediaStream, содержащий VideoTrack и AudioTrack собеседника
Дальше мы должны получить VideoTrack из MediaStream и отобразить его на экране.
Для отображения VideoTrack, необходимо передать ему объект, реализующий интерфейс VideoSink. Для этих целей библиотека предоставляет класс SurfaceViewRenderer.
Для получения звука собеседника нам не нужно делать ничего дополнительного — библиотека все сделает за нас. Но все же, если мы хотим более тонкой настройки звука, можно получить объект AudioTrack и через него менять настройки аудио
Например, следующим образом мы можем замьютить собеседника
Отправка данных
Отправка видео и аудио со своего устройства также начинается с создания объекта PeerConnection и отправки IceCandidate-ов. Но в отличие от создания SDPOffer при получении видеопотока собеседника, в данном случае мы должны сначала создать объект MediaStream, который включает в себя AudioTrack и VideoTrack.
Для отправки своих аудио и видеопотоков, нужно создать объект PeerConnection, после чего при помощи сигнального механизма обменяться IceCandidate и SDP пакетами. Но вместо того, чтобы получить от библиотеки медиапоток собеседника, мы должны получить медиапоток нашего устройства и передать его в библиотеку, чтобы она передала его нашему собеседнику
Теперь нам нужно создать объект MediaStream и передать в него объекты AudioTrack и VideoTrack
Получить AudioTrack можно следующим образом
Получение VideoTrack происходит чуть сложнее. Сначала получаем список всех камер устройства:
Далее нужно создать объект CameraVideoCapturer, который и будет захватывать изображение
Теперь, после получения CameraVideoCapturer начинаем захватывать изображение и добавляем его в MediaStream
После создания MediaStream и добавления его в PeerConnection, библиотека формирует SDP-offer и происходит описанный выше обмен SDP-пакетами через сигнальный механизм. По завершению этого процесса собеседник начнет получать наш видео поток. C этого момента соединение установлено.
Комментарии