Виртуальная камера для WebRTC

8b797a9b4ef51c4aec66ccf86e47823e

Небольшое введение

Едва ли кто-то избежал использования видеоконференций. К назначенному времени проверяем свой skype look, усаживаемся поудобнее и общаемся с коллегами.

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

А еще варианты? да пожалуйста!

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

  • можно подойти к задаче по-взрослому: под linux, например, запускаем v4l2loopback и рисуем в виртуальную вебкамеру что душе угодно, в зависимости от фантазий и возможностей железа. Если GPU позволяет, можно пропатчить, например, rad-nerf и вложить свою речь в уста Обамы, или даже тайком записать начальника на видео и по нему, за несколько часов, обучить модель. При рендеринге, правда, появится изрядная задержка, и придется либо мириться с липсинком, либо использовать в виртуальные аудиоустройства, либо ухудшать фонемную анимацию за счет использования мел-спектрограмм. И хорошо бы, чтобы ваша ноутбучная GTX 4060 не перегрелась за время разговора

  • а если в ноуте GPU слабенькая? Тоже не беда, зацикливаем свой ролик, и wav2lip дорисует на нем движения губ, густо замазывая погрешности. Красота!

Правда, с масштабируемостью у подобных подходов беда. Да и, вообще, как-то тупиково все это.

И мы пойдем другим путем!

Итак, есть желание рассказать про нашу собственную технологию виртуальной () персонифицированной () камеры для WebRTC (*).

Начнем с последнего слова (*). Если вы не используете совсем уж динозавров типа skype, то с вероятностью, стремящейся к единице, вы еженедельно сталкиваетесь с WebRTC.

Строго говоря, WebRTC — это целый сонм технологий. Тут и работа с локальными устройствами, и проковыривание всяких там nat-ов, и контроль соединения, и разнообразные заморочки с кодированием аудио-видео, и шифрование…
Но, в контексте данной задачи, нам важно, чтобы

  1. JS код в браузере захватил аудиоустройство пользователя (getUserMedia).

  2. В peerconnection должны уйти аудио и видео треки, синхронные между собой А посередине вся магия. О ней мы и поговорим.

Наша камера (*) виртуальная, потому что видеокамеру вашего девайса мы не используем, но видео выдаем. Откуда же возьмется видеодорожка? Странный вопрос. Из канваса, конечно! Ибо для WebRTC, по большому счету, безразлично, откуда появился видеотрек: из камеры ли, из канваса или с экрана. Таким образом, нам надо анимировать 3D модель и отрендерить кадры в канвас.

Пара слов про анимацию

Грубо говоря, анимацию можно условно разделить на 2 части: «фоновая», не связанная с произносимыми звуками (микродвижения и моргание глаз, повороты головы, движение на лбу и переносице, кадык и тп), и фонемная, соответствующая произносимому звуку. Очевидно, для первой части анимации можно использовать предзаготовленные паттерны, для второй необходимо в реальном времени (или близко к тому) вычислять некоторые параметры, что мы и делаем посредством легковесных моделей.

Итак, частотой кадров мы должны синтезировать картинки на основе 3D модели и входных векторов, описывающих состояние анимационных паттернов в данный момент времени.

Оставив в стороне сетки, есть два основных способа рендеринга 3D модели:

  1. на основе параметрической модели (рига)

  2. морфинг с весовыми коэффициентами, определяемыми параметрами выше. Именно так мы и делаем:

  • идентифицируем юзера (вы же не хотите, чтобы под вашей моделью пользовался какой-нибудь тролль?)

  • скачиваем с облака Флексатар — условно говоря, файл с набором данных для image based rendering. Можно себе это условно представить как набор изображений 3D модели с разных ракурсов (на всякий случай, нет в английском такого слова) и с разными снапшотами мимики. Да, автокоррекция все еще пытается исправить слово Флексатар, но мы сделаем все возможное, чтобы оно, вместе с нашей технологией, стало массовым

  • Отправляем аудио с микрофона на обработку, добавляем к полученному вектору анимационный, «смешиваем» картинки и отрисовываем с WebGL.

  • Аудиодорожку, задержанную на часть скользящего окна для вычислений, отправляем вместе с видео из канваса.

После этого ничего не подозревающий SFU сервер, раздающий треки участникам внутри комнаты, отправит ваше медиа коллегам, и они увидят, как вашим голосом говорит Крош или Нюша из Смешариков.

А как же задержка? Не страшно, коллеги ничего не заметят. Мы же можем разговаривать по телефону с людьми с другой стороны планеты, хотя задержка при этом выше, особенно с использованием спутниковых каналов и кодеков.

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

Что касается задержки на время обработки, это всегда компромисс. Одна крайность — обрабатывается фраза целиком, происходит распознавание текста с коррекцией на основе языковой модели. Далее используется forced alignment для привязки правильных фонем ко времени, и качество анимации лимитируется только профессионализмом разработчика алгоритма. Например, чтобы губы не шлепали, они должны «склеиваться» и тянуться при разлипании. Но мы же не про кино, и задачей является создание комфортной иллюзии живого собеседника в реалтайме, и мы не можем себе позволить коррекцию. Качество несколько ухудшается, и это плата за время:»- Нет в мире совершенства! — вздохнул Лис»

Создание 3D моделей

Мы не всегда хотим разговаривать с коллегами в образе жизнерадостного Копатыча. Переходим к самому интересному: (*) персонифицированная. За 5 лет выработали свой алгоритм создания 3D модели, на основе которой создается Флексатар. Да, если есть потребность, мы умеем экспортировать 3D объект в виде меша требуемой полиномиальности и текстур, но для задач реалтайм общения этого не надо.

Для расчетов требуется GPU, но на 3080 это занимает порядка 15 секунд при смешной загрузке. Для создания флексатара потребуются 5 фото: одно фронтальное и 4 с небольшим (что важно) поворотом головы. И это можно сделать прямо из браузера, а в конце статьи есть ссылка на гит, как заставить модель говорить.

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

Поскольку это 3D, мы можем не просто создавать флексатары, но и смешивать их, добавляя неуловимые ассоциации. Но это уже другая история.

Гиты и приглашения

Исходники анимирования аудиозаписи в браузере: https://github.com/dmisol/sfu2/blob/main/static/webgl.html

Гит с виртуальной вебкамерой: https://github.com/dmisol/flexatar-virtual-webcam

Помимо этого, у нас запущен тестовый сервер, https://flexatar.com с серверной версией рендеринга, где SFU на библиотеке PION (GOLANG) декодирует OPUS аудио для обработки и собирает свежеотрендеренные кадры в H264 видеодорожку. На этом сервере можно создать свой флексатар, пообщаться с другими людьми (если они онлайн), а также посмотреть браузерную анимацию на WebGL. *Естественно, когда он жив и не используется для экспериментов

Исходники SFU тут https://github.com/dmisol/sfu2

Вся работа производилась на протяжении 5 лет очень небольшой командой, без финансирования и, в общем случае, в свободное от основной работы время (успешно избегая конфликта интересов).

В настоящий момент, помимо улучшения качества, мы занимаемся
портированием серверной части на AWS и, частично, Яндекс облако.
Планируем интеграции с различными SFU, для начала, Janus и Livekit.

© Habrahabr.ru