Как устроена видеосвязь на уроках в Skyeng

По материалам доклада Кирилла Рогового на FrontendConf 2019

Как устроена видеосвязь на уроках в Skyeng

Учить английский в Skyeng можно где и когда угодно — нужны только интернет и видеосвязь. Чтобы и ученикам, и учителям было удобно заниматься, она должна быть быстрой даже в 3G-сетях, надежной при нестабильном соединении, доступной из браузера.

Для этого два года назад Skyeng отказался от внешнего сервиса видеосвязи в пользу интеграции WebRTC + Janus в собственную платформу Vimbox — и рассказал об этом в блоге на «Хабре». Сегодня мы расскажем, как мы снижаем потери данных при видеосвязи, чтобы во время занятия видео или звук как можно реже прерывались или зависали.

Британский акцент с доставкой по оптоволокну

Все начинается с того, что через API браузера мы запрашиваем у ученика или учителя доступ к камере и микрофону: если вы когда-нибудь были хотя бы на первом уроке, методист показывал вам, как это сделать.

Слайд из презентации Кирилла Рогового <a href="https://api.vc.ru/v2.8/redirect?to=https%3A%2F%2Ffrontendconf.ru%2Fmoscow%2F2019%2Fabstracts%2F5527&postId=134506" rel="nofollow noreferrer noopener" target="_blank">WebRTC под капотом</a>
Слайд из презентации Кирилла Рогового WebRTC под капотом

Затем мы захватываем два медиапотока — аудио и видео — и кодируем их, чтобы сделать файлы легче. Одна секунда ролика формата 640х480 — это 30 полноцветных картинок: вместе они весят 288 Мбит/с, а пропускная способность большинства домашних сетей — 100 Мбит/с. Мы используем кодек, который выделяет из этих 30 картинок только ключевые кадры, где картинка резко меняется. А для остальных картинок запоминает и передает разницу между ними.

Закодированные медиапотоки делятся на пакеты данных и «упаковываются» в протокол верхнего уровня RTP (Real-time Protocol): он запоминает порядковые номера пакетов данных, хранит данные о тайминге, которые нужны для синхронизации картинки и звука.

Слайд из презентации Кирилла Рогового <a href="https://api.vc.ru/v2.8/redirect?to=https%3A%2F%2Ffrontendconf.ru%2Fmoscow%2F2019%2Fabstracts%2F5527&postId=134506" rel="nofollow noreferrer noopener" target="_blank">WebRTC под капотом</a>
Слайд из презентации Кирилла Рогового WebRTC под капотом

В нашем WebRTC подключено расширение RTCP (RTP Control Protocol). Оно помогает обмениваться информацией о статистике потерь и получения пакетов данных.

Теперь самое интересное: мы должны передать пакеты данных от одного компьютера (точнее, его IP-адреса) к другому по UDP-протоколу. Это протокол, который в отличие от TCP, не гарантирует доставку пакетов. Если сравнить протоколы TCP и UDP с обычными курьерами, первый позвонит в дверь, попросит предъявить паспорт, заполнить бланк получения и расписаться, а второй просто поставит пакеты у двери и уйдет. Заберете ли вы пакеты, похитят ли их соседи — уже не его забота. Второй курьер не ждет, пока получатель откроет дверь и распишется в бланке, поэтому работает значительно быстрее.

Вернемся к UDP-протоколу. Данные по нему передаются быстро: это очень важно, когда преподаватель из Кардиффа тренирует британский акцент с учеником из Нижнего Новгорода, чтобы ни звук, ни видео не зависали. Незначительные потери в данных не страшны: скажем, если ученик не получит 10 из 1800 картинок за минуту видео, то скорее всего, даже не заметит этого. Наша главная задача — избежать крупных потерь пакетов при такой доставке.

Когда пакеты получены, происходит все то же самое, но в обратном порядке — протокол RTCP проверяет, все ли пакеты в наличии, медиапотоки извлекаются из RTP, декодируются и подаются на платформу. Весь обмен данными происходит за считанные доли секунд, пока преподаватель поправляет произношение артикля the.

Так бы все работало в идеальном мире. А как получается в реальности?

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


Четыре решения одной проблемы

Как сделать так, чтобы секунды и минуты видео не терялись передаче данных по UDP? Самое популярное решение — джиттер буфер (jitter buffer), трансляция видео с почти незаметной задержкой. К примеру, прямой путь между IP-адресами ученика и учителя занимает 30 мс (миллисекунд).

Добавим к этому времени еще 60 мс: за это время мы проверим, все ли пакеты получены, а если нет, то повторно запросим их. А пока отрисуем кадр с теми пакетами данных, которые у нас есть. Пользователь увидит картинку через 90 мс: это комфортный уровень задержки, который мы даже не замечаем.

Еще один способ снизить потери — временно снизить качество изображения, уменьшить битрейт. Такой способ применяется, когда сеть перегружена: чтобы отправлять пакеты поменьше, используют более сильное сжатие изображения через кодеки. Вероятно, вы сталкивались с тем, что когда скорость вашего домашнего интернета снижается, то ролики на YouTube воспроизводятся не в HD-качестве, а в 240p или 360p.

В Skyeng мы поставили лимит на видеотрафик в 286 кб/с при максимальном разрешении 640х480. Этого вполне хватает, чтобы передавать картинку в высоком качестве, но при этом мы не даем WebRTC произвольно перегружать сети и снижать битрейт, чтобы пользователи не сталкивались с внезапным ухудшением качества видео.

Третий способ — дублировать часть данных при отправке, чтобы в случае потери данных восстановить их. Эта технология называется Forward error correction.

Четвертый способ — гибко настроить собственные сети, чтобы выстраивать каналы между учителями и учениками по принципу наименьшего числа переключений от сети к сети.

Во-первых, мы заворачиваем весь видеотрафик через собственные сервера в Москве и Санкт-Петербурге.

Во-вторых, внимательно настраиваем сервера и маршрутизаторы. К примеру, в Linux для UDP-пакетов есть свои буферы, и эти буферы по настроены на пропускную способность 100 mbps. Если сервер начнет пропускать сквозь себя 200, 300, 400 mbps, пакеты начнут теряться прямо на сервере из-за того, что буфер слишком быстро заполняется.

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

1717
реклама
разместить
11 комментариев

Спасибо за статью. Было интересно почитать.

1

а у вас точка-точка всё? На сервере не пишете? 

Дмитрий, у нас свои сервера в разных дата-центрах. Так мы можем выбрать лучшие сетевые маршруты: для всех пользователей Skyeng собираем пинги до всех видеосерверов, и когда приходит время для занятия определенной пары ученик-учитель, мы можем выбрать оптимальный сервер по принципу “где самая меньшая сумма пингов”. 

Подкинулся на рекламу Skyeng бесплатное занятие и записался... но возникли проблемы... так и не смог первый урок провести). Хотя рекомендации по изучению англ.яз приходят исправно.

Извините, вам, кажется, стабильно не везет в этом месяце - это про историю с доменом) Надеемся, там все разрулится, конечно.  

Если серьезно, закинем ребятам, которые занимаются отловом проблем на пути пользователя. Не против, если они вам напишут?

отслеживаете ли Вы видео и аудио качество пройденных уроков? и если да, то каким способом?

Роман, да, т.к. видео на нашей стороне, нам за него отвечать) Одна из первых метрик, которую стали отслеживать - это разница между плановой и реальной нагрузкой: по расписанию мы понимаем, сколько уроков проходит в какой час, и какой трафик должен проходить через нас - если меньше (а так бывало), то где-то что-то не так. Постепенно обвешиваем новыми метриками: следим, чтобы частота кадров в секунду не опускалась ниже определенного уровня, рассинхрон видео и аудио, если случается, не выходил за комфортный для восприятия порог, и тд.

Кстати, продакт, а в прошлом один из разработчиков команды видео будет 23 мая выступать на митапе https://intercomconf.com/online/ - там же будут другие хорошие ребята с экспертизой, мб вам будет интересно пообщаться.