ГлавнаяБлогBarkReels: как я сделал AI-видео с говорящей собакой без бэкенда
AI / Нейросети

BarkReels: как я сделал AI-видео с говорящей собакой без бэкенда

Создайте видео с говорящей собакой прямо в браузере: без бэкенда, только клиентский код. Узнайте, как работает пайплайн и как повторить.

Al
Редакция Algolitalgolit.ru
8 мин чтения17 августа 2026 г.

Как заставить собаку говорить: мой опыт создания AI-видео без бэкенда

Моя собака имеет мнение, но никогда его не высказывала. Поэтому я создал BarkReels: вы загружаете фото, а она получает голос. Рот двигается в такт аудио, она моргает, уши подрагивают, субтитры появляются, и на выходе — настоящий MP4. В этой статье я расскажу, как построить такой пайплайн без единого сервера, и поделюсь кодом, который вы можете использовать для своих проектов.

Что такое BarkReels и почему это работает

BarkReels — это клиентское приложение, которое генерирует видео с говорящей собакой. Оно использует API для зрения и синтеза речи, но вся обработка — сегментация, анимация и кодирование — происходит в вашем браузере. Это возможно благодаря современным веб-технологиям: WebGL, WebCodecs и ONNX Runtime. Вам не нужен бэкенд, потому что всё тяжёлое выполняется на вашем GPU.

Архитектура: как всё устроено

Пайплайн выглядит так:

фото ──┬─→ vision-модель ──→ порода, настроение, монолог, координаты морды
       └─→ ISNet (ONNX, в браузере) ──→ вырезанная собака с альфа-каналом

монолог ──→ ElevenLabs ──→ аудио + таймстампы слов
                               │
                               ├─→ огибающая громкости (асимметричное сглаживание)
                               └─→ тайминг субтитров

огибающая + координаты + вырезка ──→ анимационный риг ──→ WebGL-деформация ──→ кадры
                                                                          │
                                          WebCodecs H.264 + AAC ──┴──→ MP4

Ключевая идея — renderFrame(t) — чистая функция от времени. Она не читает часы, не зависит от состояния воспроизведения и не меняет ничего, что повлияло бы на будущие вызовы. Это позволяет использовать один и тот же код для предпросмотра и экспорта, гарантируя идентичный результат.

Как заставить рот двигаться: синхронизация губ

Синхронизация губ — это не нейросеть. Я использую огибающую громкости аудио с асимметричным сглаживанием: атака 15 мс, спад 90 мс. Мышцы резко открывают пасть и плавно закрывают. Симметричное сглаживание вызывает дрожание рта между слогами, как у индикатора уровня. Эта асимметрия дала больше реализма, чем всё остальное.

Пример кода: вычисление огибающей

import numpy as np

def compute_envelope(audio, sr, attack=0.015, release=0.09):
    """Вычисление огибающей громкости с асимметричным сглаживанием."""
    # Прямоугольное интегрирование для получения амплитуды
    frame_size = int(sr * 0.01)
    hop = frame_size // 2
    rms = []
    for i in range(0, len(audio) - frame_size, hop):
        rms.append(np.sqrt(np.mean(audio[i:i+frame_size]**2)))
    rms = np.array(rms)

    # Асимметричное сглаживание
    attack_coef = 1 - np.exp(-1 / (sr * attack / hop))
    release_coef = 1 - np.exp(-1 / (sr * release / hop))
    envelope = np.zeros_like(rms)
    envelope[0] = rms[0]
    for i in range(1, len(rms)):
        coef = attack_coef if rms[i] > envelope[i-1] else release_coef
        envelope[i] = coef * rms[i] + (1 - coef) * envelope[i-1]
    return envelope

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

Как получить координаты морды: Google AI в одном запросе

Google Gemini Flash выполняет две задачи за один вызов: пишет монолог от лица собаки и возвращает нормализованные координаты ограничивающих рамок для носа, рта, глаз и ушей. Эти координаты используются шейдером для деформации. Когда вы пишете свой сценарий, запрос изменяется, и модель тратит все внимание на координаты.

Пример запроса к Gemini

import google.generativeai as genai

# Инициализация
 genai.configure(api_key='YOUR_API_KEY')
model = genai.GenerativeModel('gemini-1.5-flash')

# Запрос с фото и инструкцией
response = model.generate_content([
    {"mime_type": "image/png", "data": photo_bytes},
    "Верни JSON: breed, mood, monologue, anchors (nose, mouth, eyes, ears) с координатами в диапазоне [0,1]."
])

# Парсинг ответа
import json
result = json.loads(response.text)
print(result['anchors'])

Таким образом, мы получаем координаты, которые анимируем.

Как озвучить: ElevenLabs с таймстампами

ElevenLabs делает больше, чем просто читает текст. Эндпоинт /with-timestamps возвращает тайминги на уровне символов вместе с аудио. Эти тайминги управляют караоке-субтитрами, а огибающая громкости, полученная из того же аудио, управляет челюстью. Голос — не украшение, а источник анимации.

Пример запроса к ElevenLabs

import requests

url = "https://api.elevenlabs.io/v1/text-to-speech/{voice_id}/with-timestamps"
headers = {"xi-api-key": "YOUR_KEY"}
data = {
    "text": "Привет, я Барк!",
    "model_id": "eleven_monolingual_v1",
    "voice_settings": {"stability": 0.5, "similarity_boost": 0.5}
}
response = requests.post(url, json=data, headers=headers)
result = response.json()
# result['audio_base64'] и result['alignment'] содержат тайминги

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

Как анимировать в WebGL: чистая функция времени

Анимация в WebGL использует шейдеры, которые деформируют изображение в соответствии с координатами и огибающей. Главный принцип — renderFrame(t) не зависит от внешнего состояния. Это позволяет легко реализовать предпросмотр и экспорт.

// Псевдокод для WebGL-рендера
function renderFrame(t) {
    // t — время в секундах
    const envelope = getEnvelopeAtTime(t); // из аудио
    const mouthOpen = envelope * mouthScale;
    // передать uniform в шейдер
    gl.uniform1f(mouthLoc, mouthOpen);
    // нарисовать текстуру с деформацией
    drawScene();
}

Экспорт — это просто цикл по кадрам с вызовом renderFrame и кодированием через WebCodecs.

Как получить лучший результат: советы по фото

Анимация двигает конкретные анатомические точки, поэтому фото имеет огромное значение. Вот что я выяснил методом проб и ошибок:

  • ✅ Анфас. Профиль скрывает глаз и ухо, и риг не может анимировать эту сторону.
  • ✅ Лицо занимает кадр. Погрудный портрет. В полный рост морда слишком мала для чистой деформации.
  • ✅ Глаза, нос, рот и уши чётко видны. Это координаты, которые двигаются.
  • ✅ Одна собака. Сегментация выделяет один объект; две собаки сливаются в одно пятно.
  • ✅ Чёткое и освещённое фото. Размытие и тени делают край вырезки нечётким.
  • ❌ Ничего не должно закрывать морду: очки, лапы, игрушки. Всё, что закрывает якорные точки, деформируется вместе с ними.

Два совета, которые я усвоил на горьком опыте

  1. Начинайте с режима Locked Off. Интуитивно кажется, что движение делает видео живым, но именно движение выдаёт подделку. Если держать кадр неподвижным, зритель воспринимает его как настоящее видео спокойно сидящей собаки, и оценивает только рот. А рот управляется реальным аудио.
  2. Короткие сценарии выигрывают. Два-три ярких предложения. Длинные монологи рассинхронизируются с лицом и быстрее сжигают бесплатный лимит.

Практический вывод: что делать прямо сейчас

Попробуйте сами: зарегистрируйтесь на ElevenLabs и Google AI Studio, получите ключи, откройте BarkReels, вставьте ключи и загрузите фото собаки. За 4 минуты вы получите видео. Оба бесплатных тарифа покрывают расходы, карта не нужна. Ключи хранятся в localStorage и отправляются только провайдеру, потому что моего сервера нет.

Если у вас нет собаки — возьмите фото с Unsplash. Работает с любой собакой.

Изучите код на GitHub: репозиторий. Форкните, включите Pages и разверните. Там есть GitHub Actions для автоматической сборки.

Главный урок: современный браузер способен на многое, если правильно использовать WebGL и WebCodecs. Не бойтесь экспериментировать с клиентской обработкой — это открывает новые возможности для интерактивных приложений.

Если вы сделаете своё видео — поделитесь в комментариях. Мне правда интересно, что ваша собака скрывала.

#искусственный интеллект#WebGL#видео#браузер#API
Al
Редакция Algolit

Пишем про алгоритмы, подготовку к собеседованиям и карьеру в IT — так, чтобы было понятно и полезно.

Хочешь закрепить знания на практике?

Решай задачи на Algolit — интерактивная платформа для обучения

Начать бесплатно →