ABR для живых трансляций
Все мы смотрим видеоролики в интернете, и каждому наверняка приходилось сталкиваться с проблемами во время просмотра. Как разработчик сервиса вебинаров, попробую разобрать эту проблематику и рассмотреть возможные решения.
Давайте представим себе ситуацию, в которой у нас есть человек, желающий посмотреть видео через интернет, и мы, как разработчики, стремимся предоставить ему эту возможность.
Предположим, речь идет о фильме. В таком случае, берем веб-сервер и размещаем на нем файл с соответствующим фильмом.
Первая проблема — быстрый старт
Пользователь заходит на страницу с плеером и нажимает кнопку «play», после чего ожидает полной загрузки файла с фильмом передвоспроизведением. Однако, это определенно нельзя назвать комфортным просмотром, поскольку ожидается, что воспроизведение начнется немедленно.
Таким образом, первый критерий качества при просмотре видео через интернет — это время, проходящее между началом запроса на воспроизведение и началом просмотра.
Следует отметить, что чем длиннее видео, тем больше времени потребуется на его загрузку.
Логичным решением этой проблемы является разделение фильма на множество небольших отрезков, которые передаются поочередно. Такие небольшие фрагменты видео называются чанками.
Вторая проблема — фризы
Теперь, когда зритель нажал на кнопку «play», видео начало воспроизводиться (что замечательно). Возникает следующая проблема: после завершения проигрывания первого чанка начинается загрузка второго. Во время этой загрузки воспроизведение приостанавливается, и пользователь сталкивается с ожиданием, видя загрузочный индикатор вместо видео. Такое происходит на каждом переходе между чанками.
Вот и вторая проблема — когда плееру нечего показывать пользователь получает фриз.
Значит нужно не дожидаясь окончания проигрывания текущего чанка скачать следующий. И лучше не один, а несколько, про запас, ведь сеть иногда проседает и некоторые чанки будут грузится дольше других. Это называется — буферизация видео.
Ну вот, другое дело — пользователь посмотрел всё видео без проблем и остался доволен.
Тем не менее, стоит учесть, что другие пользователи могут столкнуться с медленным интернетом, из-за чего чанки будут загружаться дольше, чем воспроизводиться, вновь вызывая «фризы».
Простейшим способом решения данной проблемы является уменьшение размера каждого чанка и общего размера всего видео.
Сделать это мы можем за счет трех вещей:
Максимально пережать кодеком, но тогда мы получим размытие, потерю цветов, артефакты
Уменьшить разрешение, например до 360p
Уменьшить FPS (частоту кадров в секунду)
Третья проблема — качество
Теперь наш зритель с плохим интернетом доволен (нет), ведь он смог посмотреть фильм, хоть и в плохом качестве, но это лучше, чем ничего и во многих случаях этого вполне достаточно.
Однако, все остальные пользователи, даже те, у кого хороший интернет, вынуждены смотреть видео в низком качестве.
Таким образом, возникает третья проблема — низкое качество видео.
Давайте же сделаем несколько версий для каждого чанка с разным качеством и дадим пользователям самим выбрать какое смотреть. Такой подход называется ABR (Adaptive bitrate streaming).
Выбор качества
Ну вот — замечательно, теперь пользователи смотрят видео, выбирая качество в зависимости от своих потребностей и возможностей.
Но оказывается многие просто не понимают, что от них требуется. Они запускают видео в высоком качестве, при плохом интернет-канале, и, столкнувшись с проблемами, часто просто уходят.
А те, кто понимает, вынуждены прикладывать немало усилий для подбора максимального работающего качества.
Значит, нужно автоматически подобрать оптимальное качество на основе условий у пользователя.
Условия на устройстве
Устройство пользователя также может оказывать значительное влияние на просмотр. Факторы, такие как разрешение экрана, процессор, доступная память и мощность графического ускорителя, могут ограничивать возможность плавного воспроизведения видео высокого разрешения.
Размер экрана
Нет смысла показывать качество с разрешением выше чем разрешение экрана, незачем показывать 1080p на экране 800×600. Это же относится и к размеру блока в котором находится видео-элемент.
Производительность
Помимо прочего, устройство, с которого зритель просматривает видео, может не справиться с декодированием. В таком случае плеер отбрасывает кадры, которые не успел обработать. Мы можем рассчитать соотношение отброшенных кадров к скачанным и, если это количество превышает 25%, понизить качество.
Условия сети
Опора на пропускную способность
С сетевой обстановкой все не так очевидно. У нас нет простого инструментария для получения данных о сети. Вернее он есть, это — navigator.connection, но у него слабая поддержка и ненадежные данные.
Лучший способ заранее понять какая скорость скачивания нашего видео с нашего сервера — это скачать чанк до начала просмотра и соотнести его размер со временем скачивания.
Теперь пользователи освобождены от необходимости самостоятельно выбирать оптимальное качество перед просмотром: мы заранее знаем скорость соединения и, основываясь на полученных данных, можем выбрать подходящее качество.
Однако и этого недостаточно. К сожалению, существует проблема изменения скорости соединения в процессе просмотра. В самый захватывающий момент, когда зрителю сейчас раскроется тайна одинаковых родинок на главных героях, видео начинает «фризить».
Следовательно, необходимо иметь информацию о состоянии сети в процессе просмотра и динамически адаптировать качество видео.
Наиболее очевидным подходом представляется измерение скорости при загрузке каждого фрагмента. И уже в зависимости от этой скорости при необходимости понижать или повышать качество.
В реальных же условиях сетевое соединение подвержено значительным колебаниям, и такие измерения на графике скорее всего будут больше напоминать пилообразную волну, чем стабильный показатель скорости.
В результате, зритель сталкивается с бесконечными переключениями качества изображения. Картинка буквально разваливается, чтобы затем вновь собраться, вызывая при этом приступы тошноты и даже эпилептические реакции.
Для достижения более усредненного показателя на основе статистики, полученной из большего числа предыдущих скачанных фрагментов, используется скользящая средняя — EWMA (Exponentially Weighted Moving Average).
Этот усредненный показатель будем считать доступной пропускной способностью.
Теперь можно исключить все варианты, размер которых превышает пропускную способность.
Хотя мы сглаживаем данные о сети, периодические колебания и даже резкие падения не исчезли. Это означает, что периодические скачки качества также остались, хоть и в меньшем объеме.
Нам нужно выбрать такое качество при котором риск переключения при колебании сети будет наименьшим. Нужно обозначить зону риска, варианты качества, попадающие в нее будут считаться рискованными и не подходящими для выбора. Обычно это все варианты качества, размеры которых превышают 90–98% пропускной способности.
Соответственно, если текущее качество попадает в зону риска мы должны понизить до безопасного.
Теперь нам необходимо отказаться от вариантов слишком низкого качества по отношению к доступному каналу — назовем это некачественной зоной. В эту зону обычно относят все варианты, размеры которых составляют менее 70–85% от пропускной способности.
В итоге у нас остается небольшая зона посередине, назовем ее, условно, зона стабильности. В ней и находится наше целевое качество.
Это консервативная стратегия ABR, она реализована во всех современных плеерах и для многих считается достаточной. Она проста и быстро реагирует на изменения сети.
Тем не менее, она несовершенна, так как опирается на весьма приблизительную оценку пропускной способности и не учитывает других факторов, такие как буфер. Из-за этого мы не можем окончательно избавиться от ложных колебаний между вариантами качества, иногда игнорируем лучший вариант качества, когда канал для него достаточен, но он попадает в зону риска.
Итак, большинство зрителей довольны, но не все. Некоторые всё равно оказываются в калейдоскопе переключения качества, а другие жалуются на плохую картинку при хорошей сети.
Опора на буфер
Возможно, опираться на приблизительные расчеты сетевых условий — не единственный вариант. Необходимо найти более точный и контролируемый способ, от которого мы можем оттолкнуться.
На самом деле, нам даже не требуется рассчитывать скорость. Важно лишь, чтобы всегда было, что показывать, и, чтобы мы не попадали в состояние «фриза», то есть чтобы буфер был заполнен.
Для начала необходимо определить размер буфера — это длина видео в секундах, готового к проигрыванию. Если буфер полон, мы находимся в безопасности и можем улучшать качество. Если он пустеет, необходимо понижать качество.
Так же, как и в случае с опорой на сеть, для начала нужно определить зону риска. Если буфер почти пуст, немедленно переключаемся на наименьшее доступное качество. Это может быть процент от целевой длины буфера или время в секундах, например, длина одного чанка.
Согласно тому же принципу, определим безопасную зону, в пределах которой всегда будет отображаться наилучшее качество.
В середине у нас сформировалась зона, характеризующаяся набором качеств, между которыми происходит переключение по мере наполнения или осушения буфера.
Мы реализовали базовую схему алгоритмов BBA(Buffer-Based Approach). В результате мы избавились от ненадежных расчетов и прогнозирования сети, а также устранили ложные колебания между вариантами качества.
Но есть одна существенная проблема, из-за заданных заранее зон с фиксированным качеством очень часто это качество низкое.
Что, если не закреплять эти зоны жестко, а автоматически соотносить уровень заполненности буфера с вариантами качества с учетом их веса?
Так работает алгоритм BOLA (Buffer Occupancy based Lyapunov Algorithm) являющимся логическим продолжением BBA.
Выглядит хорошо, отсутствуют необоснованные скачки качества, а само качество максимально высокое в соответствии с условиями зрителя.
Однако, существует определенный недостаток: при начале просмотра или перемотке буфер остается пустым, что приводит к тому, что зритель вынужден смотреть видео в наихудшем качестве до момента заполнения буфера.
Эту проблему можно решить путем применения консервативной стратегии, основанной на пропускной способности, пока буфер не будет достаточно заполнен. Такой подход обычно называется гибридным или динамическим.
Особенности живых трансляций
В начале мы обсуждали критерии качества просмотра видео в интернете:
В живых трансляциях у нас есть еще один критерий — задержка. Классическим примером является ситуация, когда зритель смотрит трансляцию спортивного матча и из-за большой задержки слышит крик «ГООООЛ!» за стеной, хотя у него еще ничего не произошло.
Более повседневным же для нашей практики являются проблемы с живым общением ведущего и аудитории, ведущий задает вопрос и видит ответы в чате, если задержка составляет десятки секунд это может вызывать значительный дискомфорт.
Особенностью нашего сервиса является использование нескольких видеотрансляций одновременно. Например, каждый выступающий отображается в отдельном видео, что требует фиксированной целевой задержки для синхронизации стримов.
Все это означает, что мы не можем использовать большой буфер, и описанные выше подходы не работают в полной мере.
Фактически наш буфер не может быть больше текущей задержки. При этом поскольку задержка может меняться, то и размер возможного буфера меняется вместе с ней.
Очевидно, что буфера в 1–1,5 чанка недостаточно для использования описанных выше стратегий, основанных на буфере.
Что же мы можем использовать из классических подходов?
Стратегию, основанную на пропускной способности, мы можем полностью взять на вооружение, но нужно использовать имеющиеся данные о буфере для решения ее недостатков.
Для решения проблемы наиболее подходящего качества в зоне риска, мы можем скорректировать рассчитанную пропускную способность в зависимости от уровня заполненности буфера. Когда буфер заполняется, оценка сети завышается, а при его опустошении — занижается.
Но этого недостаточно, нужно еще решить проблему колебания показателей сети. Кроме того оценки сети часто снижаются из-за близости к живому краю трансляции. Время висящих запросов, ожидающих поступления чанков, также учитывается и искажает статистику.
Давайте возьмем идею разделения буфера на зоны, как это делается в BBA. Попадая в опасную зону буфера, чтобы избежать постоянного перехода в плохое качество, мы должны при низкой оценке сети понизить качество на одну позицию, вместо ориентирования на пропускную способность. Соответственно, при попадании в безопасную зону при низкой оценке сети, мы должны на одну позицию повысить качество.
Оценка эффективности ABR алгоритма
Теперь необходимо понять, действительно ли этот подход оправдан и действует более эффективно. Но как оценить эффективность алгоритма ABR? Только сравнив его с другим алгоритмом ABR.
Критериями качества при этом должны служить четыре фактора:
Сетевые режимы, которые мы используем для тестирования:
Сценарии для тестирования:
Постепенное ограничение скорости
Резкое ограничение скорости
Старт с ограничением скорости
Восстановление после просадки сети
Восстановление после длительной просадки сети
Работа с ультранизкой задержкой
Сравнительный анализ и подтверждение на практике позволили убедиться в обоснованности использования данного подхода.
Данный алгоритм показал себя не хуже чем классические в 100% тестов.
В 65% тестов показал себя лучше.
В 87% тестов показал себя хорошо.
Оставшиеся 13% — тесты с экстремальными условиями (экстремально низкие скорости и т.д.).
Теперь вы знаете чуть больше о мире видео. Надеюсь было полезно.
.