Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
31 KiB
Дорожная карта видеофич — Техническая консультация v1
Дата: 22 марта 2026 Консультанты: ML/AI-инженер, Backend-архитектор, Remotion-инженер, Frontend-архитектор, DevOps-инженер, Инженер по производительности
Общая картина
Четыре фичи. От простого к безумному. Вот что получается, если разложить всё по полочкам:
| # | Фича | Сложность | MVP | Полная версия | Доп. инфраструктура |
|---|---|---|---|---|---|
| 1 | Продвинутые шаблоны Remotion | Легко-средне | 3-4 дня | 3-4 дня | Ничего — можно начинать хоть сейчас |
| 2 | Детекция вирусных моментов | Средне | 5-7 дней | 8-12 дней | Только API-ключ для LLM |
| 3 | Авто-монтаж и трекинг лица | Очень сложно | 12-15 дней | 30-45 дней | Фаза 1: ничего; Фаза 2: GPU-воркер |
| 4 | Конвертация в вертикальные Shorts (9:16) | Средне | 6-8 дней | +3-4 дня после #3 | Ничего |
| Итого | 26-34 дня | 44-65 дней |
Реалистичный прогноз для одного разработчика: 6-8 недель (все MVP) или 3-4 месяца (полные версии).
Фича 1: Продвинутые шаблоны Remotion
Статус: Спецификация и план реализации уже написаны. Бери и делай.
- Спецификация:
docs/superpowers/specs/2026-03-21-advanced-remotion-templates-design.md - План:
docs/superpowers/plans/2026-03-21-advanced-remotion-templates.md
Что делаем: Расширяем CaptionStyleSchema четырьмя новыми стилями подсветки слов (pop_in, karaoke, bounce, glow_pulse), двумя переходами (zoom_in, drop_in), тремя полями (word_entrance, highlight_rotation_deg, text_transform). Добавляем два системных пресета: "Shorts" и "Podcast".
Где трогаем код: Расширение схемы в Remotion + бэкенде, логика рендеринга в Captions.tsx, Alembic-миграция для пресетов, контролы в StyleEditor на фронте.
Особый интерес специалистов не требуется — всё спроектировано, новой инфраструктуры нет. Самая безрисковая фича в этом списке.
Фича 2: Детекция вирусных моментов
Вот тут начинается самое интересное. За $0.005 за видео мы можем автоматически находить самые цепляющие фрагменты в подкастах и интервью. Пять копеек — и AI выкладывает тебе на блюдце моменты, которые зрители пересылают друг другу.
Архитектура
LLM API: Gemini 2.5 Flash — лучшая поддержка русского языка, $0.15/$0.60 за 1М токенов. Альтернатива: GPT-4o-mini (те же деньги, русский чуть хуже). Стоимость анализа одного 30-минутного видео: примерно $0.005.
Аудио-подкрепление: librosa для кривых RMS-энергии — уточняет границы клипов до естественных пауз, повышает скор для энергичных сегментов. Зависимость ~20МБ, обработка 30-минутного аудио за <10 секунд.
Пайплайн:
- Берём транскрипцию из БД
- librosa считает огибающую энергии по всему аудио (разрешение 100мс)
- LLM анализирует текст транскрипции через промпт со structured JSON output
- Постобработка: привязка границ клипов к точкам низкой энергии, расчёт energy-скоров
- Сохраняем клипы в новую таблицу
clips
Бэкенд
Новый модуль: clips (models, schemas, repository, service, router) — хранит найденные клипы со связями project/file/job.
Модель клипа:
Clip {
project_id: UUID (FK projects)
source_file_id: UUID (FK files)
job_id: UUID? (FK jobs)
title: str
start_ms: int
end_ms: int
score: float
source_type: "viral_detected" | "user_created" | "auto_generated"
status: "pending" | "approved" | "rejected" | "exported"
meta: JSON? (рассуждения LLM, теги, хэштеги)
}
Новый тип джоба: VIRAL_DETECT в JobTypeEnum. Актор вызывает LLM API напрямую через httpx из Dramatiq-воркера — отдельный сервис не нужен.
Интеграция с LLM:
- Прямой HTTP-вызов из актора с retry + exponential backoff на 429
- Промпты хранятся в
cpv3/infrastructure/prompts/viral_detection_v1.txt - Активная версия контролируется через env-переменную
LLM_VIRAL_PROMPT_VERSION - Новые настройки:
LLM_API_URL,LLM_API_KEY,LLM_MODEL_NAME
Фронтенд
- Новый
ViralClipsStepв визарде проекта (features/project/) - Список клипов с превьюшками, скорами, заголовками, кнопками принять/отклонить
- Модалка редактирования клипа с видео-превью (воспроизведение ограничено диапазоном start/end)
- Новый тип джоба
VIRAL_DETECTв обработке нотификаций (через существующую WebSocket-инфраструктуру)
Ключевые цифры
| Метрика | Значение |
|---|---|
| Точность (precision) | 50-70% |
| Полнота (recall) | 60-80% |
| Время обработки | 10-20 секунд |
| Стоимость за видео | ~$0.005 |
| Стоимость при 1 000 видео/месяц | ~$5 |
| Новые зависимости | google-generativeai или openai (~10МБ) + librosa (~20МБ) |
10-20 секунд и пять долларов за тысячу видео. Вдумайтесь в эти цифры.
Риски
- Качество промпт-инжиниринга определяет ценность фичи — придётся итерировать по фидбеку пользователей
- Визуальные моменты (мимика, физическая комедия) из текста не ловятся — ~20-30% вирусных моментов проходят мимо
- Качество транскрипции критично — Whisper
tinyдаёт ~25% WER на русском; для входных данных вирусной детекции использовать минимумsmall - LLM галлюцинирует таймстемпы — обязательно валидировать возвращённые метки времени против реальных границ сегментов
MVP vs Полная версия
- MVP: Только текстовый анализ через LLM, без аудио-энергии. Возвращает клипы со скорами. Пользователь ревьюит и принимает/отклоняет.
- Полная: Добавляем librosa-анализ энергии, few-shot примеры из принятых пользователем клипов, пакетную обработку, прямой экспорт клипов в 9:16.
Фича 3: Авто-монтаж и трекинг лица
Самая амбициозная фича. Самая сложная. И, возможно, самая впечатляющая для пользователей. Представьте: загружаете подкаст с двумя спикерами, а на выходе получаете динамичное вертикальное видео, где камера сама «следит» за говорящим — как будто это снимал живой оператор.
Архитектура
Детекция лиц: MediaPipe BlazeFace (Apache 2.0, модель ~2МБ, 30-60 FPS на CPU). Сэмплируем на 3 FPS — позиции лиц не меняются значительно за 330мс. Зависимость: mediapipe (~30МБ).
Диаризация спикеров: pyannote.audio 3.1 (MIT, ~10% DER, self-hosted). На CPU работает со скоростью 0.17-0.33x реального времени (5-10 минут на 30-минутное аудио). GPU ускоряет до 1-2 минут. Зависимости: pyannote-audio (~200МБ) + torchaudio (~50-80МБ). PyTorch уже установлен через Whisper.
Маппинг лицо-спикер:
- Фаза 1: Эвристика по временнОй корреляции — сопоставляем треки лиц с сегментами спикеров по максимальному пересечению во времени. 70-85% точности для видео с двумя спикерами. Ноль дополнительных зависимостей. Около 100 строк Python.
- Фаза 2: TalkNet-ASD (Active Speaker Detection) — совместный анализ движения губ и аудио для определения, кто говорит. 92.3% точности. Требует
torchvision+ веса модели (~50МБ). Нужен GPU (2-5 FPS на CPU vs 15-25 FPS на GPU).
Видео-композитинг (подход Remotion):
Динамический кроп через CSS transform: scale() translate() на элементе <Video> внутри контейнера с overflow: hidden. Это GPU-ускоренная браузерная операция — по сути бесплатная с точки зрения производительности. Для самого кропа пере-кодирование через FFmpeg не нужно.
Новые Remotion-композиции:
| Композиция | Назначение | Фаза |
|---|---|---|
CaptionedVideo (существует) |
Наложение субтитров на нативное видео | Текущая |
ShortsVideo (новая) |
Статический/ключевой кроп + субтитры в 9:16 | Фича 4 |
AutoEditVideo (новая) |
Кроп с трекингом лица + монтаж + субтитры | Фича 3 (полная) |
Все композиции разделяют компонент <Captions> и хук useCaptions.
Формат данных кропа (ключевые кадры):
type FaceKeyframe = {
time: number; // секунды
x: number; // центр лица, 0.0-1.0 нормализовано
y: number; // центр лица, 0.0-1.0 нормализовано
width: number; // ширина bounding box, 0.0-1.0
height: number; // высота bounding box, 0.0-1.0
speakerId?: string;
};
type CropTrack = {
keyframes: FaceKeyframe[];
interpolation: "linear" | "ease" | "smooth";
zoom: number; // базовый множитель зума
safeMargin: number; // отступ вокруг лица (0.1 = 10%)
};
Remotion interpolate() между ключевыми кадрами для плавного панорамирования/зума. spring() используется только для жёстких переключений между спикерами.
Бэкенд
Новые типы джобов: FACE_DETECT, SPEAKER_DIARIZE в JobTypeEnum. Результаты хранятся в Job.output_data (JSON) — новая таблица для данных лица/диаризации не нужна.
Отделение ML-сервиса:
- Фаза 1: Оставляем в Dramatiq-воркерах (тот же образ). MediaPipe + pyannote добавляют только ~280МБ к образу.
- Фаза 2: Отдельный Docker-контейнер
ml-workerна выделенных очередях Dramatiq (ml_head_tracking,ml_diarization). Тот же код, другой образ, другие лимиты ресурсов.
Изменения в Remotion-сервисе: POST /api/render нужен параметр compositionId для выбора композиции. Props расширяются полями crop, outputWidth, outputHeight.
Время обработки (30-минутное 1080p видео)
| Шаг | CPU | GPU |
|---|---|---|
| Извлечение аудио (FFmpeg) | 10-20 сек | 10-20 сек |
| Детекция лиц (MediaPipe, 3 FPS) | 1-2 мин | 10-15 сек |
| Диаризация спикеров (pyannote) | 15-30 мин | 1-2 мин |
| Маппинг лицо-спикер | < 1 сек | < 1 сек |
| Рендер Remotion (кроп + субтитры) | 10-30 мин | 10-30 мин |
| Итого (с параллелизацией) | 35-80 мин | 16-40 мин |
Детекция лиц и диаризация могут работать параллельно — у них разные входные данные (видеокадры vs аудиодорожка).
Требования к памяти
| Конфигурация | Пиковое потребление RAM |
|---|---|
| Whisper base + pyannote (параллельно) | 8-12 ГБ |
| Whisper medium + pyannote (параллельно) | 12-16 ГБ |
| Рекомендуемый лимит ML-воркера | 16 ГБ, --threads 1 |
Фронтенд
- Превью трекинга лица: видеоплеер с наложением bounding box через canvas
- Трек спикеров в TimelinePanel (расширяет существующую систему из 4 треков)
- Контролы: слайдер уровня зума, скорость перехода, выбор спикера
- Переключатель сравнения «до/после»
- UX-флоу: загрузка подкаста -> запуск анализа (ProcessingStep) -> ревью назначений спикеров -> корректировка -> экспорт
Ключевые цифры
| Метрика | Значение |
|---|---|
| Точность детекции лиц | ~90% (MediaPipe на talking-head контенте) |
| DER диаризации | ~10% (pyannote 3.1) |
| Точность маппинга лицо-спикер (Фаза 1) | 70-85% |
| Точность маппинга лицо-спикер (Фаза 2, TalkNet) | ~92% |
| Новые зависимости | ~280МБ (mediapipe + pyannote + torchaudio) |
| GPU обязателен? | Нет для Фазы 1; рекомендуется для Фазы 2 |
Риски
- Маппинг лицо-спикер — главная нерешённая подзадача. Точность 70-85% означает, что каждое пятое назначение может быть неверным. Пользователь должен иметь возможность поправить вручную.
- Диаризация на CPU — бутылочное горлышко. 15-30 минут на 30-минутное видео. GPU сокращает до 1-2 минут.
- Конфликты версий PyTorch между Whisper и pyannote — обязательно тестировать
uv syncперед коммитом. - Потеря качества видео при кропе 16:9 -> 9:16 — остаётся только ~31.6% ширины кадра. Исходник должен быть минимум 1080p.
- Скачивание моделей при первом запуске — модели pyannote (~100МБ) требуют принятия лицензии на Hugging Face. Обрабатывать в Dockerfile, не в рантайме.
MVP vs Полная версия
- MVP (12-15 дней): Детекция лиц на сэмплированных кадрах. Пользователь вручную выбирает, за каким лицом следить. Статический кроп на выбранное лицо. Без переключения спикеров, без диаризации. Работает для одного спикера.
- Полная (30-45 дней): Диаризация + маппинг лицо-спикер. Динамический кроп, следующий за активным спикером. Плавные spring()-переходы при смене спикеров. Сплит-скрин для реакций. Поддержка нескольких спикеров.
Фича 4: Конвертация в вертикальные Shorts (9:16)
Архитектура
Пайплайн: Сначала кроп, потом субтитры — всегда. Один проход рендеринга в Remotion через новую композицию ShortsVideo. Композиция рендерит в целевых размерах 9:16, применяет CSS-кроп к <Video> и накладывает субтитры поверх.
Позиционирование субтитров: Новые поля в схеме не нужны. Бэкенд корректирует font_size, padding_px, max_width_pct в styleConfig под соотношение 9:16. Remotion — это «глупый рендерер»: логика о том, что выглядит хорошо в 9:16, живёт в пресетах.
Спецификация кропа:
type CropConfig = {
mode: "static" | "keyframe";
staticCrop?: { x: number; y: number; zoom: number }; // 0-1 нормализовано
keyframes?: Array<{ time: number; x: number; y: number; zoom: number }>;
interpolation?: "linear" | "ease" | "smooth";
};
Статический кроп — вырожденный случай ключевого кропа (один ключевой кадр).
Бэкенд
Новый тип джоба: ASPECT_CONVERT в JobTypeEnum. Новая функция crop_to_vertical() в media/service.py через FFmpeg crop+scale фильтр.
Новый тип артефакта: VERTICAL_VIDEO в ArtifactTypeEnum.
Пайплайн:
- Обрезка исходного видео до временного диапазона клипа (если из вирусной детекции)
- Применение кропа (статический центральный кроп или face-tracking кроп из Фичи 3)
- Загрузка в S3 по пути
{folder}/vertical/{filename} - Webhook + нотификация
Фронтенд
- Превью кропа: перетаскиваемый прямоугольник 9:16 поверх видеоплеера (CSS
object-fit: cover+object-position) - Переключатель side-by-side превью: оригинал 16:9 vs обрезанное 9:16
- Интеграция с Фичей 2: кнопка «Конвертировать в Short» на каждом одобренном вирусном клипе
- Интеграция с Фичей 3: автозаполнение региона кропа из данных детекции лица
Время обработки
| Подход | Время (30-мин видео) |
|---|---|
| FFmpeg кроп (без субтитров) | 12-36 мин |
| Remotion кроп + субтитры (один проход) | 11-45 мин |
| FFmpeg с NVENC (аппаратное кодирование) | 3-5 мин |
MVP vs Полная версия
- MVP (6-8 дней): Ручной выбор региона кропа с превью. Пользователь перетаскивает прямоугольник 9:16 поверх видео. Новая
ShortsVideoRemotion-композиция рендерит кроп + субтитры. - Полная (+3-4 дня после Фичи 3): Авто-кроп на основе данных детекции лица. Конвертация в один клик. Пакетная конвертация вирусных клипов.
Рекомендуемый порядок разработки
Неделя 1-2: Фича 1 (Шаблоны) ████████
Неделя 2-4: Фича 2 (Вирусная детекция) ████████████████
Неделя 4-6: Фича 4 MVP (9:16 кроп) ████████████████
Неделя 6-14: Фича 3 (Трекинг лица) ████████████████████████████████████████
Неделя 14-15: Фича 4 (апгрейд) ████████
Почему именно так:
- Шаблоны первыми — готовы к реализации, нулевой риск, моментальная польза для пользователей
- Вирусная детекция второй — лучшее соотношение пользы к трудозатратам ($0.005/видео, 5-7 дней MVP), валидирует гипотезу о том, что пользователи хотят автоматический монтаж
- 9:16 MVP третьим — создаёт композицию
ShortsVideo, которую потом расширит Фича 3; полезна сама по себе с ручным кропом - Трекинг лица последним — самая сложная, самые большие вложения; к этому моменту Фичи 2 и 4 уже валидируют спрос
- Апгрейд 9:16 — тривиален, когда трекинг лица уже даёт позиции
Анализ стоимости
Стоимость обработки одного видео
| Уровень | Состав | Вычисления | LLM API | Итого | Время ожидания |
|---|---|---|---|---|---|
| Только CPU | Всё на CPU | $0.05 | $0.06 | $0.11 | 35-80 мин |
| GPU (T4) | ML на GPU, FFmpeg на CPU | $0.11 | $0.06 | $0.17 | 16-40 мин |
| GPU + NVENC | Всё на GPU | $0.13 | $0.06 | $0.19 | 10-15 мин |
Одиннадцать центов на CPU. Девятнадцать с GPU. Даже на самом дорогом варианте — меньше двадцати центов за полный пайплайн с AI-анализом, трекингом лица и кодированием видео.
Месячная стоимость инфраструктуры (100 видео/месяц)
| Сценарий | Стоимость |
|---|---|
| Только CPU (текущая инфра) | ~$11 + сервер |
| Modal serverless GPU | ~$21/месяц |
| Spot GPU (g4dn.xlarge) | ~$115/месяц |
| Постоянный GPU (g4dn.xlarge 24/7) | ~$380/месяц |
Рекомендация: Начинаем на CPU. Переходим на Modal serverless GPU, когда время ожидания в очереди превышает 15 минут. При 500+ видео/день — смотрим на spot-инстансы.
Предлагаемые тарифы SaaS
| Тариф | Цена | Ограничения | Себестоимость | Маржа |
|---|---|---|---|---|
| Free | $0 | Видео до 10 мин, низкий приоритет в очереди | ~$0.04/видео | Маркетинг |
| Pro | $15-30/мес | Видео до 30 мин, GPU ML | ~$0.17/видео при 50 видео | 60-80% |
| Business | $50-100/мес | Видео до 60 мин, приоритетная очередь, NVENC | ~$0.38/видео | 70-85% |
Маржинальность 60-85%. При масштабировании — только растёт.
Инфраструктурные решения
Отделение ML-сервиса
Фаза 1: ML остаётся в существующих Dramatiq-воркерах. MediaPipe + pyannote добавляют лишь ~280МБ к образу. PyTorch уже установлен через Whisper.
Фаза 2: Отдельный Docker-контейнер ml-worker на выделенных очередях. Тот же код, другой образ (Dockerfile.ml), другие лимиты ресурсов. Docker Compose profiles:
docker-compose up # По умолчанию: без ML-воркера
docker-compose --profile ml up # С ML-воркером
НЕ строить отдельный HTTP-микросервис. Dramatiq уже обеспечивает очередь джобов, ретраи, прогресс и отмену. Добавление HTTP service discovery, API-контрактов и health check — оверхед с нулевой пользой для асинхронных нагрузок.
Немедленные оптимизации (до начала работы над новыми фичами)
| Действие | Эффект | Трудозатраты |
|---|---|---|
| Переключить PyTorch на CPU-only индекс | -800МБ размер образа | 1 час |
Исправить дефолт REMOTION_SERVICE_URL в воркере |
Баг-фикс | 5 мин |
| Добавить лимиты ресурсов к docker-compose сервисам | Предотвращение каскадных OOM | 30 мин |
| Разбить Dramatiq на пулы очередей (легковесные vs ML vs вычисления) | Предотвращение голодания воркеров | 2-3 часа |
Четыре задачи. Суммарно полдня. Экономия: 800МБ, один баг, и страховка от того, что ML-джоб сожрёт всю память и уронит API.
Сводка по технологическому стеку
Новые зависимости
| Пакет | Размер | Назначение | Фича |
|---|---|---|---|
google-generativeai или openai |
~10 МБ | LLM API клиент | 2 |
librosa |
~20 МБ | Анализ энергии аудио | 2 |
mediapipe |
~30 МБ | Детекция лиц | 3 |
pyannote-audio |
~200 МБ | Диаризация спикеров | 3 |
torchaudio |
~50-80 МБ | Обработка аудио для pyannote | 3 |
| Всего новых зависимостей | ~310-340 МБ |
Новые бэкенд-модули
| Модуль | Назначение | Фича |
|---|---|---|
clips |
CRUD клипов, воркфлоу ревью | 2 |
Новые Remotion-композиции
| Композиция | Назначение | Фича |
|---|---|---|
ShortsVideo |
Статический/ключевой кроп + субтитры в 9:16 | 4 |
AutoEditVideo |
Динамический кроп с трекингом лица + субтитры | 3 |
Новые типы джобов
| Тип джоба | Назначение | Фича |
|---|---|---|
VIRAL_DETECT |
LLM-анализ транскрипции | 2 |
ASPECT_CONVERT |
9:16 кроп + пере-кодирование | 4 |
FACE_DETECT |
Детекция bounding box лиц | 3 |
SPEAKER_DIARIZE |
Диаризация спикеров | 3 |
Сквозные проблемы
Шесть специалистов — шесть взглядов на одну кодовую базу. Вот что они нашли:
| Проблема | Кто нашёл | Приоритет | Действие |
|---|---|---|---|
| PyTorch тащит CUDA-библиотеки на CPU-only инфру (+800МБ) | DevOps | Высокий | Переключить на CPU-only PyTorch индекс |
Воркер с --processes 1 --threads 2 упадёт по OOM на ML-джобах |
Performance | Высокий | Разбить на пулы очередей, --threads 1 для ML |
_get_job_status_sync() течёт соединениями к БД |
Performance | Высокий | Починить до добавления новых акторов |
| Нет очистки временных файлов при OOM-крэше | Performance | Средний | Добавить периодическую очистку /tmp или cron |
tasks/service.py — 1 674 строки, скоро перевалит за 2К |
Backend | Средний | Вынести бойлерплейт акторов в декоратор/контекст-менеджер |
Дефолт REMOTION_SERVICE_URL в воркере неверный (localhost:8001) |
DevOps | Средний | Исправить на http://remotion:3001 в docker-compose |
| Ни на одном Docker-сервисе нет лимитов ресурсов | DevOps | Средний | Добавить memory/CPU лимиты на все сервисы |
| Whisper со временем нужно переместить в ML-сервис | Backend | Низкий | Запланировать при разделении ML-воркера в Фазе 2 |
Проверка isCurrent слова в Captions.tsx хрупкая |
Remotion | Низкий | Сравнивать по индексу, а не по тексту + start time |
Отчёты специалистов
Полные выводы специалистов доступны в стенограмме сессии. Ключевые файлы, которые изучал каждый:
- ML-инженер:
cpv3/modules/transcription/service.py,cpv3/modules/tasks/service.py,pyproject.toml - Backend-архитектор:
cpv3/modules/tasks/service.py,cpv3/modules/jobs/schemas.py,cpv3/modules/media/service.py,cpv3/modules/captions/service.py,docker-compose.yml - Remotion-инженер:
remotion_service/src/components/Composition.tsx,Captions.tsx,Root.tsx,useCaptions.ts,useVideoMeta.ts, все определения типов - Frontend-архитектор:
src/widgets/TimelinePanel/,src/features/project/FragmentsStep/,src/shared/context/WizardContext.tsx,src/shared/store/notifications/ - DevOps-инженер:
docker-compose.yml,Dockerfile,pyproject.toml,uv.lock - Инженер по производительности:
cpv3/modules/tasks/service.py,cpv3/modules/media/service.py,cpv3/modules/transcription/service.py,docker-compose.yml