Визуальная синхронизация губ — один из факторов, определяющих, воспринимается ли 3D-персонаж как живой собеседник, а не как говорящая голова с произвольно двигающимся ртом [1]. В системах, где ответ языковой модели синтезируется в речь потоково (первое предложение озвучивается, пока генерируется следующее), аудио и данные для анимации поступают в браузер по частям — отдельными независимо синтезированными фрагментами по мере готовности. Например, если ответ состоит из трёх предложений, зритель услышит и увидит анимацию первого предложения ещё до того, как второе и третье вообще сгенерированы языковой моделью — к моменту готовности последнего фрагмента первый уже давно отыгран. Это меняет саму постановку задачи lip sync: вместо однократного сопоставления фонем с одним аудиофайлом требуется бесшовная анимация, собираемая из потока фрагментов, границы между которыми клиент не должен показывать зрителю.
Требуется способ формирования анимации рта 3D-аватара, удовлетворяющий трём условиям: (1) анимация конкретного фрагмента речи должна становиться доступной сразу по готовности этого фрагмента, без ожидания полного ответа; (2) переход между анимацией, порождённой соседними фрагментами, не должен создавать заметного скачка; (3) вычисление анимации на каждый кадр рендеринга должно быть дешёвым, поскольку выполняется на клиентском устройстве, а не на сервере. На рис. 1 показана общая схема конвейера: от генерации текста до анимации в браузере.
Рис. 1. Потоковая сборка анимации: сервер обрабатывает фрагменты по мере готовности, транспорт гарантирует порядок и доставку, клиент рендерит покадрово; ниже показано перекрытие фрагментов 1–3 во времени
Существующие инструменты извлечения визем из аудио, включая Rhubarb Lip Sync [2], спроектированы для офлайн-обработки одного законченного файла целиком: они принимают на входе весь WAV-файл и возвращают полную временную шкалу визем за один вызов. Это хорошо работает для предзаписанной речи, но не рассчитано на ситуацию, когда в момент вызова доступен только очередной фрагмент ответа, а остальные ещё не существуют — инструмент как таковой не меняется, меняется то, как часто и над какими фрагментами он вызывается. В отличие от такого офлайн-подхода, предлагаемый метод рассматривает временную шкалу визем не как единый артефакт, готовый только по завершении всего ответа, а как поток независимых сегментов, каждый из которых обрабатывается и визуализируется сразу после синтеза соответствующего аудиофрагмента — это и устраняет необходимость ожидания полного завершения генерации ответа.
После синтеза аудио для очередного фрагмента текста WAV-файл передаётся тому же анализатору звуковой волны, который возвращает временную шкалу визем (список пар «визема, время начала»), но уже только для этого фрагмента, а не для ответа целиком. Классификация ведётся по стандарту Престон Блэр [2], сокращающему многообразие фонем до девяти базовых визуальных форм рта: покой, смыкание губ, заднеязычные, шипящие, передние гласные, открытые гласные, лабиодентальные, зубные и альвеолярные согласные. Такое сокращение размерности принципиально для работы в реальном времени: девяти визуальных состояний достаточно для убедительной синхронизации, и они на порядок дешевле в вычислении и передаче, чем покадровая реконструкция формы рта.
Каждый фрагмент включает аудио в закодированном виде, массив визем с временными метками и идентификатор трека; всё это доставляется в браузер по мере готовности. Доставка идёт через постоянное соединение поверх той же инфраструктуры гарантированной доставки, что используется для остальных этапов конвейера: фрагменты не теряются и не приходят из очереди в перепутанном порядке. Поэтому на уровне анимации не нужно отдельно решать задачу упорядочивания или повторного запроса — она уже решена транспортным слоем, и анимация вправе полагаться на чистый, последовательный поток фрагментов. Клиент декодирует аудио через встроенный аудио-API и на каждом кадре рендеринга вычисляет смещение времени относительно начала воспроизведения текущего трека. Поскольку физиологически движение губ опережает звук, вычисленное смещение дополнительно корректируется на небольшую константу в сторону опережения. Так в анимацию закладывается известный эффект восприятия речи [1].
Прямое переключение между визуальными состояниями по границе временной метки визуально выглядит как дискретный скачок. Чтобы этого избежать, функция смешения на каждый момент времени t отвечает не одной готовой формой рта, а связкой из трёх чисел: какая визема сейчас, какая будет следующей, и насколько далеко мы продвинулись от одной к другой. Последнее — прогресс α — это просто доля пройденного пути между двумя соседними метками по времени: 0 сразу после смены визем, 1 прямо перед следующей. Формально: α = (t − t₀) / (t₁ − t₀), где t₀ и t₁ — метки времени текущей и следующей визем. Дальше 3D-рендерер сам плавно перетекает от одной формы рта к другой — технически это называется blend shape (веса, задающие, насколько сильно 3D-модель лица деформирована в сторону той или иной виземы), и рендерер смешивает веса двух соседних визем именно в пропорции α. Саму пару «текущая-следующая визема» ищет не полный перебор всех накопленных меток, а более быстрый бинарный поиск по отсортированному списку — грубо говоря, деление списка пополам на каждом шаге вместо проверки всех элементов подряд; на клиенте счёт визем может идти на сотни за диалог, и такой поиск не замедляется пропорционально их числу. Такая же логика смешения реализована дважды — на клиенте, работающем в браузере на TypeScript, и в переносимом виде на языке Rust для встраиваемых сценариев (десктопный клиент, плагин для стороннего программного обеспечения трансляции), где безопасность работы с памятью на уровне компиляции важна для стабильности процесса, работающего часами без перезапуска.
Помимо речи, персонаж должен независимо моргать, менять выражение лица и позу в такт эмоциональному тону реплики. Вместо настройки каждого канала анимации по отдельности все контроллеры читают единую структуру состояния. В её основе — трёхмерный эмоциональный вектор: валентность (насколько реплика позитивна или негативна по тону), возбуждение (насколько она энергична или, наоборот, спокойна) и доминирование (насколько уверенно или подчинённо звучит персонаж). Плюс вспомогательные параметры энергии, внимания и комфорта. Всё это формируется языковой моделью по ходу диалога. Наклон головы определяется осью доминирования; скорость анимации и физика вторичного движения — осью возбуждения; частота и характер моргания зависят от совокупного состояния. Такая архитектура устроена как реестр независимых контроллеров: они читают общее состояние и исполняются поочерёдно на каждом кадре. Новое поведение добавляется реализацией одного интерфейса без изменения существующих контроллеров и без риска рассогласования между каналами, поскольку все они управляются одним и тем же источником эмоционального состояния.
Метод реализован для аватаров в формате VRM [3], рендеринг которых на клиенте выполняется средствами WebGL через библиотеку three-vrm [4]. Реализовано пять контроллеров анимации: моргание, взгляд, локомоция и эмоциональные жесты через конечный автомат, мимика, наклон головы и вторичная физика. Они работают независимо друг от друга поверх общей структуры эмоционального состояния и потока визем, поступающего вместе с аудио.
Корректность функции смешения (граница временной шкалы, середина интервала, момент после конца, отклонение некорректных данных при десериализации) проверена девятью модульными тестами, все проходят. Стоимость самого вычисления измерена микробенчмарком (criterion [5], 100 замеров на сценарий) на реалистичном фрагменте речи — таймлайне с визической плотностью около одной смены визем на 150 мс, что соответствует типичной выдаче анализатора на непрерывной речи. Результаты — в таблице 1.
Таблица 1
Стоимость вычисления смешения визем (criterion, N = 100)
|
Сценарий |
Время |
|
Один вызов, фрагмент 3 с, 20 визем |
12,7 нс |
|
Один вызов, фрагмент 8 с, 50 визем |
15,1 нс |
|
Весь фрагмент 3 с при 60 кадр/с (180 вызовов) |
2,59 мкс |
Рост числа визем в 2,5 раза (с 20 до 50) увеличивает время одного вызова лишь на 19 % — это согласуется с логарифмической, а не линейной зависимостью от бинарного поиска. Обработка всех 180 кадров за проигрывание трёхсекундного фрагмента занимает 2,59 мкс совокупно — при бюджете в 16 700 мкс на один 60-кадровый цикл рендеринга — это менее 0,02 % бюджета, что подтверждает условие (3) числом, а не только словом «дёшево». Измерение охватывает исключительно саму функцию смешения в изоляции — оно не включает декодирование аудио, работу WebGL-рендерера или сетевую доставку фрагмента, и не является оценкой сквозной задержки всего диалогового конвейера.
Метод рассчитан на аватары с ограниченным, заранее известным набором визуальных выражений и не рассчитан на фотореалистичную реконструкцию формы рта по звуку — для такой задачи требуется принципиально иной подход на основе покадровой генерации изображения. Разделение ответственности между транспортным слоем и слоем анимации, описанное выше, работает только пока гарантии транспорта действительно соблюдаются: если развернуть тот же клиент поверх канала без гарантии доставки и порядка, придётся либо вернуть буферизацию и переупорядочивание на уровень анимации, либо мириться с редкими видимыми разрывами — метод не пытается быть устойчивым к обоим случаям одновременно, и это осознанный выбор границы, а не упущение.
Весовые коэффициенты сопоставления визем с фонемами подобраны по опубликованному стандарту [2] и не переоценивались экспериментально для конкретной реализации. Величина опережающей коррекции времени задана константой, а не выведена из измерений конкретной модели синтеза речи, — для голосов с иной артикуляционной динамикой она может потребовать пересчёта. Измерена стоимость только самого вычисления смешения визем в изоляции; сквозная задержка от готовности аудиофрагмента до отрисованного кадра на экране, включающая сеть, декодирование и рендеринг WebGL, отдельно не измерялась. Субъективная оценка убедительности синхронизации пользователями также не проводилась. Быстрое вычисление ещё не гарантирует, что зритель воспримет результат как достаточно плавный — это отдельный вопрос, и на него статья ответа не даёт.
Показано, что при потоковом синтезе речи задача синхронизации губ переходит от однократной обработки целого аудиофайла к бесшовной сборке анимации из независимо синтезированных фрагментов, а перенос ответственности за порядок и полноту потока на транспортный слой позволяет слою анимации оставаться простым. Предложенная архитектура реализована для 3D-аватаров и переносима между браузерным и встраиваемым окружением; корректность смешения визем подтверждена модульными тестами, а его вычислительная стоимость — микробенчмарком, показавшим менее 0,02 % бюджета одного кадра при 60 кадр/с.
Литература:
- Miller M. R. Timing Matters: Effects of Response Delay on Perceived Naturalness in Robot Conversations: MSc project. — Oregon State University, 2025.
- Wolf D. Rhubarb Lip Sync [Электронный ресурс]. — 2024. — Режим доступа: URL: https://github.com/DanielSWolf/rhubarb-lip-sync (23.07.2026)
- VRM Consortium. VRM: A 3D Avatar File Format for VR Applications [Электронный ресурс]. — 2023. — Режим доступа: URL: https://vrm.dev/en/ (23.07.2026)
- Pixiv Inc. three-vrm: VRM for Three.js [Электронный ресурс]. — 2024. — Режим доступа: URL: https://github.com/pixiv/three-vrm (23.07.2026)
- Criterion.rs: Statistics-driven Microbenchmarking in Rust [Электронный ресурс]. — 2024. — Режим доступа: URL: https://github.com/bheisler/criterion.rs (23.07.2026)

