В наше время онлайн‑встречи стали привычной практикой. Появилась возможность общаться по видеосвязи из разных концов мира, что значительно упростило коммуникацию. Но иногда эта связь может подвести. К примеру, падает качество изображения: возникают артефакты, нечёткость картинки.
Меня зовут Алексей Шпагин. Я руководитель разработки бэкенда единой видеоплатформы. В нашем сервисе видеоконференций можно проводить групповые звонки без ограничений по времени и количеству участников, совместно просматривать видео, а также демонстрировать экран в формате 4К. В этой статье расскажу, почему может снижаться качество транслируемого изображения, как эту проблему решить и какими инструментами оценивать результаты. Чтобы подкрепить рассуждения, в качестве примеров я буду использовать кейсы VK Звонков.
В 2022 году я рассказывал про оценку качества звука на конференции HighLoad++. Статья об этом уже есть на Хабре. В этом материале я буду делать отсылки к ней, так как есть сходство между тем, как передаются видео и звук через интернет.
Из чего складывается качество видео в звонке
Первое и самое очевидное — это разрешение картинки: чем оно выше, тем качественнее изображение.
К примеру, картинка слева (720р) большая со множеством деталей. Справа — её уменьшенная копия, на которой чётко видны очертания человека и даже просматривается рисунок фона.
При низком исходном разрешении картинки всё иначе: если маленькое изображение растянуть, оно размывается и появляются артефакты.
Второе — это степень сжатия или битрейт.
Слева качественная картинка, 2 мегабита в секунду — это относительно много. Справа картинка сильно пережата (62 килобита в секунду), что негативно отразилось на изображении.
На практике порой бывает ещё хуже. Поток видео сжимается до 16 килобит в секунду, разрешение картинки падает до 168р — уже мало что можно увидеть:
Важно соблюдать баланс между объёмом видео и степенью сжатия, чтобы пользователи получали качественную картинку, а сеть не перегружалась.
Третий параметр — количество кадров в секунду.
Чем больше кадров в секунду, тем картинка приятнее для восприятия. Конкретные примеры:
2 FPS — ощущается как технические проблемы, что‑то не загружается, наблюдаются проблемы со связью;
8 FPS — присутствуют рывки в видео;
15 FPS — неплохо для видеозвонков с веб‑камеры;
30 FPS — отличное качество видео.
Чем больше количество кадров в секунду, тем выше качество транслируемой картинки. Но вместе с этим увеличивается и объём видео.
Изображение большого разрешения с низким FPS не будет качественным, как и картинка с высоким FPS и маленьким разрешением. Чтобы пользователю было комфортно общаться в видеоконференции, важно учитывать каждый параметр и находить баланс.
Почему снижается качество видео
Мы не отправляем через сеть RAW‑видео, а прибегаем к помощи видеокодеков: H.264, VP8, VP9. Они сжимают видео с потерей качества, но можно настраивать степень сжатия и таким образом влиять на итоговое качество картинки. При этом нужно учитывать, что, как бы мы ни старались, оно всё равно будет ниже исходного RAW‑видео, но по качеству — приемлемым. Пользователи не будут чувствовать дискомфорт во время видеоконференции.
В процессе кодирования выделяются ключевые кадры (I‑frame) и дельта‑кадры (P‑frame). Вторые кодируют только изменения между ключевым кадром и текущим.
Далее идёт пакетизация кадров. Ключевые занимают больше всего сетевого трафика, потому что содержат кодирование целой картинки.
Маленькие синие квадраты под кадрами на иллюстрации выше — это пакеты. Можно заметить, что ключевые кадры занимают больше пакетов, чем дельта‑кадры. В реальности случаются потери пакетов, их перестановки, джиттер, задержки. На картинке ниже, например, пакет I3 пропал, из‑за чего мы не можем восстановить наш ключевой кадр. За этим следует появление артефакта, который снижает качество транслируемого изображения.
Более подробно про сетевые проблемы я рассказывал в статье про звук. Описанные там аспекты распространяются и на трансляцию видео.
Примеры артефактов при передаче видео по сети
Посмотрим что происходит, если пакеты пропадают.
Пример 1.
Слева — качественная картинка, справа — с артефактами, но детали просматриваются. Однако если плохие сетевые условия сохранятся, то изображение продолжит ухудшаться.
Пример 2.
На скриншоте с демонстрации экрана видно, что изображение уже совсем испорченное.
Как можно сохранить качество видео
Первый способ — Jitter Buffer. Это базовый механизм. Для звука и видео важно аккумулировать данные и ожидать пакеты, которые доходят. Однако это следует делать в разумных пределах, так как размер Jitter Buffer влияет на увеличение latency. В докладе про звук раскрыто более подробно.
Второй способ — NACK (Negative Acknowledgment). Очень простая и понятная технология. Если мы видим, что пакет пропал, то можем его перезапросить:
Третий способ — FIR (Full Intra Request), запрос на повторную отправку ключевого кадра. Если мы потеряли пакеты, не можем их восстановить и декодировать ключевой кадр, тогда нужно запросить его заново через FIR. В этом случае все промежуточные фреймы обнуляются, а дельта‑фреймы сбрасываются. Мы начинаем с чистого листа, кодируя с ключевого кадра.
Четвёртый способ — FEC (Forward Error Correction). При кодировании мы добавляем новую информацию к основным данным. Тогда в случае потери некоторых пакетов часть можно будет восстановить при декодировании. Например, в i‑пакете содержатся дополнительные данные, которые помогают при потере i + 1-го пакета в сети. Технология работает в ограниченных пределах, потому что добавляет избыточность в поток, повышая тем самым битрейт. Если он увеличится слишком сильно, трафик будет идеальным, но мы не сможем доставить его до конечного пользователя.
Пятый способ — Temporal Scalability. В одном видеопотоке одновременно кодируются два или более подстрима с различным FPS. Их количество и параметры можно настроить: обычный стрим и прореженный стрим с меньшим FPS. При потерях в сети пакеты могут пропадать в одном слое. Даже если пакеты из слоя с высоким FPS потеряны, мы можем «спасти» поток, снизив FPS и декодируя кадры из потока с низким FPS. Пользователь может заметить уменьшение количества кадров в секунду, но это лучше, чем чёрный экран или полное прерывание потока.
Шестой способ — это Transport‑CC. Его главная функция — определить пропускную способность между сервером и пользователем и подстроить качество видео под эту полосу. Напомню, качество зависит от разрешения, степени сжатия и FPS. Эти параметры можно настраивать: например, уменьшить размер изображения, что снижает битрейт и поможет видео справиться с плохой сетью. Можно также снизить FPS, но в разумных пределах, чтобы просмотр не доставлял пользователю дискомфорта.
Как измерять качество видео в звонке
Сразу отмечу, что для измерений мы используем метрики на базе референса (безреференсными метриками не пользуемся).
Вот так упрощённо выглядит стенд для оценки качества видео:
Принцип работы стенда:
Мы подаём референс в звонок.
Из звонка получаем видео с искажением.
Далее подаём в алгоритм оценки референсное и искажённое видео.
Алгоритм выдаёт оценку.
Как референс подаётся в звонок
При подаче референса используются следующие подходы.
-
Встроенные средства приложения. Например, Google Chrome в тестовых целях позволяет прочитать видео из файла и использовать его в качестве источника видео. Собственное нативное приложение можно модифицировать, но со сторонними это невозможно.
Плюсы: легко подавать входные данные, ресурсы ПК не тратятся.
Минусы: сложно работать со сторонними приложениями.
Веб‑камера. Можно использовать несколько вариантов:
Виртуальная камера на основе софта (OBS или самостоятельно написанного).
-
Физическое устройство, например Raspberry Pi. Мы подключали его к компьютеру и симулировали камеру. Такой подход технологичный и правильный, но сложный из‑за необходимости разрабатывать и поддерживать Raspberry. Кроме того, решение тяжело автоматизировать.
Плюсы: работает со всеми приложениями и сервисами.
Минусы: необходимость разработки, сложность поддержки и управления.
Как захватить видео на приёмной стороне
Можно использовать два подхода:
Встроенные средства. В таком случае необходим доступ к коду. Если это наше приложение, мы можем сделать запись в файл, на стороннем — нет.
Внешние средства:
Захватить весь экран. Но у подхода есть недостатки: расходует ресурсы и влияет на результат измерений.
Взять устройство HDMI Capturer. С его помощью можно записывать в файл содержимое экрана. Приложение передаёт изображение на него как на обычный монитор.
Инструменты для измерения качества видео
Мы используем два основных:
PSNR (Peak Signal‑to‑Noise Ratio). Популярный инструмент, но оценивает видео покадрово.
VMAF (Video Multimethod Assessment Fusion). Алгоритм от компании Netflix, оценивает качество картинки так же покадрово, как и PSNR.
Применение инструментов
Рассмотрим, как устроен стенд для проведения измерений. Ниже представлена схема:
Слева на схеме наш QA‑инженер или разработчик, который должен сделать замеры. Он запускает задачу в TeamCity и выбирает, на каком контуре провести тестовый звонок. Измерение можно запустить как на продакшене, так и в лаборатории.
TeamCity поднимает тестового клиента № 1, который совершает звонок в нашу систему. Тестовый клиент № 2 принимает его. Между клиентами устанавливается связь по сигналингу, начинает ходить аудио и видео.
После этого тестовый клиент № 1 проигрывает референсное видео в сторону получателя, клиента № 2. Затем полученное и референсное видео подаются в VMAF. Он выдаёт оценку, и инженер видит её в артефактах сборки TeamCity.
Мы также умеем «портить» сеть между клиентами и сервисом. Так можно симулировать различные проблемы, а потом оценивать, как ведёт себя система с точки зрения качества видео.
Подготовка референсов
Напомню, мы используем покадровое сравнение. Оно подразумевает, что и в референсе, и в полученном видео набор кадров будет одинаковый. Ниже расскажу, как мы этого добиваемся.
Для начала маркируем каждый фрагмент тестового видео шахматной доской:
С её помощью мы контролируем границы видео и смотрим, нет ли геометрических искажений.
Для последующего анализа важно, какой именно фрагмент видео используется. Для этого маленькими квадратами внутри доски в двоичном коде мы кодируем идентификатор фрагмента: разные фрагменты имеют разные идентификаторы.
Далее размечаем каждый кадр:
Чёрная полоса сверху — это двоичные разряды: чёрные — 0, белые — 1. Каждый кадр имеет свой числовой идентификатор, целое число, но в битовом представлении.
Алгоритм действий после приёма видео:
Анализируем полученное в тесте видео на потерянные кадры.
Собираем опорное видео для VMAF: из исходного референса выбираем только те кадры, которые есть в полученном фрагменте. Если каких‑то кадров не хватает, то мы убираем их и в референсе. То есть пересобираем его таким образом, чтобы остались только кадры, которые мы получили в видео из звонка системы.
Полученный FPS сохраняем отдельно от VMAF. VMAF сравнивает кадр к кадру, поэтому мы должны обеспечить синхронизацию. Выпущенные кадры логируем в файл для инженера, который будет искать выпавшие кадры.
Примеры замеров
Замер № 1:
Видео почти 2 мегабита в секунду с хорошим качеством картинки. VMAF даёт высокую оценку — 95 из 100. PSNR — 50, тоже подтверждает качество.
Замер № 2:
Артефактов мало, и картинка не сильно отличается от предыдущего примера, притом что её сжали почти в 4 раза. VMAF выдаёт значение 87. Это не идеально, но и не плохо. PSNR немного пострадал, снизился до 47.
Замер № 3:
Здесь уже заметны артефакты, 150 килобит в секунду маловато для видео. VMAF упал до 63 из 100, PSNR снизился до 43.
Пример № 4:
Последний фрагмент — видео плохого качества. VMAF — 23 из 100, а PSNR — 38.
Что мы можем «отловить» по результатам измерений:
Артефакты внутри видео, которые появились из‑за потери пакетов или каких‑то сетевых проблем.
Разрешение картинки ниже ожидаемого. Наши оценки покажут, если исходная картинка была большая, а потом её размер уменьшили на сервере.
Видео обрезалось или сдвинулось. Например, если при перекодировании были проблемы на сервере, мы это увидим благодаря той самой шахматной доске.
Видео слишком сильно сжато кодеком. Это квадраты при достаточно низком битрейте.
Мы подробно описали, как устроен стенд для измерений, а также сделали систему мониторинга нашего продакшен‑окружения. Эта система автоматически активирует стенд каждые 15 минут, чтобы проверить качество видео на продакшене и занести данные об измерениях в специальный график. Благодаря этому мы можем постоянно отслеживать изменения и фиксировать любое снижение качества.
Подведём итоги
Чтобы пользователь был доволен, нам необходимо найти баланс между размером видео и степенью его сжатия с учётом сетевых условий. Важно помнить, что высококачественное видео всегда тяжёлое, его сложно отправить пользователю. Сильно сжатое видео легко передаётся по сети, но со значительным искажением транслируемой картинки.
Качество видео можно измерить с помощью PSNR и VMAF, которые основаны на математических расчётах и дают воспроизводимые результаты. Если мы протестируем одно и то же изображение несколько раз, итоги будут одинаковыми.
Эти инструменты позволяют оценить, насколько хорошо нам удаётся улучшить качество видео. Мы можем тонко настраивать Transport‑CC в лаборатории или уже на продакшене и оценивать влияние доработок на изображение в видеозвонке.