Files
local-transcriber/docs/PRD.md
T
ddadminandClaude Opus 4.6 18115ec7fd docs: добавлен ADR-001 (CUDA bootstrap), обновлены PRD и plan
- Зачем:
  - зафиксировать архитектурное решение по GPU runtime и rejected alternatives,
    чтобы не переизобретать отклонённые подходы в будущем.
- Что:
  - создан docs/adr/001-cuda-bootstrap.md (контекст, решение, tradeoffs, альтернативы).
  - PRD 4.2: исправлено описание CUDA-зависимостей (cuDNN не нужен, cuBLAS из pip).
  - plan.md: добавлен выполненный шаг 5.1 со ссылкой на ADR.
  - удалены docs/plan-gpu-runtime.md и отчёты ревью (review-stages-*).
- Проверка:
  - cat docs/adr/001-cuda-bootstrap.md.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 18:53:41 +03:00

202 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PRD: local-transcriber — Локальный CLI для транскрипции аудио/видео
## 1. Обзор продукта
**Название**: `local-transcriber`
**Тип**: CLI-утилита (Python, управление зависимостями через uv)
**Назначение**: Принимает аудио- или видеофайл, выполняет распознавание речи локально (без внешних API), и создаёт рядом с исходным файлом markdown-файл с транскриптом и таймкодами.
**Пример использования**:
```bash
transcribe meeting-2026-03-17.mp4
# → создаёт meeting-2026-03-17-transcript.md
```
## 2. Целевые пользователи и сценарии
- Разработчик/инженер, которому нужен текст из записи встречи, лекции, подкаста
- Дальнейшая обработка транскрипта ИИ (суммаризация, извлечение action items и т.д.) — вне скоупа, но учитывается в формате вывода
- Машины с GPU (NVIDIA, CUDA) и без GPU (CPU-only fallback)
- Windows (native / WSL2) и Linux
## 3. Функциональные требования
### 3.1. Основной flow
1. Пользователь вызывает CLI, передаёт путь к файлу (или glob-маску, post-MVP)
2. Проверка: ffmpeg доступен в PATH
3. Файл передаётся в faster-whisper (он сам обрабатывает и аудио, и видео через libav/ffmpeg — отдельное извлечение аудиодорожки не нужно)
4. Результат форматируется в markdown с таймкодами
5. Файл `<имя>-transcript.md` сохраняется рядом с исходным (кодировка: UTF-8)
**Поведение при перезаписи**:
- Явный вызов по файлу → транскрипт перезаписывается, даже если уже существует
- Батч-режим (glob-маска, post-MVP) → пропускать файлы, для которых транскрипт уже существует; `--force` для принудительной перезаписи
**Пустая речь**: если модель не распознала ни одного сегмента — файл транскрипта всё равно создаётся (шапка с метаданными + `*Речь не обнаружена.*` в теле), выводится предупреждение в stderr: `⚠ Речь не обнаружена в файле <имя>`
### 3.2. CLI-интерфейс
```
transcribe <путь_к_файлу> [опции]
Опции:
--model, -m Модель Whisper (tiny|base|small|medium|large-v3)
По умолчанию: large-v3
--language, -l Язык (ru|en|auto)
По умолчанию: auto (автодетект)
--output, -o Путь к выходному файлу
По умолчанию: <input_stem>-transcript.md
--device, -d Устройство (auto|cpu|cuda)
По умолчанию: auto (CUDA если доступен, иначе CPU)
--compute-type Тип вычислений (float16|int8|int8_float16|float32)
По умолчанию: int8 (универсален для GPU 4-8 GB и CPU)
--verbose, -v Подробный вывод (прогресс сегментов)
```
### 3.3. Формат выходного файла
Файл `*-transcript.md`:
```markdown
# Транскрипт: meeting-2026-03-17.mp4
- **Дата транскрипции**: 2026-03-17 14:30:05
- **Модель**: large-v3
- **Язык**: ru (detected) / ru (forced)
- **Длительность**: 01:23:45
- **Устройство**: CUDA (NVIDIA GeForce RTX 3060)
---
[00:00.00 - 00:04.82] Добрый день, коллеги. Сегодня мы обсудим результаты квартала.
[00:04.82 - 00:09.15] Первый вопрос — по метрикам продукта.
[00:09.15 - 00:15.40] Как вы видите на слайде, MAU вырос на двадцать три процента
по сравнению с предыдущим кварталом.
...
```
**Правила форматирования**:
- Таймкоды в формате `[MM:SS.ss - MM:SS.ss]` (минуты:секунды.сотые)
- Для записей длиннее 1 часа — `[HH:MM:SS.ss - HH:MM:SS.ss]`
- Каждый сегмент — отдельный абзац
- Метаданные в шапке файла
- Пустая строка между сегментами для читаемости
### 3.4. Поддерживаемые форматы
**Аудио**: mp3, wav, flac, ogg, m4a, wma, aac
**Видео**: mp4, mkv, avi, mov, webm, ts
Определение типа — по расширению. Фактическое декодирование выполняет ffmpeg внутри faster-whisper; если формат не поддерживается, ошибка будет от ffmpeg.
## 4. Нефункциональные требования
### 4.1. Производительность
| Конфигурация | Ожидаемая скорость (real-time factor) |
|---------------------------|---------------------------------------|
| RTX 3060 + large-v3 | ~10-15x (1 час аудио ≈ 4-6 мин) |
| RTX 4050 + large-v3 | ~12-18x (1 час аудио ≈ 3-5 мин) |
| Quadro M3000M + large-v3 | ~3-5x (1 час аудио ≈ 12-20 мин) |
| CPU (modern) + large-v3 | ~0.5-1x (1 час аудио ≈ 60-120 мин) |
| CPU + small | ~3-5x (1 час аудио ≈ 12-20 мин) |
### 4.1.1. Совместимость GPU
| GPU | VRAM | large-v3 int8 (~2.5 GB) | large-v3 float16 (~4.5 GB) | Рекомендация |
|-------------------|-------|--------------------------|----------------------------|-------------------------|
| RTX 3060 | 6 GB | ✅ | ✅ (впритык) | int8 — безопасный выбор |
| RTX 4050 | 6 GB | ✅ | ✅ (впритык) | int8 — безопасный выбор |
| Quadro M3000M | 4 GB | ✅ | ⚠️ может OOM | int8 обязательно |
| Без GPU | — | CPU int8 | — | int8 на CPU |
Дефолт `int8` выбран как универсальный: работает на всех GPU от 4 GB и на CPU, при минимальной потере качества относительно float16.
### 4.2. Требования к окружению
- Python ≥ 3.10
- ffmpeg в PATH (используется faster-whisper внутри для декодирования любых медиаформатов)
- Для GPU: Linux/WSL2 — cuBLAS из nvidia-cublas-cu12 (ставится автоматически через `uv sync`); Windows — системный CUDA toolkit (см. ADR-001)
- Дисковое пространство для моделей: ~3 GB (large-v3)
- Выходные файлы: UTF-8 (явная кодировка при записи)
### 4.3. Кроссплатформенность
- Linux: нативный запуск
- Windows: нативный Python или WSL2
- macOS: не приоритет, но faster-whisper поддерживает CPU-режим
## 5. Технический стек
| Компонент | Технология |
|---------------------|-------------------------------------------------|
| Язык | Python 3.10+ |
| Управление проектом | uv (pyproject.toml) |
| Распознавание речи | faster-whisper (CTranslate2 backend) |
| Медиа-декодирование | ffmpeg (системная зависимость, используется faster-whisper внутри) |
| CLI-фреймворк | typer |
| Прогресс | rich (progress bar + статус) |
### 5.1. Почему faster-whisper
- В 4× быстрее оригинального OpenAI Whisper при том же качестве
- Меньше потребление VRAM (large-v3 влезает в 6 GB с float16/int8)
- Нативный Python API, без Docker
- Поддержка CPU fallback из коробки
- Активное сообщество, регулярные обновления
- Автоматическая загрузка моделей из Hugging Face Hub
### 5.2. Структура проекта
```
local-transcriber/
├── pyproject.toml
├── README.md
├── src/
│ └── local_transcriber/
│ ├── __init__.py
│ ├── cli.py # CLI entry point (typer)
│ ├── transcriber.py # Обёртка над faster-whisper
│ ├── formatter.py # Форматирование в markdown
│ └── utils.py # Проверки (ffmpeg), определение device и т.д.
└── tests/
└── ...
```
## 6. Риски и ограничения
| Риск | Влияние | Митигация |
|------|---------|-----------|
| Качество распознавания русского текста | Среднее | large-v3 хорошо справляется с ru; при проблемах — попробовать `--language ru` вместо auto |
| Нет разделения по спикерам | Низкое | Осознанно выведено за скоуп MVP; добавление diarization (pyannote.audio) — возможное расширение |
| ffmpeg отсутствует в системе | Высокое | Проверка при старте + понятное сообщение об ошибке с инструкцией по установке |
| Первый запуск: долгая загрузка модели | Низкое | Прогресс-бар при скачивании; модели кешируются в `~/.cache/huggingface/` |
| CUDA несовместимость на Windows | Среднее | Автоматический fallback на CPU + предупреждение; в README — инструкция по CUDA |
| Большие файлы (>2 часов) | Низкое | faster-whisper работает потоково, не грузит всё в память |
| OOM на GPU с 4 GB VRAM | Среднее | Дефолт int8 (~2.5 GB); при OOM — fallback на CPU с предупреждением |
| Файл без речи (тишина, музыка, шум) | Низкое | Создаётся транскрипт с шапкой метаданных и `*Речь не обнаружена.*` в теле + предупреждение в stderr |
## 7. Вне скоупа MVP
- Разделение по спикерам (speaker diarization)
- Веб-интерфейс / GUI
- Пакетная обработка нескольких файлов (батч) — см. post-MVP
- Стриминг с микрофона (real-time)
- Интеграция с LLM для пост-обработки транскрипта
- Перевод (translation mode)
- Вывод в форматах SRT / VTT / JSON
- Аудиофильтрация / шумоподавление (faster-whisper сам нормализует; ручной препроцессинг может ухудшить результат)
## 8. Возможные расширения (post-MVP)
1. **Speaker diarization** — pyannote.audio, требует отдельной модели + GPU
2. **Батч-режим**`transcribe ./recordings/*.mp4`; по умолчанию пропускает файлы, для которых транскрипт уже есть; `--force` для перезаписи
3. **Экспорт в SRT/VTT** — для субтитров
4. **Watch-режим** — мониторинг директории, автотранскрипция новых файлов
5. **Интеграция с LLM**`--summarize` для генерации саммари поверх транскрипта
6. **Конфигурационный файл**`.transcriber.toml` для дефолтов проекта