Привет, Хабр! Меня зовут Никита. Я сделал сервис, который превращает обычное фото в говорящее видео — прямо внутри 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
Основной пайплайн:
Пользователь выбирает фото, пишет текст, выбирает голос и формат (9:16, 1:1, 16:9)
Фронтенд отправляет параметры на Django-бэкенд
Бэкенд проксирует запрос в HeyGen API
HeyGen ставит задачу в очередь — генерация занимает 1-3 минуты
Celery-таска поллит статус каждые 10 секунд
Когда видео готово — бот шлёт уведомление в 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-ФЗ?
