Что такое webrtc и для чего он нужен
WebRTC #1 — Знакомимся
Многие уже слышали о проекте WebRTC, некоторые даже используют его (или пытаются применять в существующих проектах), а кто-то злобно потирает руки, предвкушая постепенную расправу со Skype и Flash.
Погуглив в Хабре (хе-хе) я почему-то не нашел статей, которые углублялись в техническую сторону WebRTC, показывали бы примеры его использования.
Что же, я попытаюсь порадовать вас схемками, кодом. В общем, именно тем, что всем по вкусу. Так пройдем же под кат, мой любимый читатель.
Что это?
По сути, WebRTC являет собой:
1. Media Streams (getUserMedia).
2. Peer Connection.
Ниже я вкратце опишу эти элементы, но подробное описание я все же хочу оставить на две следующие части статьи.
Media Streams
Media Streams — API, позволяющий получить доступ к камере и микрофону через браузер без каких-либо плагинов и флеша.
Следуя WebRTC Public API, нам нужно использовать метод getUserMedia у глобального объекта navigator.
Передавать стоит три параметра:
— объект со списком того, что нам нужно (аудио/видео)
— success callback
— error callback
И пока что есть необходимость в костылях из-за наличия префиксов в различных браузерах:
Браузер мило попросит разрешения.
Ура! Мы получили Stream-объект с аудио и видео. И что же с ним делать?
Можем показать это дело юзеру используя html5 тег «video».
И немножко сахара. Теперь можно смело применять html5 фильтры (webkit) к видео элементу.
Клево, не правда ли?
Peer Connection
Peer Connection — это тот самый API, который позволяет установить Peer-to-Peer соединение между браузерами.
Ниже представлена упрощенная схема соединения между двумя клиентами.
— Первый клиент отправляет так называемый Offer второму клиенту через сервер (PeerConnection Observer).
— Второй клиент (Remote Peer) отправляет через сервер ответ первому клиенту.
— Устанавливается P2P соединение между клиентами.
Примечательно, что в дальнейшем для работы такого соединения сервер становится опциональным. Т.е. после его выключения данные все также будут передаваться. Дальнейшее участие PeerConnection Observer’а нужно для правильного закрытия соединения, добавления участников в поток и т.п.
В спецификации указан конструктор RTCPeerConnection, но пока что мы вынуждены использовать префиксы для различных браузеров:
Здесь пора бы уже и server side рассматривать, но хочется оставить первую статью более обзорной.
Недостатки
Продолжая «осмотр», нужно отметить темную сторону проекта:
1. API изменяется, т.к. проект находится на стадии активной разработки. Следовательно, иногда придется менять свой код.
2. До утверждения аудио и видео кодеков, возможны проблемы с кроссплатформенностью.
3. Кроссбраузерность. Имеем такую картину:
Chrome | Firefox | Opera | |
---|---|---|---|
getUserMedia | Stable (as of version 21) | 17 | 12 |
Peer Connection | Stable (as of version 23) | Nightly | — |
Зачем тогда это все?
Думаю, в недалеком будущем мы все же получим стабильный WebRTC API в современных браузерах. Это откроет невероятные возможности в веб разработке. Интересуясь этим проектом уже сейчас, можно будет намного быстрее вникнуть и начать использовать его потом.
И никто не отменял рассчитанные на определенный браузер (Chrome Stable, к примеру) проекты. Да и интересно же, правда?
Дальше — больше
Заканчивая первую часть цикла статей, хотелось бы составить примерный план:
1. WebRTC #1 — Знакомимся
2. WebRTC #2 — Media Streams
3. WebRTC #3 — Peer Connection: Server Side
4. WebRTC #4 — Peer Connection: Client Side
5.…
P.S. если ожидали больше материала, сильно не ругайтесь. Тема мне очень интересна, поэтому я очень заинтересован продолжить цикл, одновременно углубляясь в нее.
UPD: спасибо GeorP и egobrain за замечания.
WebRTC для любопытных (часть 1)
Книга довольно поверхностно объясняет как работает WebRTC «под капотом», для подробностей надо читать RFC. Ссылки на RFC различных используемых протоколов буду приводить. Стоит особо отметить главу «Отладка», где неплохо описываются идеи того, как отлаживать различные проблемы с сетью, задержками и прочим.
Что такое Webrtc?
Помимо JavaScript протокол WebRTC реализован также и на других языках програмирования. Можно найти множество реализаций серверов, библиотек, реализующих протокол, примером может стать реализация на go: github.com/pion/webrtc. Пишется реализация и на rust: https://github.com/webrtc-rs/webrtc (проект довольно интересный, потому что это переписываение pion/webrtc на rust).
Протокол WebRTC поддерживается в IETF в группе rtcweb. API WebRTC задокументировано в W3C как webrtc-pc.
Приемущества WebRTC
Далее приводится список того, что даст вам WebRTC. Список не полный, это просто примеры того, что заслуживает внимания. Не волнуйтесь, если какие-то слова вам не знакомы, в течение следующих частей разберем их подробнее.
Итак, приемущества WebRTC:
Множество различных реализаций
Можно работать прямо из браузера
Перепрофилированная существующая технология, то есть не изобретали колес, когда делали WebRTC
Контроль за перегруженностью
Задержка (latency, имеется в виду задержка аудио и/или видеопотока) в пределах 1 секунды
WebRTC это набор разных технологий
Это тема, для объяснения которой потребуется целая книга. Для начала разобъем ее на четыре части:
Эти четыре шага идут друг за другом, каждый предыдущий шаг должен успешно завершиться чтобы начался следующий.
Интересный факт в WebRTC это то, что каждый шаг использует множество других протоколов!
Каждому из этих шагов посвящена отдельная часть, но пока что будет полезным рассмотреть каждый шаг «с высоты птичьего полета».
Сигналинг или как агенты находят друг друга в сети
Когда запускается WebRTC-агент, он не знает с кем ему соединиться, и какого рода информацией он будет обмениваться. Сигналинг (Signaling) решает эту проблему! Сигналинг нужен для того, чтобы два агента могли найти и вызвать друг друга в сети перед тем, как начать обмен информацией.
Сигналинг использует существующий протокол SDP (Session Description Protocol). SDP это простой текстовый протокол. Каждое SDP-сообщение состоит из пар ключ-значение, расположенных в строгом порядке (rfc4566), которые в свою очередь составляют набор медиа-секций. SDP-сообщения, которыми обмениваются WebRTC-агенты содержит такую информацию как:
адреса IP и порты агентов, по которым можно соединиться с агентом (это т.н. ICE-кандидаты)
сколько аудио и видео треков агент желает отправить
какие аудио и видео кодеки поддерживает каждый из агентов
значения используемые во время соединения ( uFrag / uPwd ).
значения используемые для безопасности (отпечаток сертификата)
Отметим, что сигналинг обычно работает как бы в сторонке; то есть приложения не используют WebRTC для обмена SDP сообщениями. Тут подходит любой способ обмена этими сообщениями: REST, Websocket, да хоть письмом по почте можно отправить другому пиру SDP-сообщение, а тот в свою очередь отправит свое. В своем приложении для тестов я вообще использовал firebase для сигналинга.
Установка соединения и NAT Traversal с помощью STUN/TURN
Теперь у обоих сторон WebRTC агентов достаточно информации о том, чтобы соединиться друг с другом. Далее используется другая устоявшаяся технология под названием ICE.
Настоящая магия здесь это т.н. NAT Traversal и STUN/TURN сервера. Обе эти концепции необходимы для соединения с ICE агентом из другой сетки. Далее мы изучим этот вопрос глубже.
Как только связь между двумя агентами установлена, WebRTC переходит к установлениею шифрованного канала передачи. Далее этот канал будет использован для передачи аудио/видео и данных.
Шифрование передачи информации с помощью DTLS и SRTP
Для видео/аудио в WebRTC используется другой протокол: RTP. Для шифрования RTP-пакетов используется протокол SRTP. SRTP сессия инициализируется с помощью ключей шифрования полученных в ходе DTLS сессии (rfc5764). Далее мы обсудим, почему для медиа-данных используется свой собственный протокол.
Теперь все готово! У нас есть двунаправленный и безопасный канал. Если у вас стабильное соединение между вашими WebRTC-агентами, то вышеописанный комплекс процедур достаточен чтобы начать им (агентам) общаться. Однако в жизни все не так идеально, как кажется: мы постоянно будем сталкиваться с потерей пакетов в сети, ограниченной пропускной способностью сети. Дальше мы подумаем, как справляться со всеми этими проблемами.
Общение между пирами через RTP и SCTP
Сейчас мы имеем два WebRTC-агента с безопасным двунаправленным соединением. Давайте начнем взаимодействие! И снова мы используем уже существующие протоколы: RTP (Real-time Transport Protocol), и SCTP (Stream Control Transmission Protocol). Используйте RTP для обмена аудио/видео шифрованным по протоколу SRTP и SCTP для обмена DataChannel-сообщениями, шифрованными с помощью DTLS.
RTP сам по себе очень минимален, но предоставляет все необходимое для стриминга в реальном времени. Важно то, что RTP предоставляет разработчику гибкость в управлении потерями пакетов, задержками и перегрузками так, как он (разработчик) пожелает. Далее мы будем обсуждать по этой теме в части про медиа.
WebRTC это набор протоколов
Рис.1. WebRTC Agent Diagram
Кратко: как работает WebRTC (API)
В этой части показано как JavaScript API отображается на протокол. Это не демонстрация WebRTC API, а скорее некоторый набросок для создания у вас ментальной модели, как все работает вместе. Если вы не знакомы с каким-либо из пунктов, не переживайте, можете вернуться сюда когда узнаете больше!
Метод addTrack создает новый RTP-поток. Для потока генерируется случайный Synchronization Source (SSRC). Созданный RTP поток будет затем описан в Session Description-сообщении внутри медиа-секции после вызова createOffer метода. Каждый вызов addTrack создает новый SSRC и добавляет медиа-секцию в SDP-сообщение.
Сразу после того, как SRTP сессия установлена, зашифрованные медиа-пакеты начнут отправляеться через ICE.
createDataChannel создает новый SCTP-поток, если еще не был добавлен. По умолчанию SCTP выключен, но инициализируется как только одна из сторон потребует data channel.
Сразу после того, как DTLS сессия установлена, SCTP пакеты начнут отправляться через ICE.
createOffer генерирует Session Description для отправки удаленному пиру.
Вызов createOffer ничего не меняет на локальном пире.
После вызова setLocalDescription сгенерированное SDP-сообщение также отправляется на удаленный пир (выше обусждалось, что это можно делать любым способом), и далее на удаленном пире SDP-сообщение (offer) передается в метод setRemoteDescription. Удаленный пир в свою очередь отправляет свой локальный SDP в ответ (answer), который также нужно передать локально в setRemoteDescription.
addIceCandidate позволяет WebRTC-агенту добавить больше удаленных ICE-кандидатов.
В следующей части разберем Signaling и SDP.
Немного о WebRTC: что где использовать и случай из практики
WebRTC — это браузерная технология, предназначенная для передачи потоковых данных между браузерами или приложениями с использованием технологии двухточечной передачи (point-to-point transmission).
Эта технология хороша тем, что позволяет устанавливать связь между пользователями, используя только браузер. Для некоторых разработчиков, когда они узнают о WebRTC, это становится открытием: ведь можно создать видеочат без использования стороннего сервера — нужен только браузер.
WebRTC не требует установки дополнительных плагинов. Нужно просто написать код на HTML или JavaScript, и видеопотоки в браузере будут работать плавно.
WebRTC можно использовать не только для видеочатов: технология позволяет передавать файлы любого формата и текстовые сообщения.
API WebRTC
WebRTC имеет довольно большой набор функций и инструментов. В этой статье мы разберем три API.
1. getUserMedia
API позволяет управлять пользовательскими устройствами из браузера. Здесь можно выбрать:
Такие настройки помогают оптимизировать проект. Для того, чтобы все работало быстрее, качество можно уменьшить до 360 пикселей.
Алгоритм управления шумом тоже помогает: он эффективно устраняет шум и фоновые звуки из аудиопотока.
2. RTCPeerConnection
Этот API-интерфейс относится к технологии Peer-to-Peer, которая представляет собой прямую комбинацию двух браузеров, которые не используют сервер. Таким образом, происходит прямая передача видеопотоков с одного устройства на другое.
В RTCPeerConnection есть важная функция — встроенная поддержка серверов Stun/Turn, которые необходимы для обхода провайдера NAT, из-за которого видеопотоки могут не доходить до пользователей.
Разработчики могут получить доступ к серверам Stun/Turn от одного пользователя и получить чистый адрес для передачи видеопотока. Затем, можно подключиться к серверам Stun/Turn от другого пользователя и подключиться повторно. Таким образом, можно избежать сбоев и проблем с подключением пользователей из-за NAT.
3. RTCDataChannel
Используя RTCDataChannel, можно передавать текст и файлы различных форматов параллельно с видеопотоком.
Благодаря этому API вы можете разработать простой и быстрый чат для пользователей приложения. Он не требует установки на сервер, его можно переписать и передавать файлы любого формата размером до 4 ГБ (и более, если это позволяет браузер).
Миграция с Flash
Flash уже почти вышел из пользования. Поэтому важно мигрировать проекты (если по какой-то причине вы еще этого не сделали), разработанные с использованием Flash, на другие технологии, в частности на WebRTC.
Как уже упоминалось выше, WebRTC позволяет показывать видео с неудобных проигрывателей в форме видеофайлов или прямых трансляций, а также передавать файлы любого формата и текстовые сообщения. Кроме того, это относительно свежая оптимизированная технология, которая имеет множество внутренних настроек и не требует установки дополнительных серверов или плагинов.
Однако важно понимать, что WebRTC не является заменой Flash. Это инструмент, с помощью которого можно частично реализовать функциональность Flash.
Технические тонкости
У WebRTC есть свои тонкости — он использует два сетевых протокола — TCP и UDP.
Особенность протокола TCP в том, что он передает данные без потерь: пользователь получает стабильное изображение, видео передается без потерь и повреждений. Но этот протокол имеет ограничения по объему передачи данных. Например, нельзя передавать видео Full HD пяти людям одновременно.
Эта проблема решается с помощью протокола UDP: пользователи могут передавать высококачественные изображения и видео без ограничений. Но у него есть свой недостаток: он допускает потерю пакетов. Из-за этого изображение может дрожать и сильно терять в качестве.
Это можно исправить подключившись к сторонним серверам. Если на WebRTC разрабатывается крупный проект, в котором будет установлено соединение между сотнями пользователей, то вам все же придется использовать дополнительный сервер, чтобы уменьшить нагрузку на браузер.
Для каких проектов подходит WebRTC
Изначально, цель WebRTC — создание видеоконференций с использованием одноранговой технологии без использования какого-либо дополнительного сервера. Технология идеально подходит для разработки приложений для видеоконференций на основе браузера. Можно сказать, что это почти Skype внутри браузера.
Что по безопасности?
WebRTC не использует сторонние сервисы, где можно было бы реализовать защиту данных. Однако, технология работает через проверенные сетевые протоколы, которые обеспечивают безопасность передачи данных.
Аналитика для WebRTC
В браузере Google Chrome есть отдельная страница, где можно отслеживать передачу данных с помощью WebRTC. Там отображается вся статистика соединения: количество переданных пакетов, качество звука и видео, загрузка браузера, используемая сервером Stun/Turn.
Пример из практики: онлайн школа танцев
Пара слов о проекте, в котором мы использовали WebRTC. Нам пришел запрос на разработку приложения для онлайн школы танцев. Стандартная группа для каждого урока — 16 пользователей (один учитель и 15 учеников).
Одна из сложнейших задач проекта — добиться идеальной синхронизации 15 видеопотоков для студентов.
Проблема синхронизации возникала из-за того, что у каждого пользователя разная скорость соединения, местоположение и интернет-провайдер. Поэтому мы развернули медиа-сервер Wowza, который собрал все видеопотоки. Затем мы разместили медиа-сервер и веб-сайт приложения на Amazon, что снизило нагрузку на пользовательские устройства. Расчеты, обработка, синхронизация и мультиплексирование видеопотоков выполняются на сервере — учитель и ученики получают материалы, готовые к воспроизведению.
Синхронизация была достигнута с помощью FFmpeg — инструмента, который позволяет гибко и удобно управлять передачей аудио и видео потоков.
Нам нужно было найти решение проблемы отображения видеопотоков без использования сторонних систем. Мы решили использовать технологию WebRTC, и это оказалось идеальным решением для потоковой передачи видео через браузер.
Заключение
У нас еще не так много опыта в применении этой технологии, поэтому буду благодарен, если поделитесь своими случаями из практики и крутыми источниками для более углубленного изучения.
Опыт использования WebRTC. Лекция Яндекса
Что лучше использовать при разработке софта — нативные или веб-технологии? Холивар по этому поводу закончится ещё не скоро, но мало кто станет спорить, что нативные функции полезно продублировать для использования в браузерах или WebView. И если когда-то приложения для звонков существовали исключительно отдельно от браузера, то теперь их легко реализовать и в вебе. Разработчик Григорий Кузнецов объяснил, как пользоваться технологией WebRTC для P2P-соединений.
— Как вы все знаете, в последнее время появляется довольно много приложений, в основу которых заложен прямой обмен данными между двумя браузерами, то есть P2P. Это всевозможные мессенджеры, чаты, звонилки, видеоконференции. Также это могут быть приложения, которые производят какие-то распределенные вычисления. Пределы фантазии никак не ограничиваются.
Как же нам сделать подобную технологию? Представим, что мы хотим совершить звонок из одного браузера в другой. И пофантазируем, какие нам нужны шаги, чтобы этой цели достичь. В первую очередь кажется, что звонок — это наша картинка, наш голос, изображение, и нужно получить доступ к медиаустройствам, подключенным к компьютеру: к камере и к микрофону. После того, как вы получите доступ, вам необходимо, чтобы ваши два браузера, два клиента, друг друга нашли. Нужно помочь им как-то соединиться, достучаться, передать метаинформацию.
Когда вы достучитесь, необходимо начать передавать данные в режиме P2P, то есть обеспечить передачу медиапотоков. Все необходимые пункты у нас есть, мы готовы реализовать свой классный новый велосипед. Но это шутка, мы с вами инженеры и понимаем, что это дорого, неоправданно и рискованно. Поэтому как классические инженеры давайте сначала подумаем, какие решения уже существуют.
В первую очередь — старая умирающая технология Adobe Flash. Она действительно умирает, и компания Adobe прекратит ее поддержку уже в 2020 году. Технология действительно позволит вам получить доступ к вашим медиаустройствам, внутри нее вы сможете реализовать всю необходимую механику, чтобы помочь браузерам соединиться, чтобы они начали передавать информацию P2P, но вы опять изобретете свой велосипед, потому что нет единого стандарта, единого подхода к реализации данного способа передачи данных.
Вы можете написать для браузера плагин. Так работает Skype для тех браузеров, которые не поддерживают более современные технологии. Вам придется реализовывать свой велосипед, потому что нет единого стандарта, а еще это плохо для пользователей, так как пользователю придется себе в браузер инсталлировать какой-то плагин, совершать дополнительные действия. Пользователи этого не любят и не хотят делать.
И есть технология WebRTC — с помощью нее работают Google Hangouts, Facebook Messenger. Компания Voximplant использует ее, чтобы вы могли совершать свои звонки. Давайте на ней остановимся подробнее. Это новая развивающаяся технология, она появилась в 2011 году и продолжает развиваться. Что же она позволяет делать? Получить доступ к камере и микрофону. Установить P2P-соединение между двумя компьютерами, двумя браузерами. Естественно, она позволяет передавать медиапотоки в режиме реального времени. Кроме того, она позволяет передавать информацию, то есть любую бинарную дату вы тоже можете передавать P2P, можете сделать свою систему распределенных вычислений.
Важный момент: WebRTC не предоставляет браузерам способ найти друг друга. Мы можем сформировать всю необходимую метаинформацию о нас любимых, но как одному браузеру узнать о существовании другого? Как их соединить? Рассмотрим пример.
Есть два клиента. Первый клиент желает совершить звонок второму клиенту. WebRTC дает всю необходимую информацию, чтобы себя обозначить. Но остается открытым вопрос, как одному браузеру найти другой, как эту метаинформацию переслать, как проинициализировать вызов. Это дается на откуп разработчикам, мы можем использовать абсолютно любой способ, взять эту метаинформацию, распечатать на бумажке, отправить курьером, другой ее будет использовать, и все будет работать.
А можем придумать некоторый сигнальный механизм. В данном случае это сторонний механизм, который позволит нам, если мы знаем о наших клиентах, обеспечить передачу между ними некоторой информации, которая необходима для установки соединения.
Рассмотрим пример с использованием сигнального сервера. Есть сигнальный сервер, который держит постоянное соединение с нашими клиентами, например, по веб-сокетам или с помощью HTTP. Первый клиент формирует метаинформацию, и с помощью веб-сокетов или HTTP пересылает ее на сигнальный сервер. Пересылает также какую-то часть информации, с кем именно он хочет соединиться, например, никнейм или еще какую-то информацию.
Сигнальный сервер по этому идентификатору устанавливает, какому именно клиенту нужно переадресовать нашу метаинформацию, и пересылает ее. Второй клиент берет ее, использует, устанавливает себе, формирует ответ, и с помощью сигнального механизма пересылает ее на сигнальный сервер, тот в свою очередь ретранслирует ее первому клиенту. Таким образом оба клиента в данный момент обладают всей необходимой датой и метаинформацией, чтобы установить P2P-соединение. Готово.
Давайте чуть подробнее рассмотрим, чем же именно обмениваются клиенты, они обмениваются SDP-датаграммой, Session Description Protocol.
Это, по сути, текстовый файл, который содержит всю необходимую информацию, чтобы установить соединение. Там есть информация об IP-адресе, о портах, которые используются, о том, какая именно информация гоняется между клиентами, что это такое — аудио, видео, какие кодеки используются. Все, что нам необходимо, там есть.
Обратите внимание на вторую строчку. Там указан IP-адрес клиента, 192.168.0.15. Очевидно, это IP-адрес компьютера, который находится в какой-то локальной сети. Если у нас два компьютера, каждый из которых находится в локальной сети, каждый из которых знает свой IP-адрес в рамках этой сети, хотят созвониться. Получится ли у них сделать это с такой датаграммой? Очевидно, нет, они же не знают внешних IP-адресов. Как быть?
Отойдем в сторону и посмотрим, как работает NAT. В интернете многие компьютеры скрыты за роутерами. Есть локальные сети, внутри которых компьютеры знают свои адреса, есть роутер, который обладает внешним IP-адресом, и наружу все эти компьютеры торчат с IP-адресом этого роутера. Когда пакет от компьютера в локальной сети идет на роутер, роутер смотрит, куда его нужно переадресовать. Если на другой этой локальной сети, то он просто его ретранслирует, а если нужно его отправить вовне, в интернет, то составляется таблица маршрутизации.
Мы заполняем внутренний IP-адрес компьютера, который желает переслать пакет, его порт, ставим внешний IP-адрес, IP-адрес роутера, и делаем также подмену порта. Для чего она нужна? Представим, что два компьютера обращаются к одному и тому же ресурсу, и нам нужно правильно смаршрутизировать ответные пакеты. Мы их будем идентифицировать по порту, порт будет по каждому из компьютеров уникальным, в то время как внешний IP-адрес будет совпадать.
Как жить, если есть NAT, если компьютеры торчат наружу под одним IP-адресом, а внутри знают о друг друге по другим?
На помощь приходит фреймфорк ICE — Internet Connectivity Establishment. Он описывает способы обхода NAT, способы установки соединения, если у нас есть NAT.
Этот фреймворк использует приписывание так называемого STUN-сервера.
Это такой специальный сервер, обращаясь к которому, вы можете узнать свой внешний IP-адрес. Таким образом, в процессе установки P2P соединения, каждый из клиентов должен сделать по запросу к этому STUN-серверу, чтобы узнать свой IP-адрес, и сформировать дополнительную информацию, IceCandidate, и с помощью сигнального механизма также этим IceCandidate обменяться. Тогда клиенты будут знать друг о друге с правильными IP-адресами, и смогут установить P2P соединение.
Однако бывают более сложные случаи. Например, когда компьютер скрыт за двойным NAT. В этом случае фреймворк ICE предписывает использование TURN-сервера.
Это такой специальный сервер, который превращает соединение клиент-клиент, P2P, в соединение клиент-сервер-клиент, то есть выступает в роли ретранслятора. Хорошая новость для разработчиков в том, что независимо от того, по какому из трех сценариев пошла установка соединения, находимся ли мы в локальной сети, нужно ли обратиться к STUN- или TURN-серверу, АPI-технология для нас будет идентичной. Мы просто в начале указываем конфигурацию ICE- и TURN-серверов, указываем, как к ним обратиться, и после этого технология делает для нас все под капотом.
Небольшое резюме. Чтобы установить соединение, нужно выбрать и реализовать некий механизм сигнализации, некого посредника, который будет помогать нам пересылать метаинформацию. WebRTC даст нам всю необходимую мету для этого.
Нам предстоит побороться с NAT, это наш главный враг на этом этапе. Но чтобы его обойти, используем STUN-сервер, чтобы узнать свой внешний IP-адрес, и TURN-сервер используем в качестве ретранслятора.
Что же именно мы передаем? Про медиа-потоки.
Медиапотоки — это такие каналы, которые внутри себя содержат треки. Треки внутри медиа-потока синхронизированы. Аудио и видео не будет расходиться, они будут идти с единым таймингом. Вы можете внутри медиапотока сделать любое количество треков, треками можно управлять по отдельности, например, вы можете приглушить аудио, оставив только картинку. Также вы можете передавать любое количество медиа-потоков, что позволяет вам, например, реализовать конференцию.
Как же получить доступ к медиа из браузера? Поговорим про API.
Есть метод getUserMedia, который принимает на вход набор констрейнтов. Это специальный объект, где вы указываете, к каким именно устройствам вы хотите получить доступ, к какой именно камере, к какому микрофону. Указываете характеристики, которые хотите иметь, какое именно разрешение, и есть также два аргумента — successCallback и errorCallback, который вызывается в случае успеха или неудачи. В более современных реализациях технологии используются промисы.
Есть также удобный метод enumerateDevices, который возвращает список всех подключенных к вашему компьютеру медиа-устройств, что дает вам возможность показать их пользователю, нарисовать какой-то селектор, чтобы пользователь выбрал, какую конкретно камеру он хочет использовать.
Центральным объектом в API служит RTCPeerConnection. Когда мы выполняем соединение, то берем класс RTCPeerConnection, который возвращает объект peerConnection. В качестве конфигурации мы указываем набор ICE-серверов, то есть STUN- и TURN-серверов, к которым мы будем обращаться в процессе установки. И есть важный ивент onicecandidate, который триггерится каждый раз, когда нам нужна помощь нашего сигнального механизма. То есть технология WebRTC сделала запрос, например, к STUN-серверу, мы узнали свой внешний IP-адрес, появился новый сформированный ICECandidate, и нам нужно переслать его с помощью стороннего механизма, ивент стриггерился.
Когда мы устанавливаем соединение и хотим проинициализировать вызов, мы используем метод createOffer(), чтобы сформировать начальную SDP, offer SDP, ту самую мета-информацию, которую нужно переслать партнеру.
Чтобы установить ее в PeerConnection, мы используем метод setLocalDescription(). Собеседник получает эту информацию по сигнальному механизму, устанавливает ее себе с помощью метода setRemoteDescription() и формирует ответ с помощью метода createAnswer(), который также с помощью сигнального механизма пересылается первому клиенту.
Когда мы получили доступ к медиа, получили медиапоток, мы его передаем в наше P2P-соединение с помощью метода addStream, а наш собеседник узнает об этом, у него стриггерится ивент onaddstream. Он получит наш поток и сможет его отобразить.
Также вы можете работать с дата-потоками. Очень похоже на формирование обычного peerConnection, просто указываете RtpDataChannels: true и вызываете метод createDataChannel(). Подробно на этом останавливаться не буду, потому что такая работа очень похожа на работу с веб-сокетами.
Пару слов о безопасности. WebRTC работает только по HTTPS, ваш сайт должен быть подписан сертификатом. Медиапотоки тоже шифруются, используется DTLS. Технология не требует установки ничего дополнительного, никаких плагинов, и это хорошо. И не получится сделать шпионское приложение, сайт не будет подслушивать или подсматривать за пользователем, он покажет пользователю специальный промт, запросит у него доступ и получит его, только если пользователь разрешит доступ к аудио- и медиаустройствам.
Что касается поддержки браузеров — IE остается и останется красным. В конце прошлого года добавилась поддержка Safari, то есть уже все современные браузеры умеют работать с этой технологией и мы можем смело ее использовать.
Хочу поделиться набором всяких полезностей, которые помогут вам, если вы желаете работать с WebRTC. В первую очередь это adapter. Технологии все время развиваются, и есть разница в браузерных API. Библиотека adapter нивелирует эту разницу и облегчает работу. Удобная библиотека для работы с дата-потоками — Peerjs. Также можете посмотреть на открытые реализации STUN- и TURN-сервера. Большой набор туториалов, примеров, статей находится на страничке awesome-webrtc, очень рекомендую.