# WhisperX с диаризацией

WhisperX расширяет Whisper от OpenAI тремя ключевыми улучшениями: **метки времени на уровне слов** через принудительное выравнивание фонем, **диаризация говорящих** с использованием pyannote.audio, и **до 70× реального времени** через пакетную инференцию с faster-whisper. Это инструмент выбора для производственных конвейеров транскрибации, которым нужны точные временные метки и определение говорящих.

**GitHub:** [m-bain/whisperX](https://github.com/m-bain/whisperX) **PyPI:** [whisperx](https://pypi.org/project/whisperx/) **Лицензия:** BSD-4-Clause **Статья:** [arxiv.org/abs/2303.00747](https://arxiv.org/abs/2303.00747)

## Ключевые особенности

* **Метки времени на уровне слов** — точность ±50 мс благодаря принудительному выравниванию wav2vec2 (в сравнении с ±500 мс в обычном Whisper)
* **Диаризация говорящих** — определение, кто сказал что, с помощью pyannote.audio 3.1
* **Пакетная инференция** — до 70× реального времени на RTX 4090
* **Предварительная фильтрация VAD** — Silero VAD удаляет тишину перед транскрибацией
* **Все модели Whisper** — от tiny до large-v3-turbo
* **Несколько форматов вывода** — JSON, SRT, VTT, TXT, TSV
* **Автоматическое определение языка** — или принудительно задать конкретный язык для более быстрой обработки

## Требования

| Компонент | Минимум                 | Рекомендуется           |
| --------- | ----------------------- | ----------------------- |
| GPU       | RTX 3060 12 ГБ          | RTX 4090 24 ГБ          |
| VRAM      | 4 ГБ (маленькая модель) | 10 ГБ+ (large-v3-turbo) |
| ОЗУ       | 8 ГБ                    | 16 ГБ+                  |
| Диск      | 5 ГБ                    | 20 ГБ (кеш моделей)     |
| Python    | 3.9+                    | 3.11                    |
| CUDA      | 11.8+                   | 12.1+                   |

**Требуется токен HuggingFace** для диаризации говорящих — примите лицензию на [pyannote/speaker-diarization-3.1](https://huggingface.co/pyannote/speaker-diarization-3.1).

**Рекомендация Clore.ai:** RTX 3090 (~~$0.30–1.00/день) для модели large-v3-turbo с размером батча 16. RTX 4090 (~~$0.50–2.00/день) для максимальной пропускной способности при размере батча 32.

## Установка

```bash
# Установка WhisperX
pip install whisperx

# Проверить GPU
python -c "import torch; print(torch.cuda.get_device_name(0))"
```

Если возникают конфликты версий CUDA:

```bash
pip install torch==2.5.1+cu124 torchaudio==2.5.1+cu124 --index-url https://download.pytorch.org/whl/cu124
pip install whisperx
```

## Быстрый старт

```python
import whisperx
import json

device = "cuda"
compute_type = "float16"  # "int8" для меньшего объёма VRAM
batch_size = 16            # уменьшите до 4–8 при ограниченной VRAM

# 1. Загрузить модель
model = whisperx.load_model("large-v3-turbo", device, compute_type=compute_type)

# 2. Загрузить и транскрибировать аудио
audio = whisperx.load_audio("interview.mp3")
result = model.transcribe(audio, batch_size=batch_size)
print(f"Language: {result['language']}")

# 3. Выравнивание для меток времени на уровне слов
model_a, metadata = whisperx.load_align_model(
    language_code=result["language"], device=device
)
result = whisperx.align(
    result["segments"], model_a, metadata, audio, device,
    return_char_alignments=False,
)

# 4. Печать результатов
for seg in result["segments"]:
    print(f"[{seg['start']:.2f}s → {seg['end']:.2f}s] {seg['text']}")
    for w in seg.get("words", []):
        print(f"  '{w['word']}' @ {w.get('start', 0):.2f}s")

# 5. Сохранение
with open("transcript.json", "w") as f:
    json.dump(result, f, indent=2, ensure_ascii=False)
```

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

### Транскрибация с диаризацией говорящих

```python
import whisperx
import gc
import torch

device = "cuda"
HF_TOKEN = "hf_your_token_here"  # с https://huggingface.co/settings/tokens

# Шаг 1: Транскрибировать
model = whisperx.load_model("large-v3-turbo", device, compute_type="float16")
audio = whisperx.load_audio("meeting.mp3")
result = model.transcribe(audio, batch_size=16)

# Освободите GPU-память перед загрузкой модели выравнивания
del model; gc.collect(); torch.cuda.empty_cache()

# Шаг 2: Выравнивание
model_a, metadata = whisperx.load_align_model(
    language_code=result["language"], device=device
)
result = whisperx.align(result["segments"], model_a, metadata, audio, device)
del model_a; gc.collect(); torch.cuda.empty_cache()

# Шаг 3: Диаризация
diarize_model = whisperx.DiarizationPipeline(
    use_auth_token=HF_TOKEN, device=device
)
diarize_segments = diarize_model(audio, min_speakers=2, max_speakers=6)

# Шаг 4: Назначить говорящих словам
result = whisperx.assign_word_speakers(diarize_segments, result)

for seg in result["segments"]:
    speaker = seg.get("speaker", "UNKNOWN")
    print(f"[{speaker}] [{seg['start']:.1f}s → {seg['end']:.1f}s] {seg['text']}")
```

### Использование из командной строки

```bash
# Базовая транскрибация
whisperx audio.mp3 --model large-v3-turbo --device cuda

# Принудительно задать язык (быстрее, пропускает определение)
whisperx audio.mp3 --model large-v3-turbo --language en --device cuda

# С диаризацией говорящих
whisperx audio.mp3 --model large-v3-turbo --diarize --hf_token hf_your_token

# Вывод субтитров SRT
whisperx audio.mp3 --model large-v3-turbo --output_format srt --output_dir ./subs/

# Режим для малой VRAM
whisperx audio.mp3 --model medium --compute_type int8 --batch_size 4 --device cuda

# Обработка каталога пакетно
for f in /data/audio/*.mp3; do
  whisperx "$f" --model large-v3-turbo --output_dir /data/transcripts/
done
```

### Скрипт генерации SRT

```python
import whisperx

def transcribe_to_srt(audio_path, output_path, model_name="large-v3-turbo"):
    device = "cuda"
    model = whisperx.load_model(model_name, device, compute_type="float16")
    audio = whisperx.load_audio(audio_path)
    result = model.transcribe(audio, batch_size=16)

    model_a, metadata = whisperx.load_align_model(
        language_code=result["language"], device=device
    )
    result = whisperx.align(result["segments"], model_a, metadata, audio, device)

    with open(output_path, "w") as f:
        for i, seg in enumerate(result["segments"], 1):
            start = format_ts(seg["start"])
            end = format_ts(seg["end"])
            f.write(f"{i}\n{start} --> {end}\n{seg['text'].strip()}\n\n")

    print(f"SRT сохранён в {output_path}")

def format_ts(seconds):
    h = int(seconds // 3600)
    m = int((seconds % 3600) // 60)
    s = int(seconds % 60)
    ms = int((seconds % 1) * 1000)
    return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}"

transcribe_to_srt("podcast.mp3", "podcast.srt")
```

## Тесты производительности

| Метод           | Модель             | Аудио 1ч     | GPU          | Прибл. скорость |
| --------------- | ------------------ | ------------ | ------------ | --------------- |
| Обычный Whisper | large-v3           | \~60 мин     | RTX 3090     | 1×              |
| faster-whisper  | large-v3           | \~5 мин      | RTX 3090     | \~12×           |
| **WhisperX**    | **large-v3-turbo** | **\~1 мин**  | **RTX 3090** | **\~60×**       |
| **WhisperX**    | **large-v3-turbo** | **\~50 сек** | **RTX 4090** | **\~70×**       |

| Размер батча | Скорость (RTX 4090)     | VRAM  |
| ------------ | ----------------------- | ----- |
| 4            | \~30× реального времени | 6 GB  |
| 8            | \~45× реального времени | 8 ГБ  |
| 16           | \~60× реального времени | 10 ГБ |
| 32           | \~70× реального времени | 14 ГБ |

## Советы для пользователей Clore.ai

* **Освобождайте VRAM между шагами** — удаляйте модели и вызывайте `torch.cuda.empty_cache()` между транскрибацией, выравниванием и диаризацией
* **Токен HuggingFace** — вы должны принять лицензию модели pyannote перед тем, как диаризация заработает; установите `HF_TOKEN` как переменную окружения
* **Настройка размера батча** — начните с `batch_size=16`, уменьшите до 4–8 на картах 12 ГБ, увеличьте до 32 на картах 24 ГБ
* **`int8` вычисление** — используйте `compute_type="int8"` чтобы сократить использование VRAM вдвое с минимальной потерей качества
* **Docker-образ** — `pytorch/pytorch:2.5.1-cuda12.4-cudnn9-runtime`
* **Постоянный кеш моделей** — смонтируйте `/root/.cache/huggingface` чтобы не скачивать модели заново при каждом перезапуске контейнера

## Устранение неполадок

| Проблема                        | Решение                                                                                                              |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `CUDA — недостаточно памяти`    | Уменьшите `batch_size`, используйте `compute_type="int8"`, или используйте меньшую модель (medium, small)            |
| Диаризация возвращает `UNKNOWN` | Убедитесь, что токен HuggingFace действителен и вы приняли лицензию pyannote                                         |
| `Модуль 'whisperx' не найден`   | `pip install whisperx` — убедитесь, что нет опечатки (это `whisperx`, а не на `whisper-x`)                           |
| Плохие метки времени слов       | Проверьте, что `whisperx.align()` вызывается после `transcribe()` — сыой вывод Whisper не имеет точности по словам   |
| Неправильное определение языка  | Принудительно задайте язык с помощью `--language en` или `language="en"` в Python API                                |
| Медленная обработка             | Увеличьте `batch_size`, используйте `large-v3-turbo` вместо `large-v3`, убедитесь, что GPU не используется совместно |
