Синхронизация событий в видеотрансляциях
Важным аспектом интерактивных видеотрансляций является синхронность всех происходящих событий. Как рассинхронизация аудио- и видеодорожек, так и несвоевременное отображение событий в интерфейсе могут привести к неудобствам и негативному пользовательскому опыту.
Для наглядности представим трансляцию турнира по боулингу, в которой есть элемент интерфейса, отображающий текущий счёт.
Игрок только собирается бросить шар, но счёт в интерфейсе уже обновился. Это происходит из-за того, что на транскодирование и доставку видео требуется больше времени, чем на передачу информации о счёте.
Доставка видео и событий до клиента
Давайте рассмотрим типичную схему работы стримингового сервиса.
Как мы видим, события и видеопоток распространяются по разным каналам. События передаются зрителям через обычный сервер бизнес-логики, тогда как для видео требуются транскодирование и сеть серверов кэширования. Это означает, что на обработку и доставку видео требуется больше времени.
Проблема произвольной задержки
ажется очевидным отсрочить выполнение событий на время задержки видео, однако «из коробки» у нас нет информации о том, какая задержка у воспроизводимого видео на клиенте. Измерить её эмпирическим путём также не удастся, так как у каждого клиента она может быть разной.
Размер задержки может зависеть от множества факторов: производительности клиентского устройства, качества сети, равномерности подачи контента, а также протокола, используемого для доставки и воспроизведения видео (WebRTC, DASH, HLS и т.д.).
Варианты решения
Давайте рассмотрим некоторые варианты решения задачи сопоставления событий с видео.
Сопоставление с текущим временем проигрывания видео
Зная время начала трансляции и текущее время воспроизведения видео, несложно рассчитать задержку, сопоставив эти данные с временем на устройстве клиента. Однако этот метод применим только для зрителей, которые начали смотреть трансляцию с самого начала. Зрители, подключившиеся в процессе трансляции, имеют информацию только о времени воспроизведения с момента своего подключения.
Передача событий через дорожку субтитров
Иногда для решения этой проблемы события передают через отдельную дорожку субтитров, тем самым чётко соотнося воспроизводимые кадры с соответствующими событиями.
Однако у этого способа есть ряд недостатков.
Во-первых, данную дорожку придется отфильтровывать, чтобы зрители не могли выбрать её для просмотра как обычные субтитры.
Во-вторых, необходимо организовать дополнительный канал подачи этих данных в транскодер для упаковки в виде субтитров, что зачастую является нетривиальной задачей, так как транскодер часто запускается с заранее подготовленными параметрами.
Эти данные не несут полезной нагрузки для самого видео, усложняют его использование в сторонних сервисах, задействуют механизмы не по назначению и фактически являются мусорными в отрыве от пользовательского интерфейса.
Кроме того, в некоторых случаях, данных о событии может быть достаточно много, что не слишком подходит для формата субтитров. Поэтому, чаще всего, все сводятся к прожиганию в субтитрах только меток времени. Этого достаточно для расчета задержки и сопоставления событий с видео.
Однако, если нам нужны только метки времени на видео, возможно, существуют более естественные способы их получить, не прибегая к использованию субтитров.
Использование графических меток
Для передачи временных меток в видео можно воспользоваться опытом кино и тв продакшена и встраивать их непосредственно в изображение.
SMPTE Timecode
Не все знают, что знаменитая «хлопушка», которую мы видим в начале дублей на съемках, представляет собой не что иное, как графическую метку, используемую для синхронизации событий видеопроизводства, таких как свет, звук и механические изменения сцены.
Для менее заметной передачи временных меток в видео используются протоколы LTC (Linear Timecode) и VITC (Vertical Interval Timecode).
Пример зари цифрового ТВ
Стеганография
Для ещё менее заметной для зрителя передачи меток можно применить методы стеганографии — способы передачи или хранения информации, которые скрывают сам факт передачи.
Однако все подобные методы накладывают значительные расходы на внедрение и извлечение меток. Необходим более простой и экономичный способ.
PRFT метки времени
При использовании формата MPEG-DASH наши видеоданные заворачиваются в медиаконтейнер, например, MPEG-4, который содержит метаданные, определенные стандартом, такие как: время создания файла, продолжительность, языковой код потока, название альбома, правовой статус произведения и т. п.
Это то, что нам нужно. Поскольку данные содержатся в бинарном виде, нам нужно обратиться к стандарту ISO/IEC 14496–12 для их извлечения. Не буду вдаваться в подробности конвертации бинарного кода в movie box-ы, остановлюсь только на том как высчитать из имеющихся боксов нужную нам информацию.
Нам понадобится prft-бокс (ISO/IEC 14496–12:2012 — 8.16.5 Producer Reference Time), представляющий собой ntp-метку в самих чанках видео.
Поскольку в основе расчета временных меток внутри контейнера используется эпоха 1 января 1900 года в качестве начала отсчета, эта дата берется как отправная точка (start).
Соответственно, код для получения серверного времени генерации чанка (wallClockTime) можно получить примерно следующим образом:
const start = new Date(Date.UTC(1900, 0, 1, 0, 0, 0));
const ntpTime = prft.ntpTimestampSec * 1000 + (prft.ntpTimestampFrac / 2 ** 32) * 1000;
const wallClockTime = new Date(start.getTime() + ntpTime).getTime();
Для получения времени чанка в рамках таймлайна самой трансляции (сколько времени прошло от начала стрима) нам понадобится бокс mdhd (ISO/IEC 14496–12:2012 — 8.4.2 Media Header Box), находящийся в структуре по пути moov > trak > mdia > mdhd в init-файлах.
const mediaTimeInSec = (prft.mediaTime / mdhd.timescale) * 1000;
Таким образом, мы получили размер текущей задержки и можем применять события, опираясь на эти данные.
Стоит обратить внимание, что нам не нужно рассчитывать время каждого чанка; достаточно первого полученного, а дальше нужно делать поправку на currentTime видеоэлемента.
Проблема синхронизации нескольких стримов
Теперь рассмотрим более сложную ситуацию, когда у нас одновременно идет больше одного стрима.
Вернемся, для примера, к нашей трансляции игры в боулинг. Представьте, что у нас два видеопотока с трансляцией игрока с разных ракурсов.
Поскольку задержка у разных стримов различна, мы видим, что с одного ракурса игрок только готовится метнуть шар, а с другого он уже выбил страйк. Кроме того, возникает вопрос, с каким из потоков нужно синхронизировать переключение счета.
Более типичными примерами могут быть одновременные трансляции двух и более спикеров или дополнительный стрим демонстрации экрана.
Варианты решения
MCU
Одним из вариантов решения может быть использование подхода MCU (Multipoint Control Unit), заключающегося в объединении всех видеопотоков в один общий.
Здесь я хочу ограничиться лишь упоминанием данного подхода, так как тема требует отдельного разговора.
Управление задержкой
Другим вариантом является приведение стримов к целевой задержке. Установить задержку можно с помощью перемотки, но это может привести к дезориентации: зритель может потерять часть полезной информации. Лучшим способом будет управление скоростью воспроизведения — замедление и ускорение стримов, чтобы добиться целевой задержки.
Стоит обратить внимание, что оптимальное отклонение от естественной скорости не должно превышать 10%, так как большее отклонение будет заметно зрителю.
Проблемы стабильной подачи данных
Нужно учесть, что выдерживать целевую задержку получится только если контент для плеера будет поступать непрерывно и равномерно, что позволит постоянно иметь данные в буфере для отображения.
Давайте рассмотрим некоторые проблемы, препятствующие равномерности подачи данных.
Равномерное поступление чанков
Важным маркером является равномерное поступление чанков на ориджин сервер с транскодера. Если чанки на ориджин приходят неравномерно, в первую очередь необходимо обратить внимание на отсутствие проблем со стороны ведущего.
Проблемы на ведущем
К проблемам со стороны ведущего можно отнести проблемы с оборудованием. Помимо откровенно сбоящих камер нередко происходит долгий захват стримов с камеры и микрофона. В таких случаях на время отсутствия основного стрима помогает использовать фейковый стрим — заглушку.
Компьютеру ведущего может не хватать производительности, и он не будет справляться с кодированием видео в реальном времени. В этом случае на помощь приходят алгоритмы ABR, и качество исходящего видео снижается.
Частой причиной проблем являются сетевые сбои. В случае низкой пропускной способности канала на помощь снова приходят алгоритмы ABR. Но, к сожалению, это не единственная проблема, которая часто встречается в сети. Часто наблюдаются значительные потери пакетов, и приходится применять ретрансмиты, запрашивая потерянные пакеты повторно. Нередки и ситуации, когда пакеты приходят не по порядку. Для исправления этой ситуации приходится использовать Jitter-очередь, дожидаться прихода всех пакетов и потом выстраивать их в правильном порядке.
Для нивелирования некоторых проблем на ведущем можно сделать запасной источник — заглушку на транскодере. В этом случае у зрителей не будет разрывов в получении трансляции.
Проблемы на транскодере
Если проблем на ведущем не наблюдается, но чанки все равно приходят с пропусками или неравномерно, например, некоторое время не приходит ни одного чанка, а затем, как бы нагоняя, приходит сразу пачка чанков одновременно, это может говорить о том, что транскодер не справляется.
Проблемы с доставкой чанков зрителю
Если вы проводите достаточно массовые трансляции и у вас широкая география зрителей, одних ориджин-серверов вам будет недостаточно. Вам понадобится распределенный CDN, который снимет значительную часть нагрузки и поможет решить множество сетевых проблем между ориджин-сервером и зрителем.
Однако, к сожалению, CDN не способны решить проблемы «последней мили». Представим ситуацию, когда несколько пользователей из одной локальной сети смотрят трансляцию. Каждый из них обращается к EDGE-серверу, создавая нагрузку на пропускную способность сети. При достаточном количестве таких зрителей они могут перегрузить канал, и никто больше не сможет просматривать контент. Обратите внимание, что при этом каждый из них получает один и тот же контент, но для каждого отдельно.
Для решения таких проблем в ключевых локальных сетях устанавливают кэш-серверы или используют подход eCDN. Об этом подробнее я писал в статье «Трансляция видео посредством P2P-сетей».
Проблемы на зрителе
Проблемы со стороны зрителя я подробно разбирал в статье «ABR для живых трансляций». Поэтому не буду здесь останавливаться на них подробно, отмечу только, что для зрителя необходимо стремиться к балансу между следующими факторами: скоростью старта воспроизведения, отсутствием фризов, качеством изображения и наименьшей возможной задержкой.
Заключение
Корректное отображение событий в интерфейсе является критически важным для обеспечения положительного пользовательского опыта в интерактивных видеотрансляциях.
Мы рассмотрели основные проблемы, связанные с задержками при передаче данных, и некоторые решения, такие как использование меток времени в формате MPEG-DASH и управление задержкой стримов. Важно учитывать не только технические аспекты передачи контента, но и влияние факторов, таких как производительность клиентского устройства и качество сети, на конечный результат. Для успешного решения этих задач необходим комплексный подход, который включает в себя как оптимизацию работы на стороне ведущего и транскодера, так и создание эффективной инфраструктуры доставки контента для зрителе.