feat(transcriber): реализована обёртка над faster-whisper (шаг 3)

- Зачем:
  - необходим модуль транскрипции с CUDA fallback для основного flow приложения.
- Что:
  - добавлена зависимость faster-whisper>=1.2.1 в pyproject.toml.
  - реализована функция transcribe() с fallback CUDA→CPU на всех этапах (загрузка модели, вызов transcribe, итерация сегментов).
  - исправлен IndexError в get_gpu_name() при пустом stdout nvidia-smi.
  - добавлено 6 тестов в test_transcriber.py и 1 тест в test_utils.py (16 тестов зелёные).
- Проверка:
  - uv run pytest -v (16 passed).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 22:30:40 +03:00
co-authored by Claude Opus 4.6
parent 510d6ccfc9
commit dfc5f46bf3
7 changed files with 862 additions and 8 deletions
+4 -4
View File
@@ -161,18 +161,18 @@
> PRD-ссылки: 5.1 (faster-whisper), 4.1.1 (GPU совместимость), 6 (риски OOM)
- [ ] `uv add faster-whisper` — добавить в зависимости
- [ ] Реализовать `transcribe()`:
- [x] `uv add faster-whisper` — добавить в зависимости
- [x] Реализовать `transcribe()`:
- Создать `WhisperModel(model_name, device=device, compute_type=compute_type)`
- При ошибке загрузки на CUDA (OOM, CUDA error) → **поймать**, вывести warning, **повторить с device="cpu"**
- Запомнить фактический device → записать в `TranscribeResult.device_used`
- `model.transcribe(str(file_path), language=language if language != "auto" else None)`
- faster-whisper возвращает `(segment_generator, info)` — итерировать generator, для каждого сегмента вызвать `on_segment(segment)` если callback передан, затем собрать в `list[Segment]`
- Заполнить `TranscribeResult` из info (language, duration и т.д.)
- [ ] Обработка ошибок:
- [x] Обработка ошибок:
- `RuntimeError` с "CUDA" / "out of memory" → fallback на CPU + warning
- Ошибка ffmpeg (невалидный медиафайл) → пробросить с понятным текстом
- [ ] Тесты в `tests/test_transcriber.py` (mock WhisperModel, без реальной модели):
- [x] Тесты в `tests/test_transcriber.py` (mock WhisperModel, без реальной модели):
- `test_transcribe_collects_segments` — mock возвращает 3 сегмента → результат содержит 3 Segment
- `test_transcribe_calls_on_segment` — callback вызывается для каждого сегмента
- `test_transcribe_cuda_fallback` — mock бросает RuntimeError("CUDA") при device="cuda" → fallback, `device_used == "cpu"`