Разработчик рассказал, как Whisper врёт в проде и как это ловить

Разработчик сервиса дубляжа speeek описал, как Whisper ошибается в продакшене и какие костыли помогают это ловить. За 2026 год через его конвейер прошло 9 203 задачи.

Главное
  • Слово длиннее 50 символов в транскрипции удаляется целиком — в живой речи таких нет
  • Повтор одной подстроки пять раз в окне 130 символов считается галлюцинацией и уходит на чистку в LLM
  • Распознавание идёт на своей A4000 с whisperX large-v3-turbo, при отказе — Replicate, затем Gladia
Схема конвейера обработки видео: от загрузки файла до распознавания речи нейросетью Whisper
Фото: Хабр: Машинное обучение

Разработчик сервиса дубляжа speeek опубликовал на Хабре первую из трёх статей о том, как нейросеть переводит видео. Он пишет код один с 2022 года, когда OpenAI выложил Whisper. За 2026 год через конвейер прошло 9 203 задачи, и он ломается в тех же местах, что и в первый месяц.

Статья посвящена входу конвейера: как звук превращается в текст с таймкодами и спикерами. Это не туториал по Whisper, а разбор того, что с моделью происходит в проде, когда пользователь грузит запись вебинара с телефона.

Пять этапов и сорок мелочей

На вход принимаются mp4, mov, mp3, wav или ссылка на YouTube. С YouTube видео качается через yt-dlp в 720p, звук вытаскивается ffmpeg в mp3, а из видео удаляются все аудиодорожки. Одна из неожиданных проблем: у части файлов аудиодорожка короче видео на полсекунды или секунду. Если это не поправить, укладка перевода в конце съедет. Решение — дописать тишину.

Перед распознаванием звук разделяется на вокал и всё остальное через Demucs. Whisper на чистом вокале ошибается меньше, чем на вокале с музыкой. Фон сохраняется, чтобы переведённая речь ложилась на оригинальную подложку с музыкой и шумом зала.

Каскад моделей вместо одной

Распознавание идёт на своей ноде с одной A4000, whisperX с large-v3-turbo, выравниванием по словам и диаризацией pyannote. Если нода занята или упала, задача уходит на две модели Replicate, затем на Gladia. Казахский сразу отправляется в Gladia, потому что whisperX с ним плох.

Отдельная проблема — хинди. Шаг выравнивания whisperX не может выровнять хинди-сегменты и молча их выбрасывает. Из транскрипции пропадали куски по 12–15 секунд речи, при этом в логах не было ни одной ошибки. Автор теперь считает слова на входе и выходе каждого шага.

Три способа, которыми врёт Whisper

В продакшене галлюцинации выглядят конкретно. Первая ловушка — слово-монстр: «Иииииииииииииииииииииииииии» или «pre,pre,pre,pre,pre,pre,pre» на длинных паузах, музыке и аплодисментах. Правило простое: слово длиннее 50 символов удаляется целиком.

Вторая — зацикленная фраза вроде «I love I love I love I love I love». Ловится так: берутся первые 10 символов окна и считается, сколько раз они встречаются в окне из 130 символов. Пять и больше — галлюцинация, текст уходит на чистку в LLM. Если LLM не смогла нормализовать, сегмент не озвучивается вообще и помечается в редакторе красным треугольником.

Третья, «половинчатая» ловушка — огрызки вроде «A.», «Э.», «Да.». Всё, что короче трёх символов, выкидывается, как и сегменты без спикера: диаризация не назначает спикера на [Music] и [Applause].

В последних 300 задачах en→ru флаг «галлюцинация, не озвучивать» не сработал ни разу. Автор объясняет это тем, что LLM чинит петли раньше, чем срабатывает ловушка.

Сегменты Whisper не годятся для перевода

Whisper отдаёт сегменты, которые не совпадают с границами мыслей: полтора предложения, абзац, два слова. Граница сегмента — это граница окна декодера. Переводить и озвучивать такое нельзя, потому что у фразы должны быть свои start и длительность для укладки в тайминг. Поэтому сегменты Whisper выбрасываются все.

Для профиТехнические детали: архитектура, цифры, ссылки

Стек: whisperX с large-v3-turbo, выравнивание по словам, диаризация pyannote на одной A4000. Каскад при отказе ноды: Replicate (whisper-diarization → whisperX), затем Gladia. Казахский — сразу Gladia, хинди — только faster-whisper с нативными таймкодами.

Пороги фильтрации галлюцинаций: слово длиннее 50 символов — удалить; одна подстрока пять и более раз в окне 130 символов — отдать LLM; обрывок короче трёх символов или сегмент без спикера — выкинуть. Окно было 120 символов, стало 130 в январе 2025-го.

Вопросы и ответы

Что такое галлюцинации Whisper?
Повторы и бессмысленные вставки в транскрипции: слова длиннее 50 символов, зацикленные фразы, обрывки короче трёх символов.
Как сервис speeek борется с галлюцинациями?
Слова длиннее 50 символов удаляются, повторы уходят на чистку в LLM, обрывки и сегменты без спикера выкидываются.
Почему сегменты Whisper не используются для перевода?
Их границы совпадают с окном декодера, а не с мыслями, поэтому уложить перевод в тайминг невозможно.