111 lines
5.0 KiB
Markdown
111 lines
5.0 KiB
Markdown
# ТЗ: Караоке-генератор — MVP (v0.1)
|
||
|
||
## Цель
|
||
Реализовать CLI-инструмент, который принимает аудиофайл песни и генерирует видео-файл с синхронизированным текстом (стиль "субтитры/караоке").
|
||
|
||
---
|
||
|
||
## Стек
|
||
- **Python 3.10+**
|
||
- **Whisper** (openai-whisper или faster-whisper) — транскрипция + тайминги
|
||
- **FFmpeg** — рендер финального видео
|
||
- **MoviePy** или **ffmpeg-python** — наложение текста на видео
|
||
- **Pillow** — рендер текстовых кадров (если MoviePy не справляется)
|
||
- **Pexels API** — поиск стоковых видео-фонов
|
||
- **GigaChat API** (через прокси `185.130.212.192:8443`) — NLP-анализ смысла текста
|
||
|
||
---
|
||
|
||
## Функционал MVP (v0.1)
|
||
|
||
### Вход
|
||
```
|
||
python karaoke.py --audio song.mp3 [--text lyrics.txt] [--output output.mp4]
|
||
```
|
||
- `--audio` — обязательный аргумент, путь к аудиофайлу (mp3, wav, ogg, m4a)
|
||
- `--text` — опционально, путь к файлу с текстом (txt, lrc, srt)
|
||
- `--output` — опционально, путь к выходному файлу (по умолчанию `output.mp4`)
|
||
|
||
### Шаг 1: Транскрипция
|
||
- Если `--text` не передан → запустить Whisper на аудио
|
||
- Whisper возвращает сегменты с таймингами `[{start, end, text}]`
|
||
- Если `--text` передан:
|
||
- `.lrc` / `.srt` → парсить тайминги напрямую
|
||
- `.txt` → выровнять текст по аудио через Whisper (forced alignment)
|
||
|
||
### Шаг 2: NLP-анализ (для фона)
|
||
- Отправить полный текст в GigaChat
|
||
- Промпт: "Определи настроение и 3-5 ключевых визуальных сцен для этой песни. Ответь JSON: {mood: str, scenes: [str]}"
|
||
- Пример ответа: `{"mood": "romantic", "scenes": ["sunset beach", "city lights", "rain"]}`
|
||
|
||
### Шаг 3: Подбор видео-фона
|
||
- Взять первую сцену из `scenes`
|
||
- Запрос к Pexels API: `GET /videos/search?query={scene}&per_page=3`
|
||
- Скачать первый подходящий клип (HD, landscape)
|
||
- Зациклить клип до длины аудио (loop)
|
||
- Если Pexels не вернул результат → использовать чёрный фон
|
||
|
||
### Шаг 4: Рендер видео
|
||
- Разрешение: 1280x720
|
||
- Фреймрейт: 30fps
|
||
- Фон: видео-клип (зациклен)
|
||
- Текст: текущая строка по центру внизу экрана
|
||
- Шрифт: белый, размер 48px, с чёрной тенью
|
||
- Подсветка активной строки: жёлтый цвет
|
||
- Fade-in/out: 0.3 сек
|
||
- Аудио: оригинальный файл встроен в видео
|
||
- Формат выхода: mp4 (H.264 + AAC)
|
||
|
||
---
|
||
|
||
## Структура проекта
|
||
```
|
||
tasks/karaoke/
|
||
├── PROJECT.md
|
||
├── karaoke.py # точка входа
|
||
├── transcribe.py # Whisper транскрипция
|
||
├── nlp.py # GigaChat NLP-анализ
|
||
├── video_bg.py # Pexels API + скачивание фона
|
||
├── render.py # FFmpeg/MoviePy рендер
|
||
├── requirements.txt
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## Конфигурация / секреты
|
||
Читать из переменных окружения (или из `~/.openclaw/.env`):
|
||
- `PEXELS_API_KEY` — ключ Pexels API (нужно получить на pexels.com/api)
|
||
- `GIGACHAT_BASE_URL` — `https://185.130.212.192:8443` (прокси)
|
||
- `OPENAI_API_KEY` — если используется OpenAI Whisper API (опционально, можно local)
|
||
|
||
---
|
||
|
||
## Ограничения MVP
|
||
- Только один видео-фон на всю песню (не меняется по сценам)
|
||
- Нет UI — только CLI
|
||
- Нет предпросмотра
|
||
- Рендер может занять 1-5 мин для песни 3-5 мин
|
||
|
||
---
|
||
|
||
## Критерии готовности
|
||
- [ ] `python karaoke.py --audio test.mp3` → генерирует `output.mp4`
|
||
- [ ] Текст синхронизирован с аудио (±0.5 сек)
|
||
- [ ] Видео-фон подобран автоматически (или чёрный если API недоступен)
|
||
- [ ] Файл воспроизводится в VLC/браузере без ошибок
|
||
- [ ] `requirements.txt` заполнен, `README.md` с инструкцией запуска
|
||
|
||
---
|
||
|
||
## Что НЕ нужно в MVP
|
||
- UI/веб-интерфейс
|
||
- Смена фона по сценам
|
||
- Дуэт (два текста)
|
||
- Экспорт SRT/LRC
|
||
- Ручная коррекция таймингов
|
||
|
||
---
|
||
|
||
_Создано: 2026-04-29 | Проект: proj_karaoke_
|