feat(auto): выбран ONNX по умолчанию без CUDA

- Зачем:
  - пользователям без NVIDIA нужен самый быстрый и читаемый CPU-профиль без дополнительных параметров.
- Что:
  - auto-политика изменена на CUDA при наличии nvidia-smi, иначе ONNX GigaAM RNN-T int8.
  - сохранён приоритет явных значений CLI и конфигурации для OpenVINO и FasterWhisper CPU.
  - обновлены тесты, README, PRD, ADR, GPU-документация и вывод benchmark.
- Проверка:
  - uv run pytest -q: 232 passed, 1 skipped.
  - uv lock --check и git diff --cached --check.
This commit is contained in:
Dmitriy Dementiev
2026-08-12 10:45:05 +03:00
parent 12e17020bf
commit 136e93765c
13 changed files with 177 additions and 115 deletions
+33 -31
View File
@@ -24,8 +24,9 @@ transcribe meeting-2026-03-17.mp4
### 3.1. Основной flow
1. Пользователь вызывает CLI, передаёт путь к файлу (или glob-маску, post-MVP)
2. Проверка: ffmpeg доступен в PATH
3. Файл передаётся в faster-whisper (он сам обрабатывает и аудио, и видео через libav/ffmpeg — отдельное извлечение аудиодорожки не нужно)
2. Файл валидируется по пути, размеру и расширению
3. По `device` выбирается backend; аудио декодируется через PyAV без отдельного
извлечения дорожки
4. Результат форматируется в markdown с таймкодами
5. Файл `<имя>-transcript.md` сохраняется рядом с исходным (кодировка: UTF-8)
@@ -41,16 +42,16 @@ transcribe meeting-2026-03-17.mp4
transcribe <путь_к_файлу> [опции]
Опции:
--model, -m Модель Whisper (tiny|base|small|medium|large-v3)
По умолчанию: large-v3
--model, -m Модель распознавания
По умолчанию: medium (CUDA) / gigaam-v3-e2e-rnnt (ONNX)
--language, -l Язык (ru|en|auto)
По умолчанию: auto (автодетект)
По умолчанию: ru
--output, -o Путь к выходному файлу
По умолчанию: <input_stem>-transcript.md
--device, -d Устройство (auto|cpu|cuda|openvino|openvino-gpu|openvino-cpu)
По умолчанию: auto (CUDA → OpenVINO GPU → OpenVINO CPU → CPU)
--compute-type Тип вычислений (float16|int8|int8_float16|float32)
По умолчанию: int8 (универсален для GPU 4-8 GB и CPU)
--device, -d Устройство (auto|cpu|cuda|onnx|openvino|openvino-gpu|openvino-cpu)
По умолчанию: auto (CUDA при наличии, иначе ONNX CPU)
--compute-type Тип вычислений
По умолчанию: float16 (CUDA) / int8 (ONNX)
--verbose, -v Подробный вывод (прогресс сегментов)
```
@@ -82,16 +83,17 @@ transcribe <путь_к_файлу> [опции]
**Правила форматирования**:
- Таймкоды в формате `[MM:SS.ss - MM:SS.ss]` (минуты:секунды.сотые)
- Для записей длиннее 1 часа — `[HH:MM:SS.ss - HH:MM:SS.ss]`
- Каждый сегмент — отдельный абзац
- Соседние сегменты объединяются в абзац до паузы 2 секунды или длительности 60 секунд
- Метаданные в шапке файла
- Пустая строка между сегментами для читаемости
- Пустая строка между абзацами для читаемости
### 3.4. Поддерживаемые форматы
**Аудио**: mp3, wav, flac, ogg, m4a, wma, aac
**Видео**: mp4, mkv, avi, mov, webm, ts
Определение типа — по расширению. Фактическое декодирование выполняет ffmpeg внутри faster-whisper; если формат не поддерживается, ошибка будет от ffmpeg.
Определение типа — по расширению. Фактическое декодирование выполняет PyAV с
встроенными библиотеками FFmpeg; системная установка `ffmpeg` не требуется.
## 4. Нефункциональные требования
@@ -102,6 +104,8 @@ transcribe <путь_к_файлу> [опции]
| 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 + ONNX GigaAM RNN-T | ~10-14x (1 час аудио ≈ 4-6 мин) |
| CPU + OpenVINO Turbo INT8 | ~7-10x (1 час аудио ≈ 6-9 мин) |
| CPU (modern) + large-v3 | ~0.5-1x (1 час аудио ≈ 60-120 мин) |
| CPU + small | ~3-5x (1 час аудио ≈ 12-20 мин) |
@@ -112,23 +116,22 @@ transcribe <путь_к_файлу> [опции]
| RTX 3060 | 6 GB | ✅ | ✅ (впритык) | int8 — безопасный выбор |
| RTX 4050 | 6 GB | ✅ | ✅ (впритык) | int8 — безопасный выбор |
| Quadro M3000M | 4 GB | ✅ | ⚠️ может OOM | int8 обязательно |
| Без GPU | — | CPU int8 | — | int8 на CPU |
| Без GPU | — | ONNX GigaAM INT8 | — | auto выбирает ONNX |
Дефолт `int8` выбран как универсальный: работает на всех GPU от 4 GB и на CPU, при минимальной потере качества относительно float16.
Device-aware дефолты выбирают `float16` для CUDA и `int8` для ONNX/OpenVINO.
### 4.2. Требования к окружению
- Python ≥ 3.13
- ffmpeg в PATH (используется faster-whisper внутри для декодирования любых медиаформатов)
- Для GPU: Linux/WSL2 — cuBLAS из nvidia-cublas-cu12 (ставится автоматически через `uv sync`); Windows — системный CUDA toolkit (см. ADR-001)
- Дисковое пространство для моделей: ~3 GB (large-v3)
- Дисковое пространство для моделей: зависит от выбранного backend и модели
- Выходные файлы: UTF-8 (явная кодировка при записи)
### 4.3. Кроссплатформенность
- Linux: нативный запуск
- Windows: нативный Python или WSL2
- macOS: не приоритет, но faster-whisper поддерживает CPU-режим
- macOS: ONNX CPU в auto-режиме; FasterWhisper CPU доступен явно
## 5. Технический стек
@@ -136,19 +139,18 @@ transcribe <путь_к_файлу> [опции]
|---------------------|-------------------------------------------------|
| Язык | Python 3.13+ |
| Управление проектом | uv (pyproject.toml) |
| Распознавание речи | faster-whisper (CTranslate2 backend) |
| Медиа-декодирование | ffmpeg (системная зависимость, используется faster-whisper внутри) |
| Распознавание речи | faster-whisper, ONNX Runtime, OpenVINO GenAI |
| Медиа-декодирование | PyAV со встроенными библиотеками FFmpeg |
| CLI-фреймворк | typer |
| Прогресс | rich (progress bar + статус) |
### 5.1. Почему faster-whisper
### 5.1. Почему несколько backend
- В 4× быстрее оригинального OpenAI Whisper при том же качестве
- Меньше потребление VRAM (large-v3 влезает в 6 GB с float16/int8)
- Нативный Python API, без Docker
- Поддержка CPU fallback из коробки
- Активное сообщество, регулярные обновления
- Автоматическая загрузка моделей из Hugging Face Hub
- faster-whisper оптимизирован для NVIDIA CUDA и поддерживает много языков
- ONNX GigaAM RNN-T даёт быстрый читаемый результат на CPU
- OpenVINO предоставляет явные профили для Intel GPU и x86 CPU
- Все backend работают локально через Python API, без Docker и облачных ключей
- Модели загружаются автоматически и кешируются локально
### 5.2. Структура проекта
@@ -160,9 +162,10 @@ local-transcriber/
│ └── local_transcriber/
│ ├── __init__.py
│ ├── cli.py # CLI entry point (typer)
│ ├── transcriber.py # Обёртка над faster-whisper
│ ├── transcriber.py # Оркестрация backend и fallback
│ ├── backends/ # Адаптеры FasterWhisper, ONNX и OpenVINO
│ ├── formatter.py # Форматирование в markdown
│ └── utils.py # Проверки (ffmpeg), определение device и т.д.
│ └── utils.py # Проверки файлов и определение device
└── tests/
└── ...
```
@@ -173,11 +176,10 @@ local-transcriber/
|------|---------|-----------|
| Качество распознавания русского текста | Среднее | 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 с предупреждением |
| Большие файлы (>2 часов) | Среднее | Учитывать память выбранного backend; чанкование рассматривается отдельно |
| OOM на GPU с 4 GB VRAM | Среднее | CUDA использует float16; при OOM — fallback на CPU с предупреждением или явный более лёгкий профиль |
| Файл без речи (тишина, музыка, шум) | Низкое | Создаётся транскрипт с шапкой метаданных и `*Речь не обнаружена.*` в теле + предупреждение в stderr |
## 7. Вне скоупа MVP
+9 -6
View File
@@ -2,6 +2,7 @@
**Статус**: Принято
**Дата**: 2026-03-21
**Обновлено**: 2026-08-12
## Контекст
@@ -39,7 +40,8 @@ shared libraries. Ни то, ни другое не должно происхо
Вместо отдельного `--backend` флага устройство само определяет бэкенд:
- `cuda`, `cpu` → FasterWhisperBackend
- `openvino` → OpenVINOBackend
- `auto`CUDA (nvidia-smi) → OpenVINO (import check + x86) → CPU
- `onnx`OnnxAsrBackend
- `auto` → CUDA при наличии `nvidia-smi`, иначе ONNX на CPU
### load_model() — единственный владелец pipeline
@@ -71,18 +73,19 @@ OpenVINO модели предквантизированы (int8/fp16), compute_
- Из дефолтов: для large-v3 автоматически выбирается fp16 (стабильнее по качеству)
- Несуществующая пара (model + compute_type) при явном выборе → ошибка
### Обе зависимости по умолчанию
### Зависимости бэкендов по умолчанию
faster-whisper (~37MB) и openvino-genai (~69MB) ставятся вместе — суммарно ~106MB,
приемлемо. Модели скачиваются только для активного бэкенда. CUDA (nvidia-cublas-cu12,
~554MB) остаётся conditional (Linux x86_64). OpenVINO — conditional (x86_64/AMD64, не macOS).
faster-whisper, onnx-asr/onnxruntime и openvino-genai ставятся вместе. Модели
скачиваются только для активного бэкенда. CUDA (`nvidia-cublas-cu12`) остаётся
conditional для Linux x86_64. OpenVINO — conditional для x86_64/AMD64, кроме
macOS; ONNX обеспечивает автоматический CPU-путь на остальных платформах.
## Последствия
- Обратная совместимость: `transcribe()` сохранён; `load_model()` изменил сигнатуру (возвращает 4-tuple вместо 2-tuple, добавлен `compute_type_explicit`)
- Новый бэкенд добавляется одним файлом в `backends/` + регистрацией в `__init__.py`
- Модели скачиваются по запросу — CUDA пользователь не качает OpenVINO модели, и наоборот
- ARM и macOS: OpenVINO не ставится (platform markers), работает CPU через faster-whisper
- ARM и macOS: OpenVINO не ставится (platform markers), auto использует ONNX
## Отклонённые альтернативы
+10 -7
View File
@@ -2,7 +2,7 @@
**Статус**: Принято
**Дата**: 2026-04-25
**Обновлено**: 2026-08-11
**Обновлено**: 2026-08-12
## Контекст
@@ -101,10 +101,11 @@ Mm-hmm-редукция и иностранные вставки **не обна
## Решение
**Принять onnx-asr как экспериментальный бэкенд с явным `--device onnx`.
GigaAM v3 E2E RNN-T — модель по умолчанию для русских встреч на CPU.**
**Принять onnx-asr как CPU-бэкенд автоматического профиля.
GigaAM v3 E2E RNN-T — модель по умолчанию на машинах без CUDA.**
Бэкенд **не в auto-detect** — только при явном указании пользователем (политика experimental backend, как для openvino).
Порядок `--device auto`: CUDA при наличии `nvidia-smi`, иначе ONNX. OpenVINO и
FasterWhisper CPU остаются доступными через явный CLI-аргумент или конфиг.
Модели:
- **`gigaam-v3-e2e-rnnt`** — модель по умолчанию: практически равна обычному
@@ -122,7 +123,9 @@ GigaAM v3 E2E RNN-T — модель по умолчанию для русски
- Пользователи CPU-only с русскоязычным контентом получают 3-5× ускорение по сравнению с OpenVINO medium **при превосходящем качестве** (4/5 vs 1-2/5 summary utility на длинных файлах).
- Пользователи ONNX без явного `--model` получают пунктуацию и нормализацию
RNN-T; более точный сырой CTC остаётся доступен как `--model gigaam-v3`.
- Whisper medium (`--device openvino-cpu`) **остаётся допустимым** для коротких (≤30 мин) встреч с равномерной громкостью; на длинных файлах с тихими участками он галлюцинирует целыми блоками — этот риск зафиксирован, но решение не выводит OpenVINO из списка дефолтов (часть пользователей всё ещё нуждается в пунктуации, и для коротких файлов галлюцинации не воспроизводятся).
- Whisper medium (`--device openvino-cpu`) **остаётся допустимым явным профилем**
для коротких (≤30 мин) встреч с равномерной громкостью; на длинных файлах с
тихими участками он может галлюцинировать целыми блоками.
- Parakeet-v3 формально доступен, но в README рекомендуется только для англоязычного контента — для русского явно не годится.
- GPU faster-whisper large-v3 остаётся эталоном по качеству (для пользователей с NVIDIA GPU).
- Пост-процессинг GigaAM-транскрипта LLM-этапом нормализации (восстановление латинских терминов и имён компаний) — рекомендуемая практика для финального конспекта.
@@ -131,7 +134,8 @@ GigaAM v3 E2E RNN-T — модель по умолчанию для русски
- **Galлюцинации Whisper medium на длинных файлах** — отдельный продуктовый риск, требующий собственного исследования. Возможно, имеет смысл ограничить максимальную длину чанка для openvino-medium, или дать предупреждение пользователю.
- **Canary** (`nemo-canary-1b-v2`) — тяжелее, но multilingual + пунктуация. Кандидат на «лучшее качество за разумную скорость» для тех, кому важна пунктуация.
- **Auto-detect onnx**: после стабилизации в production-использовании (несколько недель) — рассмотреть включение в auto-detect как первый CPU-бэкенд (ниже CUDA, выше OpenVINO).
- Проверить профиль на других языках и при необходимости добавить явные
многоязычные рекомендации; автоматическая политика намеренно не зависит от языка.
## Отклонённые альтернативы
@@ -139,5 +143,4 @@ GigaAM v3 E2E RNN-T — модель по умолчанию для русски
|---|---|
| NeMo Parakeet напрямую (без onnx-asr) | Требует PyTorch + CUDA, Python ≥ 3.12, ~2 GB зависимостей — слишком тяжело для CLI |
| Замена faster-whisper на onnx-asr | faster-whisper поддерживает 99+ языков и пунктуацию, остаётся лучшим GPU-бэкендом |
| GigaAM как auto-detect default | Экспериментальный бэкенд, политика — не сюрпризить существующих пользователей; включение в auto-detect — после периода стабилизации |
| Parakeet-v3 как multilingual default | Воспроизведённые проблемы из ADR-005 (Mm-hmm-редукция, иноязычные вставки) делают его непригодным для русского; для других языков не валидировано в этом эксперименте |
-10
View File
@@ -252,16 +252,6 @@ SQL`), словарь пользовательский в `.transcriber.toml`.
---
### Включение `onnx` в `--device auto`
**Что:** После периода стабилизации `--device onnx` (несколько недель production-использования без жалоб) — рассмотреть включение в auto-detect chain.
**Порядок в chain (предложение):** CUDA → onnx (если CPU x86_64) → OpenVINO → CPU.
**Почему откладывается:** политика experimental backend — не сюрпризить существующих пользователей до накопления опыта. Источник: [ADR-006](adr/006-onnx-asr-backend.md#решение).
---
## Отклонённые направления
*(пока пусто — добавлять сюда то, что попробовали и решили не делать, с причиной)*
@@ -304,23 +304,21 @@ INT8 почти равен ему. Они лучше удерживают `FineB
### Что это означает для профиля по умолчанию
Результаты поддерживают ONNX GigaAM RNN-T как основной кандидат для русской
речи на CPU: он быстрее всех на обеих машинах, дважды занял первое место по
читаемости и пригодности для конспекта и использует VAD. Но делать его
безусловным глобальным `--device auto` преждевременно:
Результаты поддерживают ONNX GigaAM RNN-T как основной CPU-профиль: он быстрее
всех на обеих машинах, дважды занял первое место по читаемости и пригодности
для конспекта и использует VAD. После обсуждения принята простая политика:
`--device auto` выбирает CUDA при наличии `nvidia-smi`, иначе ONNX.
Ограничения выбора сохраняются:
- GigaAM ориентирован на русский язык и хуже сохраняет латиницу, аббревиатуры,
названия систем и компаний;
- OpenVINO Whisper остаётся многоязычным путём и умеет использовать Intel GPU;
- Turbo лучше GigaAM по WER и техническим терминам, хотя хуже подготовлен для
непосредственного чтения;
- изменение существующего auto-пути будет несовместимым изменением поведения и
требует отдельной продуктовой задачи с language-aware выбором.
Практичный кандидат на будущую политику: `CUDA` для NVIDIA, OpenVINO для Intel
GPU, ONNX GigaAM RNN-T для явно русской речи на CPU, OpenVINO/Whisper для других
языков и явный выбор Turbo для технически насыщенных встреч. В рамках текущей
задачи эта политика не реализуется.
- изменение существующего auto-пути является несовместимым изменением поведения;
явные значения из CLI и конфигурации остаются способом сохранить прежний
OpenVINO/Whisper-профиль или выбрать Turbo для технически насыщенных встреч.
## Вывод
@@ -338,8 +336,9 @@ GPU, ONNX GigaAM RNN-T для явно русской речи на CPU, OpenVIN
протокола может потребоваться последующая расстановка пунктуации.
- Автоматических предупреждений о повторах или потере хвоста после обновления
не было; ручная проверка нашла у medium одиночный ложный сегмент в конце RSQM.
- Модель по умолчанию и порядок `--device auto` оставлены без изменений. Решение
об их изменении требует отдельной продуктовой задачи.
- В самом benchmark-коммите модель по умолчанию и порядок `--device auto` не
менялись; по итогам анализа отдельно принято решение использовать ONNX на
машинах без CUDA.
- Повторный Ryzen-прогон подтвердил, что прежний блок из 11 повторов `medium`
не воспроизводится: четыре последовательных прохода дали одинаковый текст без
повторов и ложного хвоста. Это подтверждение для контрольного файла, а не
+7 -6
View File
@@ -2,7 +2,7 @@
## Режимы `--device`
- `auto` (по умолчанию) — CUDA → OpenVINO GPU → OpenVINO CPU → CPU (первый доступный)
- `auto` (по умолчанию) — CUDA при наличии `nvidia-smi`, иначе ONNX на CPU
- `cuda` — строго NVIDIA GPU, ошибка если недоступен
- `openvino` — авто-выбор OpenVINO GPU или CPU
- `openvino-gpu` — строго Intel GPU через OpenVINO
@@ -14,12 +14,13 @@
| Оборудование | Рекомендуемый `--device` | Бэкенд | Ожидаемая скорость |
|---|---|---|---|
| NVIDIA GPU (6+ GB VRAM) | `auto` / `cuda` | faster-whisper (CTranslate2) | 7-19x реалтайм |
| Intel Arc iGPU / dGPU | `auto` / `openvino-gpu` | OpenVINO GenAI (GPU) | TBD |
| Intel/AMD x86 CPU | `auto` / `openvino-cpu` | OpenVINO GenAI (CPU) | 3-6x реалтайм* |
| Любой CPU (fallback) | `cpu` | faster-whisper (CTranslate2) | ~1.5x реалтайм |
| Apple Silicon (macOS) | `cpu` | faster-whisper (CTranslate2) | ~2x реалтайм |
| Любой CPU без NVIDIA | `auto` / `onnx` | ONNX GigaAM RNN-T | 10-14x реалтайм* |
| Intel Arc iGPU / dGPU | `openvino-gpu` | OpenVINO GenAI (GPU) | TBD |
| Intel/AMD x86 CPU | `openvino-cpu` | OpenVINO GenAI (CPU) | 3-10x реалтайм* |
| Любой CPU, FasterWhisper | `cpu` | faster-whisper (CTranslate2) | ~1.5x реалтайм |
\* По результатам тестирования на Intel и AMD CPU. Реальная скорость зависит от CPU и модели.
\* По результатам контрольных прогонов на Intel и AMD CPU. Реальная скорость
зависит от CPU, модели и записи.
## OpenVINO