WhisperX: распознавание речи, таймкоды по словам и определение говорящих
WhisperX: распознавание речи, таймкоды по словам и определение говорящих

WhisperX — это надстройка над OpenAI Whisper, которая решает ключевые проблемы оригинального решения: отсутствие точных таймкодов для слов и невозможность определить, кто говорит. WhisperX предлагает быстрый и точный способ транскрибировать аудио с разбивкой по словам, поддержкой нескольких голосов и отличной производительностью (до 70x в реальном времени на GPU).

Зачем использовать WhisperX?

  • Словесные таймкоды: Whisper от OpenAI даёт таймкоды только для фраз — WhisperX синхронизирует каждое слово с точным временем.
  • Идентификация говорящих: встроенная диаризация позволяет определить, кто говорил и когда — важно для интервью, подкастов, собраний.
  • Скорость: до 70x быстрее реального времени при пакетной обработке аудио на больших моделях.
  • Гибкость: CLI и Python API, поддержка других языков, совместимость с CPU и GPU.

Что под капотом WhisperX?

  1. Whisper (OpenAI): модель распознавания речи.
  2. wav2vec2: модель для точной привязки слов к аудио (алайнмент).
  3. VAD: Voice Activity Detection — фильтрация несодержательной тишины и шумов.
  4. pyannote-audio: библиотека для определения говорящих (диаризация).

Установка WhisperX

1. Быстрая установка через pip

pip install whisperx

Подходит большинству пользователей. Также установите ffmpeg и rust:

sudo apt install ffmpeg
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

2. Установка с GitHub (для разработчиков)

git clone https://github.com/m-bain/whisperX.git
cd whisperX
uv sync --all-extras --dev

Важно: Убедитесь, что ваша среда поддерживает torch и transformers, особенно для GPU-версии. Для диаризации потребуется Hugging Face токен и принятие лицензий.

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

Базовая транскрипция

whisperx path/to/audio.wav

Это создаст транскрипт с таймкодами фраз.

Точная разбивка по словам (алайнмент)

whisperx path/to/audio.wav --model large-v2 --align_model WAV2VEC2_ASR_LARGE_LV60K_960H

Используется модель wav2vec2 для точной привязки каждого слова к аудио.

Диаризация (определение говорящих)

whisperx path/to/audio.wav --model large-v2 --diarize --hf_token YOUR_HF_TOKEN

Если вы знаете количество говорящих, укажите диапазон:

--min_speakers 2 --max_speakers 2

Работа на CPU

whisperx path/to/audio.wav --compute_type int8

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

import whisperx

device = "cuda"
audio_file = "audio.mp3"

# 1. Транскрипция
model = whisperx.load_model("large-v2", device)
audio = whisperx.load_audio(audio_file)
result = model.transcribe(audio)
print(result["segments"])  # до тайминга слов

# 2. Алайнмент (привязка слов к аудио)
model_a, metadata = whisperx.load_align_model(language_code=result["language"], device=device)
result = whisperx.align(result["segments"], model_a, metadata, audio, device)
print(result["segments"])  # с таймкодами для каждого слова

# 3. Диаризация
diarize_model = whisperx.diarize.DiarizationPipeline(use_auth_token="YOUR_HF_TOKEN", device=device)
diarize_segments = diarize_model(audio)
result = whisperx.assign_word_speakers(diarize_segments, result)

print(result["segments"])  # теперь с ID говорящих

Частые проблемы

  • Медленная работа: уменьшите размер модели (--model base), размер батча (--batch_size 4) или используйте --compute_type int8.
  • Ошибки диаризации: проверьте совместимость версий pyannote-audio и используемой модели (Speaker-Diarization-3.1).
  • Отсутствие таймкодов: слова вроде чисел или символов (£, %) не будут синхронизированы, если их нет в словаре модели.

Итоги

WhisperX — это мощный инструмент, который делает распознавание речи действительно пригодным для практических задач: субтитры, интервью, стенограммы и архивирование встреч. Он расширяет возможности оригинального Whisper, обеспечивая точную разбивку текста по времени и определение говорящих. Благодаря удобному интерфейсу и высокой скорости работы, это один из лучших инструментов в сфере ASR (Automatic Speech Recognition).

Полезные ссылки

Интеграция WhisperX в реальные пайплайны

WhisperX легко встраивается в автоматические пайплайны для медиааналитики, субтитров, подкаст-платформ, голосовых интерфейсов и архивирования звонков. Вот несколько сценариев:

  • Обработка встреч: объедините WhisperX с Zoom API или Microsoft Graph для автоматической расшифровки звонков с определением говорящих и экспортом в PDF или Notion.
  • Создание субтитров: используйте вывод .srt или .vtt для публикации видео с субтитрами, включая YouTube и Vimeo.
  • Контент-анализ: интеграция с NLP-инструментами (например, spaCy или GPT) позволяет проводить тематический анализ речи, выявлять тональность или ключевые темы.
  • Интерфейсы: WhisperX может выступать основой для голосового ввода в чат-ботах, поддерживая команды, подсказки и пользовательские сценарии.

Это делает WhisperX не просто инструментом распознавания, а частью целостной цепочки обработки и анализа речи.

Практика: экспорт в .srt и форматирование под UI

Результаты работы WhisperX можно удобно использовать не только для анализа, но и для отображения в интерфейсах. Ниже — два практических сценария: генерация субтитров и форматирование данных по говорящим.

📄 Экспорт субтитров в формате .srt

После выравнивания сегментов с помощью WhisperX вы можете сохранить результат как .srt-файл с точными метками начала и конца фраз:

from datetime import timedelta

def format_timestamp(seconds):
    td = timedelta(seconds=seconds)
    return str(td)[:-3].replace('.', ',').zfill(12)

def save_srt(segments, path="output.srt"):
    with open(path, "w", encoding="utf-8") as f:
        for i, seg in enumerate(segments, 1):
            start = format_timestamp(seg["start"])
            end = format_timestamp(seg["end"])
            text = seg["text"].strip()
            f.write(f"{i}\n{start} --> {end}\n{text}\n\n")

# segments = result["segments"] после выравнивания
save_srt(result["segments"])

Итоговый файл можно загружать на платформы вроде YouTube, Vimeo, в видеоредакторы или CMS-системы.

👥 Группировка сегментов по говорящим (JSON для UI)

Если вы используете определение говорящих (speaker diarization), результат можно удобно сгруппировать по спикерам — например, для отображения в виде диалога:

from collections import defaultdict
import json

def group_by_speaker(segments):
    speakers = defaultdict(list)
    for seg in segments:
        speaker = seg.get("speaker", "unknown")
        speakers[speaker].append({
            "start": seg["start"],
            "end": seg["end"],
            "text": seg["text"].strip()
        })
    return speakers

grouped = group_by_speaker(result["segments"])

with open("transcript_by_speaker.json", "w", encoding="utf-8") as f:
    json.dump(grouped, f, ensure_ascii=False, indent=2)

Пример структуры:

{
  "SPEAKER_00": [
    { "start": 0.45, "end": 2.93, "text": "Добрый день, коллеги!" },
    { "start": 5.21, "end": 7.15, "text": "Сегодня мы обсудим проект." }
  ],
  "SPEAKER_01": [
    { "start": 2.95, "end": 4.80, "text": "Здравствуйте, я подготовил отчет." }
  ]
}

Такой формат легко интегрируется в пользовательские интерфейсы: от субтитров и таймлайн-редакторов до чатов с цветовой маркировкой по ролям.

Дополнительно: советы по производительности, качеству и стабильности

🔧 Оптимизация под слабое железо

WhisperX можно запускать даже без GPU — при правильной настройке. Вот как минимизировать нагрузку:

  • Используйте параметр: --compute_type int8 или "int8" в Python — это снижает требования к памяти.
  • Уменьшите размер модели: вместо large-v2 попробуйте base или medium.
  • Снижайте размер батча: --batch_size 2 или даже 1, если возникают ошибки CUDA.
  • Для CPU-систем: установите ffmpeg, и запускайте с --compute_type int8 --device cpu. На Mac M1 transcription 1 мин аудио занимает примерно 45 секунд с моделью base.

🧪 Проверка качества: метрики WER и CER

Для оценки качества распознавания используйте метрики:

  • WER (Word Error Rate) — процент ошибок по словам.
  • CER (Character Error Rate) — полезна для коротких фраз и субтитров.

Пример расчета WER в Python:

from jiwer import wer

ref = "Сегодня мы обсуждаем проект"
hyp = "Сегодня мы обсуждаем проект"
print("WER:", wer(ref, hyp))

Библиотека jiwer автоматически нормализует текст (удаляет пунктуацию, приводит к нижнему регистру).

🛡️ Повышение стабильности и избежание ошибок

  • 📦 Не используйте одновременно PyTorch 2.x и старые версии pyannote: проверьте зависимости при установке diarization.
  • 🧼 Освобождайте ресурсы: после использования моделей — gc.collect(); torch.cuda.empty_cache().
  • 🎯 Отключите --condition_on_prev_text, если в результатах появляются галлюцинации.
  • 📈 Для длинных файлов: разбейте их заранее или используйте встроенную VAD-фильтрацию (включена по умолчанию).

📊 Отладка и визуализация результатов

WhisperX может сохранять результаты выравнивания с визуализацией слов в .srt или json. Для быстрой отладки:

  • Включите --highlight_words True — в .srt будут метки каждого слова.
  • Постройте диаграмму: текст по оси X, спикеры/время по Y — это помогает найти «прыжки» времени или ошибки diarization.

🗣️ Поддержка языков и модели выравнивания

WhisperX использует разные phoneme-based модели для выравнивания, которые зависят от языка:

  • Для en, fr, de, es, it — модели загружаются из torchaudio автоматически.
  • Для других языков — необходимо указать --align_model вручную, выбрав подходящую модель с Hugging Face.

Список поддерживаемых языков можно найти в переменной DEFAULT_ALIGN_MODELS_HF в alignment.py.

⚠️ Типичные ограничения

  • 📉 WhisperX плохо справляется с перекрывающейся речью (одновременные говорящие).
  • 🧾 Числа, валюты и нестандартные символы (например, £13.60, 2014.) могут не выравниваться — они отсутствуют в словарях моделей.
  • 👤 Diarization по-прежнему неточен в шумных аудио и при большом числе участников (>4).