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

Едва ли кто-то избежал использования видеоконференций. К назначенному времени проверяем свой 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 https://flexatar.com/webgl Естественно, когда сервер жив и не используется для экспериментов

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

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

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

Комментарии (15)


  1. dmi3soloviev Автор
    29.11.2023 18:00
    +2

    Коллеги, честно признаюсь, пустился в литературное творчество с тремя сугубо меркантильными целями:

    1. найти игроков в команду. Есть планы и по беку (golang), и по мобильным приложениям. Но наша главная беда - фронтенд. Сейчас денег в проекте нет. Совсем. Но, очень надеюсь, "так будет не всегда"

    2. выйти на компании, использующие WebRTC технологию для выстраивания честных партнерских отношений. Интим "профильное трудоустройство" не предлагать

    3. Научиться правильно преподносить идею виртуальной вебкамеры.

      Буду искренне благодарен за любой фидбек!


  1. wataru
    29.11.2023 18:00

    Главная проблема вашего подхода - вам надо или условный google meet патчить, или эта камера будет работать только в вашем приложении для конференции.

    Так-то уже есть OBS с его виртуальной камерой.


    1. dmi3soloviev Автор
      29.11.2023 18:00

      ну, вот, опять я не смог внятно объяснить. пункт 3 в действии..

      наши сильные стороны:

      1. умение быстро создать 3d модель данного человека. и это не "что сетке приглючится", а честная модель на основе математики

      2. дешево анимировать 3d модель, преобразованную в формат флексатара, вплоть до уверенной анимации в браузере, без каких-либо специфических требований к оборудованию или ОС. нам неизвестны столь легковесные технологии. и это открывает дверь в WebRTC для создания простого и масштабируемого коммерческого решения "не для гиков"

      Используя два названных козыря, мы планируем создавать, хранить и предоставлять эти модели как сервис, для различных коммерческих WebRTC SFU/MCU, мессенджеров и, строго говоря, даже игр (мы же можем выгрузить модель как набор текстур и obj файл в любой требуемой полиномиальности, или параметризовать используемую в игре модель юзера). Честно, история с играми вне моих компетенций, так что далее врать не буду.

      Безусловно, надо будет индивидуально интегрироваться с каждой WebRTC платформой. Но ведь это же желаемый B2B рынок, монетизация! Нам та или иная платформа подписывает JWT, который мы получаем напрямую от фронтенда/приложения. В соответствии с содержимым токена, мы позволяем юзеру выбрать модель для данной сессии и выгружаем один из флексатаров данного юзера в браузер или приложение.

      С точки зрения разработчика фронтенда, интеграция с нами тривиальна. То же относится и к iOS/Android


      1. twinsbox89
        29.11.2023 18:00
        +1

        Ну тут есть варианты, вот пример чего мы делаем: https://chromewebstore.google.com/detail/ai-webcam-visual-effects/iedbphhbpflhgpihkcceocomcdnemcbj
        По сути свопаем стрим, а само приложение (google meet, zoom, teams ... и т.д.) даже не в курсе что стрим не с камеры.
        И получается вполне себе виртуальная камера, прямо в браузере. И продвигать можно B2C :)
        Точно также и с аудио можно поступать, добавлять нужную задержку для синхронизации.


        1. dmi3soloviev Автор
          29.11.2023 18:00

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


      1. jetdream
        29.11.2023 18:00
        +1

        А думали о варианте сделать расширение для Chrome, которое в реальном времени подменит браузерное WebRTC API (getUserMedia ) так, чтобы Web-приложение думало, что оно работает c обычной камерой?
        Я как-то просматривал технические подходы к решению защиты от browser fingerprinting, там широко используется подмена стандартных браузерных API, которые реализуются подменой свойств JS объекта.
        Интересен будет ваш опыт.


        1. dmi3soloviev Автор
          29.11.2023 18:00

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


  1. muxa_ru
    29.11.2023 18:00

    умение быстро создать 3d модель данного человека. и это не "что сетке приглючится", а честная модель на основе математики - https://habr.com/ru/articles/777286/#comment_26213030

    Проверку биометрии этой штукой обмануть уже можно?


    1. dmi3soloviev Автор
      29.11.2023 18:00
      +1

      это как проверять, наверное.
      но я не буду! безопаснее этого просто не знать)


      1. muxa_ru
        29.11.2023 18:00

        :)


  1. persona
    29.11.2023 18:00

    В Teams это уже реализовано: https://www.youtube.com/watch?v=49SlDQ6tLXU


    1. dmi3soloviev Автор
      29.11.2023 18:00

      ну там же мультяшные образы, а у нас - как живые


      1. persona
        29.11.2023 18:00
        +1

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


  1. DirectX
    29.11.2023 18:00

    Для рендеринга в браузере наверное лучше использовать Rust + WASM.


    1. dmi3soloviev Автор
      29.11.2023 18:00

      у нас в команде, к сожалению, нет таких навыков