Привет, Хабр! Меня зовут Никита. Я сделал сервис, который превращает обычное фото в говорящее видео — прямо внутри Telegram. Загружаешь фотку, пишешь текст, выбираешь голос — через пару минут бот присылает видео, где твой аватар произносит этот текст в Full HD.

Расскажу про стек, архитектуру, интеграцию с HeyGen API и боль с платежами по 54-ФЗ.

Зачем это нужно и почему Telegram

HeyGen и Synthesia делают крутые AI-видео с аватарами, но у них сложные интерфейсы, англоязычная аудитория и цены в долларах. Оплатить из России — отдельный квест.

Я подумал: а что если завернуть это в Telegram Mini App? Без регистрации (Telegram сам передаёт данные пользователя), без скачивания отдельного приложения, с оплатой российской картой. 900 миллионов пользователей, push-уведомления через бота из коробки — платформа идеальная для такого продукта.

Так появился AvatarBox (@AvatarBox_bot).

Стек

Frontend:  React 19 + TypeScript + Vite + Tailwind CSS
Backend:   Django + DRF + Celery + Redis
Infra:     Docker Compose, Nginx, PostgreSQL
AI:        HeyGen API
Payments:  T-Bank Acquiring

Выбор стека скучный и прагматичный. React — потому что Telegram Mini App SDK хорошо с ним работает. Django — потому что я на нём быстрее всего пишу. Celery — потому что генерация видео асинхронная и нужно поллить статус. Redis — как брокер для Celery и для кеша.

Авторизация — нулевой порог входа

Telegram Mini App передаёт initData — подписанную строку с данными пользователя. На бэкенде я валидирую HMAC-подпись ключом бота и создаю аккаунт автоматически. Никаких форм регистрации, никаких email-подтверждений.

Пока грузится авторизация, показываю splash screen с анимированным прогресс-баром. Он исчезает только когда выполнены оба условия: авторизация прошла И прошло минимум 3 секунды. Без второго условия экран мелькает на быстром соединении — выглядит как баг.

Генерация видео через HeyGen API

Основной пайплайн:

  1. Пользователь выбирает фото, пишет текст, выбирает голос и формат (9:16, 1:1, 16:9)

  2. Фронтенд отправляет параметры на Django-бэкенд

  3. Бэкенд проксирует запрос в HeyGen API

  4. HeyGen ставит задачу в очередь — генерация занимает 1-3 минуты

  5. Celery-таска поллит статус каждые 10 секунд

  6. Когда видео готово — бот шлёт уведомление в Telegram

HeyGen API — чёрный ящик. Ты отправляешь фото + текст + голос, получаешь URL готового видео. Внутри, насколько я понимаю, lip sync модель, которая анимирует лицо на фотографии в соответствии со звуком. Качество на уровне — артефактов мало, губы синхронизированы нормально.

Голосов больше 2000 — русский, английский и ещё 300+ языков. Выбор голоса через API, есть параметры эмоциональности и выразительности.

Боль с оплатой: 54-ФЗ, T-Bank и почему не Telegram Stars

Первый порыв — использовать Telegram Stars (встроенная валюта Telegram). Быстро, просто, API есть. Но комиссия — 30%. При себестоимости генерации $1 за минуту видео (по ценам HeyGen) — маржа не выживает.

Подключил T-Bank Acquiring. Работает, но есть нюанс: 54-ФЗ требует передачу кассового чека в каждом платеже. Нужно формировать объект Receipt с полным описанием товара, налогообложения и способа оплаты:

'Receipt': {
    'Email': buyer_email,
    'Taxation': 'usn_income',
    'Items': [{
        'Name': 'AvatarBox Studio — тариф «Про»',
        'Price': amount,
        'Quantity': 1.00,
        'Amount': amount,
        'PaymentMethod': 'full_payment',
        'PaymentObject': 'service',
        'Tax': 'none',
    }],
}

Если забыть Receipt или указать неправильный PaymentObject — T-Bank отклоняет платёж без внятного сообщения об ошибке. Я потратил полдня на дебаг, пока не нашёл в документации мелким шрифтом, что PaymentObject обязателен для УСН.

После успешной оплаты T-Bank шлёт webhook на бэкенд — обновляю подписку и отправляю уведомление пользователю через бота.

Пара мелочей, которые заняли непропорционально много времени

Анимированная рамка на главной. Conic-gradient с CSS @property — чтобы цвета плавно вращались по контуру элемента. Выглядит эффектно, но @property до сих пор поддерживается не везде, и на некоторых Android-клиентах Telegram анимация дёргается:

@property --glow-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.glow-border::before {
  background: conic-gradient(
    from var(--glow-angle), 
    #7C3AED, #F97316, #2DD4BF, #7C3AED
  );
  animation: glowSpin 8s linear infinite;
}

Отмена подписки с grace period. При отмене не отключаю доступ сразу — ставлю флаг is_cancelled, и пользователь пользуется сервисом до конца оплаченного периода. Банально, но количество жалоб в поддержку упало в разы после внедрения.

Поле is_cancelled добавлял через raw SQL (ALTER TABLE), потому что менять Django-модель в Docker-образе, который уже в проде — это отдельная история, в которую я решил не лезть.

Что бы сделал иначе

WebSocket вместо поллинга. Celery поллит HeyGen каждые 10 секунд — это 6-18 лишних запросов на каждую генерацию. WebSocket-нотификация от HeyGen была бы чище. Но HeyGen не поддерживает WS, только webhook — и я мог бы переключиться на webhook вместо поллинга. Руки дойдут.

Кеш голосов. Каждый раз при открытии формы фронтенд запрашивает список голосов у бэкенда, тот — у HeyGen API. 2000+ голосов, ответ ~200КБ. Надо закешировать в Redis с TTL в сутки — список голосов не меняется каждые пять минут.

Rate limiting. Сейчас его нет. Теоретически кто-то может заспамить API и сжечь мой баланс на HeyGen. Пока пользователей немного — не критично, но нужно добавить до первого инцидента.

Результаты

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

Telegram Mini App — реально удобная платформа для подобных продуктов. Авторизация из коробки, push через бота, оплата российской картой. Если вы думаете, куда завернуть свой MVP — рекомендую попробовать.

Попробовать: @AvatarBox_bot


Кто делал Telegram Mini App — с какими граблями столкнулись? И интересно послушать, кто интегрировал российские платёжки в боты — насколько больно было с 54-ФЗ?