Skip to content

Виртуальный фон

Кейс по встраиванию виртуального фона в браузерную видеоконференцию как части боевого видеостека, а не отдельного демо-эффекта.

Задача

Реализовать виртуальный фон в конференции с несколькими режимами:

  • размытие фона;
  • замена фона на изображение;
  • замена фона на видео.

За основу для сегментации человека был взят MediaPipe.

Контекст

Функция должна была работать внутри уже существующего клиентского пайплайна видеоконференции. Недостаточно было просто получить маску человека и нарисовать кадр на canvas.

Нужно было встроить обработку в реальный поток камеры так, чтобы не ломались:

  • включение и выключение камеры;
  • переключение между устройствами;
  • отправка локального видео в WebRTC;
  • пользовательский интерфейс выбора фона;
  • загрузка и хранение пользовательских фонов.

Как работало решение

Видео с камеры передавалось в обработчик, где для каждого кадра строилась маска человека. Дальше на основе этой маски выполнялась композиция итогового кадра:

  • человек оставался на переднем плане;
  • задний план размывался либо заменялся;
  • результат собирался на скрытом canvas.

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

Такой подход позволил встроить виртуальный фон в существующую логику WebRTC без перестройки остальной схемы работы конференции.

Что пришлось решить

1. Управление производительностью

Сегментация и перерисовка кадра создают заметную нагрузку на клиентскую машину. Поэтому обработка работала с отдельной частотой видеопроцессора: итоговый поток можно было считать с собственным videoProcessorFps, отдельно от базового framerate камеры.

Это позволило разделить две вещи:

  • с какой частотой камера отдает исходный поток;
  • с какой частотой поверх него выполняется тяжелая сегментация и сборка итогового кадра.

За счет этого можно было снижать нагрузку на CPU без полного отключения эффекта: не прогонять сегментацию на каждом кадре исходного потока, если машина пользователя не справляется.

Дополнительно использовались ограничения по width, height и framerate входного потока. Это позволяло снижать стоимость сегментации и композитинга еще до этапа обработки.

2. Борьба с просадкой fps

Для такой функции проблема не только в высоком CPU, но и в том, что при перегрузке пользователь сразу видит просадку плавности. Поэтому был реализован адаптивный профиль обработки:

  • отдельный videoProcessorFps для ограничения частоты тяжелой обработки;
  • управление параметрами входного потока камеры через width, height, framerate;
  • возможность горячо перезапустить локальный видеопоток с новыми параметрами без развала конференции;
  • продуктовый режим virtual_bg_blur_only, когда можно оставить только наиболее легкий сценарий без картинки и видео;
  • адаптивное снижение videoProcessorFps, если время обработки кадра стабильно превышало бюджет кадра;
  • автоматическое понижение разрешения входного видео при длительной перегрузке;
  • профили качества low, medium, high, в которых одновременно менялись fps, разрешение и тип фона;
  • приоритет размытия над видеофоном на слабых машинах, потому что видеофон почти всегда тяжелее статического изображения и блюра;
  • автоматический возврат к более высокому fps и качеству после стабилизации нагрузки.

За счет этого виртуальный фон не пытался любой ценой держать максимальное качество, а динамически удерживал стабильную плавность. Для видеозвонка это важнее, чем максимально "красивый" фон ценой перегруженного CPU и дерганого видео.

3. Встраивание в живой видеопайплайн

Виртуальный фон был встроен не как отдельный preview-виджет, а как часть объекта работы с камерой.

Для этого:

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

Это дало "бесшовное" переключение фона во время звонка без развала сессии. Дополнительно такая схема позволила быстро менять профиль качества: снижать параметры видеопотока и тут же переключать обработанный стрим без переподключения пользователя к конференции.

4. API для пользовательских изображений

Для фоновых картинок была сделана серверная часть:

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

Дополнительно были учтены прикладные ограничения:

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

Это превратило функцию из локального эффекта "только на текущей вкладке" в полноценную пользовательскую возможность.

5. Хранение видеофонов на клиенте

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

Отдельно пришлось решать вопросы жизненного цикла таких данных: когда видео еще используется, а когда его уже можно выгружать и освобождать память.

6. Работа с ресурсами

Для обработки использовались скрытые video-элементы и canvas, которые участвовали в построении результирующего потока. В такой задаче легко получить утечки памяти и "висящие" ресурсы, особенно если пользователь:

  • часто включает и выключает камеру;
  • меняет фон на лету;
  • переключается между камерами;
  • несколько раз открывает и закрывает связанные элементы интерфейса.

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

С точки зрения борьбы с производительностью это тоже важно: утечки video, canvas и загруженных видеофонов со временем бьют по памяти, а затем начинают ухудшать и fps, и общую отзывчивость интерфейса.

7. UI и продуктовые ограничения

В интерфейс была добавлена возможность выбрать режим виртуального фона: размытие, картинка или видео. При этом на уровне настроек конференции была предусмотрена и продуктовая опция, позволяющая оставить только режим размытия, если полноценные фоны в конкретном сценарии нежелательны.

Это было полезно не только как бизнес-настройка, но и как средство контроля производительности: для части клиентов или тарифов можно было осознанно оставить только более легкий режим.

Результат

В итоге в продукте появился полноценный виртуальный фон, встроенный в конференцию:

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

См. также

Сайт обновлен и проверен: