Files
local-transcriber/docs/PRD.md
T
ddadmin e0fcf43533 docs(plan): уточнён план по итогам ревью
- Зачем:
  - устранены пробелы в плане: недостающие тесты, неописанные параметры, архитектурные расхождения.
- Что:
  - detect_device() возвращает только str (device), compute-type независим от него.
  - добавлен get_gpu_name() для человекочитаемой строки устройства в шапке markdown.
  - добавлен on_segment callback в transcribe() для --verbose без переделки API.
  - добавлено поле device_used в TranscribeResult (фактическое устройство после fallback).
  - добавлены тесты: test_utils.py (9 тестов), test_transcriber.py (4 mock-теста).
  - выровнено поведение пустой речи: файл с шапкой + *Речь не обнаружена.* в теле (PRD и plan).
  - добавлены импорты Callable, datetime, Path в заглушки шага 1.
  - убраны строки с git add -A / git commit из всех шагов.
- Проверка:
  - открыть docs/plan.md и docs/PRD.md и убедиться в согласованности.
2026-03-17 21:40:41 +03:00

13 KiB
Raw Blame History

PRD: local-transcriber — Локальный CLI для транскрипции аудио/видео

1. Обзор продукта

Название: local-transcriber Тип: CLI-утилита (Python, управление зависимостями через uv) Назначение: Принимает аудио- или видеофайл, выполняет распознавание речи локально (без внешних API), и создаёт рядом с исходным файлом markdown-файл с транскриптом и таймкодами.

Пример использования:

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:

# Транскрипт: 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: CUDA toolkit (cuBLAS, cuDNN) — ставится автоматически через CTranslate2
  • Дисковое пространство для моделей: ~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 для дефолтов проекта