Хабрахабр

Видеозвонки, WebRTC и браузер: как это работает и как согреть «замерзающую» трансляцию

Для большинства из нас видеосвязь в браузере — нечто вроде черного ящика. Есть изображение собеседника на экране, звук, возможность общения. Но что происходит там, внутри? Об этом сегодня и поговорим.

Он занимается настройкой видеосвязи в Skyeng и стремится сделать видеосвязь не просто хорошей, а очень хорошей. Статья сделана на основе доклада нашего сотрудника, Кирилла Рогового. В ней разбираются не только принципы работы технологии, но и важные моменты процесса улучшения качества видеосвязи. Он поделился своим опытом, наработками и наблюдениями по WebRTC (Web Real Time Communications), что было оформлено в виде статьи. Все это и немного больше — под катом.

WebRTC — что это и зачем мне это знать?

Главная особенность WebRTC в том, что у разработчика не так много вариантов взаимодействия с технологией, по большей части все работает в автоматическом режиме.

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

В подавляющем большинстве случаев разработчики используют готовые компоненты — клиентские библиотеки и серверы. Для лучшего понимания можно привести аналогию с HTTP. Вероятно, лишь малая толика читателей этой статьи писала собственные HTTP-сервера, которые парсят сырые запросы по TCP, составляют ответ, делают что-то еще. Это может быть Fetch API, Node, Nginx и т.п. Но если разработчик знает, как все это функционирует, у него появляется больше возможностей в отладке кода, поиске проблем и способах улучшения производительности своих приложений и сервисов.

В первую очередь, способ отправлять и принимать UDP-пакеты в RTP — протоколе верхнего уровня внутри браузеров. Что лежит в основе WebRTC? WebRTC универсальная технология, которая неплохо справляется с передачей медиа при условии использования аудио- и видеокодеков.

Сначала открывается UDP-порт на ПК (конечно, нужно знать IP-порт собеседника), и начинается обмен UDP-пакетами, которые заворачиваются в определенный протокол верхнего уровня, который называется RTP (Real-time Protocol). Процесс установки связи происходит следующим образом. Большая часть этого процесса происходит «под капотом», разработчик же лишь заполняет некоторые пробелы.

Как работает WebRTC?

Все начинается с захвата камеры. Итак, есть API браузера, который дает возможность просить у пользователя доступ к камере и микрофону. После одобрения запроса формируется медиастрим. Передавать поток собеседнику напрямую не выйдет, поскольку объем передаваемых несжатых данных довольно велик. В обычной ситуации поток видео — это тридцать картинок в секунду, с информацией о каждом пикселе в каждой картинке — фрейме. Это BMP в мире видео. Соответственно, видео длиной в 1 секунду составляет около 36 МБ, т.е. битрейт в этом случае составляет 288 Мбит/с. А вот ширина большинства каналов — всего 100 Мбит/с. Поэтому приходится задумываться о сжатии, кодировании исходного видео.

С этим справляется, например, кодек VP9, который разработан для кодирования видео в реальном времени. Кодирование. На этом этапе очень важно сжимать видео, не теряя качества. Как это реализовано? Он позволяет передавать видео с качеством 720p и fps 30 c битрейтом 1,5 Мбит/с. Здесь стоит помнить о двух объектах. Все просто: сравниваются соседние кадры с выделением diff (информация об отличиях двух соседних кадров). Первый — keyframe — полная информация о картинке, второй — interframe — информация о разнице между соседними картинками, кадрами.

NB! Разные браузеры могут поддерживать разные кодеки, VP9 приведен лишь в качестве примера.

Нужно решить несколько проблем, без чего передача данных невозможна: Запаковка информации в RTP-протокол. Сразу после кодирования потока отправить его клиенту, например, по UDP, нельзя.

  • Хранение информации о порядке следования пакетов данных.
  • Хранение информации о тайминге, что необходимо для синхронизации видео и аудио.
  • Хранение информации о треках, что дает клиенту возможность отличать разные дорожки, выделять произвольные данные.

Вся эта информация добавляется к передаваемым данным, но оверхед небольшой — его объем в среднем составляет 5% от исходного объема данных. Кроме того, RTCP (RTP Control Protocol) дает возможность обмениваться информацией о потерянных пакетах и статистике их получения в неидеальных сетях.


Твой пакет был очень вкусным, %username% // Credit

Собственно, это код на «си» в браузере Firefox или Chrome. RTCP — это спецификация протокола в рамках RTP и библиотека для «си» от Google (lib WEBRTCP или lib GEGL).

UDP а не TCP используется потому, что у UDP минимальный интервал между пакетами. Отправка данных. По сети данные уходят в виде UDP-пакетов. Но в нашем случае минимальный интервал и скорость передачи — это преимущество. К слову, DDoS осуществляется обычно по UDP. Недостаток — нет гарантий, что отправленный пакет дойдет до адресата.

Распаковка. Полученные пакеты нужно расставить в правильном порядке и передать в декодер, на выходе которого — чистый видеопоток.

Если данные передаются без проблем — видео транслируется. Подключение к элементу видео. Последний этап — получение изображения собеседника. Если передача прекращается, мы видим последний из переданных кадров.

Если разработчик не добавил собственный сертификат, то будет использован стандартный сертификат браузера. NB! Видеопоток шифруется сертификатом браузера. Поэтому следует учитывать, что если сертификат предоставлен с доступом к приватному ключу (что практикуется в Казахстане, например), то оператор сертификата сможет подключиться к передаваемому видео и аудиопотоку.

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

Потери пакетов, фриз и вот это все

К сожалению, при передаче данных далеко не все пакеты доходят до получателя. Иногда они теряются. Почему? Есть три основных категории причин:

  • Они никуда не уходят. Это явление называется Random loss или Lossy network. Пример — когда пользователь и роутер находятся в одном помещении, но между ними стена. В итоге теряются рандомные пакеты. Еще можно включить микроволновку, и потери будут еще более масштабными. Hint — если у вас назначено важное собеседование во видеосвязи, не стоит в это же время рядом разогревать супчик.
  • Пакеты дропаются по ошибке. Они могут задерживаться и не приходить вовремя по самым разным причинам — программным и аппаратным. Перегрелось оборудование, заглючил софт — что угодно, и пакеты теряются.
  • Network congestion или перегрузка сети. Между отправителем и получателем находится много разных сетевых узлов, которые принимают и отправляют трафик. В основном, это задача маршрутизаторов. Но эти устройства рассчитаны на определенный объем принимаемых данных. Если узел получает больше трафика, чем он в состоянии обработать, то в лучшем случае формируется буфер, который дает возможность справиться с перегрузкой, что приводит к задержке в передаче пакетов, но передача все же идет. В худшем — пакеты перестают отправляться вообще.


Твой пакет не пройдет! // Credit

RTCP повторно запрашивает пакеты, на что нужно время. Что происходит с WebRTC трансляцией, если теряется относительно небольшая часть пакетов? Видео фризится, приостанавливается, пользователь начинает немного нервничать. Так, если задержка в обычной ситуации составляет 30 мс, то при повторном запрашивании пакета уйдет уже 60 мс.

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

От разработчика в такой ситуации ничего не зависит, все это — «под капотом» технологии WebRTC.

Можно ли что-то сделать?

Решение есть всегда, а в случае WebRTC их сразу четыре. Да, конечно.

Jitter buffer или интерполяция №1.

Так, если задержка в сети — 30 мс, изображение будет показываться с задержкой в 90 мс. Демонстрация картинки пользователю с небольшой задержкой. В некоторых сетевых играх вроде CS и Dota используется тот же принцип. До определенного момента никто ничего не будет замечать, общение будет комфортным.

Если объем потерянных пакетов небольшой, пользователь ничего не заметит. Предварительная задержка дает дополнительное время (те самые 60 мс из нашего примера) на решение проблем с потерей пакетов. В сложных ситуациях фриз все равно возникнет, но будет относительно коротким.

Это решение уже встроено в технологию WebRTC.

Уменьшение битрейта №2.

Битрейт = количество кадров в секунду * на качество * разрешение. Для иллюстрации решения возьмем простую модель. В сложных ситуациях достаточно понизить битрейт, и связь будет оставаться на приемлемом уровне. При изменении параметров битрейт будет либо расти, либо падать. Объяснение простое — чем ниже битрейт, тем выше вероятность, что пакеты не попадут в буфер маршрутизатора, который находится под большой нагрузкой. Качество картинки снизится, но общаться можно без проблем.

Так, при установке сессии можно установить лимит, за который WebRTC не сможет выйти. Несмотря на то, что это тоже встроенное в WebRTC решение, разработчики уже могут на что-то влиять. Этот метод в большинстве случаев помогает избежать Network congestion. В Skyeng установлено 256 кб/с при максимальном разрешении 640х480, чего хватает для того, чтобы передавать картинку относительного качества при низкой загрузке на канал.

Forward error correction №3.

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

Forward error correction работает в автоматическом режиме, но разработчик может эту опцию отключать, если твердо уверен, что она не нужна.

Сетевой тюнинг №4.

Например, можно выбирать лучший сетевой маршрут. А вот здесь разработчик может развернуться — все зависит только от него. В Skyeng маршрут выбирается по принципу «минимальная сумма пингов» при прокладывании канала «ученик-учитель». Если компания купила серверы в разных регионах, например, Москве, США, Европе, то можно задавать наиболее удобный путь, по которому данные будут передаваться. Если бы маршрут прокладывался в автоматическом режиме, качество видео страдало бы.

И чем больше разработчик знает о процессах, происходящих «под капотом», тем больше у него возможностей влиять на процесс передачи данных на «последней миле». Кроме сетевых маршрутов настраивать можно сервера и маршрутизаторы. После того, как мы настроили буферы, качество связи существенно улучшилось. Так, мы недавно обнаружили, что пакеты теряются на наших серверах, поскольку буферы слишком маленькие и ОС дропает все пакеты выше лимита.

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

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

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть