WebRTC (англ. Real-time communications — коммуникации в реальном времени) — проект с открытым исходным кодом, предназначенный для организации передачи потоковых данных между браузерами или другими поддерживающими его приложениями по технологии точка-точка.

Для полного понимания статьи рекомендую ознакомиться с основными принципами работы технологии тут.

image

Как я пришел к необходимости использования WebRTC


Задача проекта:

Представим, что нам требуется соединить двух случайных пользователей между собой для передачи real-time потокового видео друг другу.
Какие есть варианты решения проблемы?

Вариант 1:

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

Минусы:

  • Дорогостоящее оборудование сервера
  • Малая расширяемость из-за ограниченности ресурсов сервера
  • Время задержки видео увеличено из-за посредника

Плюсы:

  • Нет проблем с выбором пользователя и подключением к нему — это за нас делает сервер

Вариант 2:

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

Минусы:

  • Длительная операция подключения двух пользователей
  • Сложность создания peer-to-peer подключения
  • Сложности с протоколом NAT для передачи данных напрямую
  • Требуется несколько серверов для создания подключения

Плюсы:

  • Разгрузка серверов
  • Сервер может перестать работать, но видео не прервется
  • Качество изображения напрямую зависит от качества канала передачи данных у пользователей
  • Возможность использования end-to-end шифрования
  • Управление подключением лежит в руках пользователей

Также задача состояла в том, чтобы сделать это максимально бюджетно, без серьезных нагрузок на сервер.
Было принято решение использовать вариант под номером 2.

После усердных поисков по интернету и over9000 уйму потраченного времени я наткнулся на технологию WebRTC, которая предлагала решить минусы, которые я выявил в процессе анализа подходов к решению проблемы.

Реализация


Начался второй этап поиска. На нем я наткнулся на много различных платных библиотек, которые предлагали мне решить мою проблему, нашел очень много материалов о WebRTC, но реализации для iOS найти мне не удавалось.

Затем случайно я зашел на git ядра для браузера от Google и заметил там папку под названием “WebRTC”, в которой было несколько файлов и две папки: “Android” и “iOS”. Зайдя в папку, которая мне была симпатична более другой, я обнаружил массу исходных файлов библиотеки и папку “Example”, в которой находился проект под названием “AppRTC”.

image

Я немедленно запустил этот проект у себя на устройстве и на втором iOS девайсе, который был под рукой, и мне удалось соединить их и пообщаться с самим собой на двух телефонах.

Самым быстрым способом интегрирования видео-чата в мое приложение, которое уже имело некоторые функции (регистрация, авторизация), я видел наложением “AppRTC” примера на свое приложение, чем я и принялся заниматься.

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

В конечном итоге все в “сервисе” было разделено на две части:

  • Авторизация, регистрация, фильтр поиска собеседников, настройки, покупки и так далее;
  • Видео-чат.

Разработка шла, но после того, как началась отладка я столкнулся с тем, что библиотека абсолютно нестабильна, происходят постоянные разрывы соединения, плохое качество видео, использование процессора устройства на 120%, низкая частота обновления кадров и многое другое. Было потрачено много времени на оптимизацию, но к реальному результату это не привело: были незначительные изменения в скорости работы, но все равно не торт. Также очень много ресурсов требовал кодек VP8, а поддержки других на тот момент у сервиса не было.

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

Решением оказалось не использовать свой сервер для WebRTC. То есть сервер самого приложения только лишь анализировал подключенных к нему пользователей и предлагал им соединиться, после этого приложения начинали работать с сервером самого “AppRTC” и все взаимодействия с передачей пакетов, STUN и TURN серверами проходило там. Так же пришлось все переписывать до актуальной версии в приложении своими силами. Во время этого я заметил, что было добавлено шифрование данных, которые передавались между пользователями, и интегрирован кодек H264, который значительно снизил нагрузку на устройство и дал прирост в количестве кадров в секунду.

Был проведен полный рефакторинг кода видео-чата и приложение заработало еще быстрее и стало юзабельнее. В результате оптимизации кода, библиотека была вынесена в отдельный “Pod” сюда.

Заключение


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

Было разработано и представлено несколько решений по оптимизации работы самой библиотеки “AppRTC” и они были отправлены разработчикам.
Поделиться с друзьями
-->

Комментарии (11)


  1. IlyaGulya
    21.06.2016 11:51
    +1

    Не совсем понял, что именно вы сделали. В вашем репозитории лежат всего лишь скрипты для сборки приложения, точная копия оригинального репозитория компании Pristine (https://github.com/pristineio/webrtc-build-scripts) причём не самой последней версии, ибо у вас в зависимостях на платформе OS X ещё присутствует QTKit, который был удалён в марте.
    Можно ссылку на ваши пулл-реквесты в репозиторий webrtc? Интересно было бы посмотреть, вдруг ваши предложения ещё и на Android улучшат ситуацию, у нас тоже не всё гладко.


    1. f0r3s1
      21.06.2016 12:54

      Из скриптов сборки приложения, если бы Вы их изучили, Вы бы увидели, что сама библиотека так же подтягивается из моего репозитория. В скором времени эта библиотека, которая подтягивается, будет автоматически обновляться из git'а разработки WebRTC. Это было сделано для того, чтобы не скачивать постоянно новую версию WebRTC и не компилировать её снова, а это отнимает около 12 часов (с моим интернетом). Это было основной целью вынесения библиотеки в отдельный репо.


      1. Anakros
        21.06.2016 15:03

        Там гит вообще-то, много выкачивать нужно только один раз.


      1. IlyaGulya
        23.06.2016 13:40

        Я вкурсе как работают эти скрипты, использую их давно, спасибо. Чтобы найти различия между оригинальными и вашими я сделал следующее:
        1. Слил репозиторий https://github.com/pristineio/webrtc-build-scripts
        2. Слил ваш репозиторий
        3. Скопировал все файлы из вашего репозитория в оригинальный.
        4. Сделал git diff.
        5. Увидел всего два изменения — QTKit и добавленный файл .podspec, который, как я подозреваю, никакого отношения к сборке не имеет.
        В связи с этим вопрос — о каком вашем репозитории вы толкуете?


  1. Dimd13
    21.06.2016 13:52
    +1

    Ссылки на репы, где что нашли можно написать


    1. f0r3s1
      21.06.2016 15:42

      Библиотека тут.


  1. Anakros
    21.06.2016 14:53

    Решением оказалось не использовать свой сервер для WebRTC. То есть сервер самого приложения только лишь анализировал подключенных к нему пользователей и предлагал им соединиться, после этого приложения начинали работать с сервером самого “AppRTC” и все взаимодействия с передачей пакетов, STUN и TURN серверами проходило там.


    Что это должно значить? Вы вместо своего stun/turn-сервера чужой стали использовать и это всё решение?

    Был проведен полный рефакторинг кода видео-чата и приложение заработало еще быстрее и стало юзабельнее. В результате оптимизации кода, библиотека была вынесена в отдельный “Pod” сюда.

    Ссылочку плз на изменения по сравнению с оригинальной версией.

    Было разработано и представлено несколько решений по оптимизации работы самой библиотеки “AppRTC” и они были отправлены разработчикам.

    Ссылку можно на отправленные решения?

    К слову, у меня так и не получилось использовать h264 для гуглового WebRTC в iOS, ибо всё время приходит RTCI420Frame с NULL вместо данных в переменных yPlane, uPlane и vPlane на принимающей стороне. Как ни странно, VP8 работает. У кого-то такое было?


    1. f0r3s1
      21.06.2016 16:01
      -1

      Что это должно значить? Вы вместо своего stun/turn-сервера чужой стали использовать и это всё решение?


      Это значит то, что наш сервер указывал что нужно соединить вот этих двух ребят, затем они сами подключались к Signaling и stun/turn серверам «AppRTC» и взаимодействовали внутри серверов «AppRTC» (appr.tc).

      Ссылочку плз на изменения по сравнению с оригинальной версией.


      Имелся ввиду рефакторинг кода видео-чата внутри приложения, а не библиотеки, то есть то, как приложение взаимодействовало с библиотекой, а это уже является собственностью заказчика, и я не в праве это разглашать.

      Ссылку можно на отправленные решения?


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

      У кого-то такое было?


      У нас такое было до обновления библиотеки до актуальной версии. Сейчас, если я не ошибаюсь, поддержка VP8 медленно вырезается из библиотеки за ненадобностью.
      Так же вы могли упустить важную часть после создания session description (peerConnection:didCreateSessionDescription:error:):
      // Prefer H264 if available.
      RTCSessionDescription *sdpPreferringH264 = sip;
      sdpPreferringH264 = [ARDSDPUtils descriptionForDescription:sdpPreferringH264 preferredVideoCodec:@"H264"];        sdpPreferringH264 = [ARDSDPUtils descriptionForDescription:sdpPreferringH264 preferredAudioCodec:@"ILBC"];        [_peerConnection setLocalDescriptionWithDelegate:self sessionDescription:sdpPreferringH264];
      ARDSessionDescriptionMessage *message = [[ARDSessionDescriptionMessage alloc] initWithDescription:sdpPreferringH264];
      


      1. Anakros
        21.06.2016 16:14
        +1

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

        Какая разница? Думаю, не только мне интересно было бы взглянуть на то, что вы улучшили. Тем более, после написания статьи, но без подробностей толком.

        У нас такое было до обновления библиотеки до актуальной версии. Сейчас, если я не ошибаюсь, поддержка VP8 медленно вырезается из библиотеки за ненадобностью.
        Так же вы могли упустить важную часть после создания session description (peerConnection:didCreateSessionDescription:error:):

        Библиотека была собрана последняя из мастера пару дней назад (так же пробовал ревизию из ветки 52-го релиза хромиума), кодек конечно же приоритетный в SDP, но кадры без этих данных приходят в любом случае. Локально, однако, всё с ними окей. Такое только со стримом видео, который приходит по сети.


  1. f0r3s1
    21.06.2016 18:08
    -1

    Какая разница? Думаю, не только мне интересно было бы взглянуть на то, что вы улучшили. Тем более, после написания статьи, но без подробностей толком.


    Учту в следующий раз.


  1. Makaveli
    22.06.2016 12:07

    Зайдя в папку, которая мне была симпатична более другой, я обнаружил массу исходных файлов библиотеки и папку “Example”, в которой находился проект под названием “AppRTC”.

    Пришла мысль обновить библиотеку полностью. После переделки 80% написанного до обновления кода он все еще не работал, а пример не был обновлен до актуальной версии.

    Было разработано и представлено несколько решений по оптимизации работы самой библиотеки “AppRTC” и они были отправлены разработчикам.


    Я так и не понял, какую библиотеку вы нашли и что вы переписали? Какая-то лапша без конкретики. AppRTC у вас то пример, то библиотека, ещё 80% какого-то кода вы переписали, но какой, сказать не можете? Какие вы улучшения предложили и куда?