Галлюцинации Whisper: почему он повторяет строки и выдумывает текст
Галлюцинации Whisper: почему он пишет «Thank you for watching» на тишине или зацикливает одну строку, чем обходится каждое исправление и как найти их в SRT.
Галлюцинации Whisper (англ. Whisper hallucinations) — это текст, который модель пишет, хотя его никто не произносил: «Thank you for watching» на тишине, строка с авторами субтитров или одна и та же фраза, повторяющаяся целую минуту. Большинство таких случаев предотвращают две настройки: фильтр, отсекающий звук без речи, и отказ от опоры модели на собственный предыдущий вывод. Но в стандартных инструментах Whisper по умолчанию не включена ни одна из них.
Дальше — оба вида рядом, почему возникает каждый, что мы измерили, когда один из них добрался до нашего собственного приложения, чем обходится каждое исправление, настройки для openai-whisper, faster-whisper и whisper.cpp и как найти уцелевшие галлюцинации в готовом файле субтитров.
Галлюцинации Whisper в сравнении
| Фантомная фраза | Петля повторов | Пропущенная речь | |
|---|---|---|---|
| Что вы видите | «Thank you for watching», «Thanks for watching», строка с авторами субтитров | Одна строка, написанная снова и снова, часто без пунктуации | В транскрипте нет предложения |
| Где появляется | Тишина, музыка, аплодисменты, шум помещения | Где угодно; начавшись, продолжается | Тихое начало, короткие междометия |
| Чем вызвана | Звук без речи попадает в декодер | Каждое окно декодируется с предыдущим выводом в качестве подсказки | Тем, как конкретная модель обрабатывает этот звук |
| Первое исправление | Фильтр обнаружения речи (VAD) | Отключить опору на предыдущий текст | Попробовать вторую модель на том же клипе |
| Как проявляется в субтитрах | Лишняя реплика на паузе | Реплика, застрявшая на одной строке, или реплики без разбивки на предложения | Провал там, где должна быть строка |
Третий столбец — обратный сбой: речь, которую пропустили, а не текст, который выдумали. У него другие причины и другие способы исправления, они разобраны в сравнении моделей Whisper. Всё остальное ниже — про первые два вида.
Почему Whisper пишет текст, которого никто не говорил?
Whisper обрабатывает звук окнами по 30 секунд, и его декодер пишет текст для каждого окна. Проверка на отсутствие речи есть, но это лишь порог по вероятности, и окна с музыкой, аплодисментами или фоном помещения регулярно её проходят и превращаются в слова. Выбор слов выдаёт причину. Whisper обучали на 680 000 часов звука из интернета вместе с транскрипциями. Обычно то, что он пишет, когда транскрибировать нечего, объясняют именно этим: в таких текстах часто встречаются прощальные фразы и строки с авторами субтитров.
Цифры немалые. В исследовании 2025 года учёные из AGH University of Kraków прогнали large-v3 по звуку без речи — шуму, музыке, звукам окружающей среды — 301 317 раз. Текст появился в 40,3% случаев, а 9,1% этих галлюцинаций оказались петлями. Чаще всего выдавались «thank you» — 24,76% галлюцинаций — и «thanks for watching» — 10,32%.
На реальной речи доля гораздо ниже, зато вред больше. Исследование 2024 года Careless Whisper показало: примерно в 1% транскрипций встречались целые фразы или предложения, которых в звуке не было; в 38% таких случаев содержался явный вред — например, воспроизводство насилия, выдуманные связи или намёк на ложный авторитет, — а непропорционально часто это происходило с говорящими, которые делают долгие паузы.
Для субтитров цена вполне конкретна. Галлюцинация приходит безупречно оформленной репликой на паузе, и зритель читает её как диалог.
Почему одна плохая строка превращается в сорок
У петли другая причина. По умолчанию Whisper декодирует каждое окно, используя собственный предыдущий вывод как подсказку, так что контекст переходит из окна в окно: имена пишутся одинаково, предложения продолжаются. Но та же возможность позволяет одному плохому окну отравить следующее. Стоит декодеру написать строку дважды, как следующее окно получает её как затравку и пишет снова. В документации faster-whisper к condition_on_previous_text об этом сказано прямо: если опору на предыдущий текст выключить, модель «становится менее склонной застревать в цикле сбоя, например в зацикливании повторов или рассинхронизации временных меток».
Мы столкнулись с этим в собственном приложении до релиза и поэтому измерили: тот же 101-секундный турецкий клип, что и в нашем сравнении моделей, на RTX 3060 Ti с float16, при этом менялась только одна опция — опора на предыдущий текст.
large-v3, опора включена | large-v3, опора выключена | medium, опора включена | medium, опора выключена | |
|---|---|---|---|---|
| Знаков конца предложения в транскрипте | 0 | 30 | 47 | 30 |
| Повторяющиеся фразы (6-граммы) | 9 | 0 | 0 | 0 |
Настройка по умолчанию сломала large-v3 и ничего не изменила для medium. При включённой опоре большая модель не поставила ни одного знака конца предложения и выдала девять повторяющихся фраз; меньшая на том же звуке с теми же настройками отработала нормально. В одном из прогонов в единственной реплике оказалось вот это — на 0,12 секунды звука:
[58.26 -> 58.38] bir level oldu bir level oldu bir level oldu bir level oldu
bir level oldu bir level oldu bir level oldu bir level oldu
Отсутствие пунктуации важно не меньше, чем повторы. Инструменты для субтитров режут транскрипт на реплики по границам предложений, а у транскрипта без точек им не за что зацепиться: получаются гигантские реплики или — при небрежном разделителе строк — однословные. Выключение опоры вернуло пунктуацию, не меняя модель.
Один клип — это не бенчмарк. Но он показывает две вещи: размер модели не защищает, а самое дешёвое исправление — это настройка.
Есть ли цена у отключения опоры на предыдущий текст?
Есть. У каждого способа борьбы с галлюцинациями есть своя цена, и знать её стоит до того, как вы его примените:
- Согласованность между окнами. Без предыдущего текста как контекста написание и стиль пунктуации могут «плыть»: документация предупреждает, что отключение опоры «может сделать текст несогласованным между окнами». На практике это имя, записанное двумя способами в длинном файле.
- Initial prompt (начальная подсказка) действует только на первое окно. Инструменты передают Whisper список слов — имена, бренды, жаргон — как initial prompt, и при выключенной опоре на предыдущий текст он влияет лишь на первое окно. Параметры
--carry_initial_prompt Trueв openai-whisper и--carry-initial-promptв whisper.cpp отправляют его заново для каждого окна; в faster-whisper эту работу выполняет опцияhotwords. - Штрафы за повторы удаляют настоящие повторы.
repetition_penaltyиno_repeat_ngram_sizeподавили бы петлю, но не отличают её от говорящего, который повторяется сам. В нашем тестовом клипе есть именно такой случай: одно предложение, сказанное дважды подряд, намеренно. Штраф, который его убирает, удаляет часть диалога. - Фильтр обнаружения речи может обрезать тихую речь. VAD решает, что считать речью, ещё до того, как Whisper её услышит, и пропускает слова в тихом начале фраз и в звуке с ограниченной полосой частот, например в телефонных разговорах. В сентябре 2026 года в AutoSubs появился переключатель, отключающий пропуск тишины, — именно для такого случая.
hallucination_silence_thresholdтребует пословных временных меток и не является панацеей. Он пропускает длинные паузы вокруг предполагаемой галлюцинации. На нашем клипе заметной разницы не дал: строка, которую мы подозревали в выдумке, оказалась настоящей речью.
Ни одна из этих цен не сравнится с ценой петли. Неверно написанное имя — это одна замена через «найти и заменить»; петля повторов — это отрывок, который приходится транскрибировать заново.
Как остановить галлюцинации Whisper: инструмент за инструментом
| openai-whisper | faster-whisper | whisper.cpp | Sablate | |
|---|---|---|---|---|
| Фильтр обнаружения речи | Встроенного нет | vad_filter=True, по умолчанию включён только в пакетном конвейере | --vad с моделью Silero | Всегда включён |
| Отключить опору на предыдущий текст | --condition_on_previous_text False | condition_on_previous_text=False | -mc 0 | Всегда отключена |
| Пропускать тишину после предполагаемой галлюцинации | --hallucination_silence_threshold | hallucination_silence_threshold | Аналога нет | Нет |
| Отправлять подсказку заново в каждом окне | --carry_initial_prompt True | hotwords | --carry-initial-prompt | Нет |
| Эти настройки можно менять | Да | Да | Да | Нет |
Последние три строки — честное слабое место Sablate: оба исправления всегда включены, и ни одна из этих настроек не вынесена в интерфейс. Если вы хотите настроить фильтр или переносить подсказку между окнами, это позволяют сделать инструменты с открытым кодом.
Для openai-whisper на файле с интервью:
whisper talk.mp4 --model turbo --output_format srt --condition_on_previous_text False
У openai-whisper нет собственного фильтра обнаружения речи, поэтому эта команда устраняет петлю, но не фантомные фразы; частичный ответ на них — --hallucination_silence_threshold вместе с --word_timestamps True. В whisper.cpp есть оба исправления, а его консольная утилита ожидает 16-битный WAV:
ffmpeg -i talk.mp4 -ar 16000 -ac 1 -c:a pcm_s16le talk.wav
./build/bin/whisper-cli -m models/ggml-large-v3-turbo.bin -f talk.wav -osrt -mc 0 --vad -vm models/ggml-silero-v6.2.0.bin
-mc 0 не сохраняет текстовый контекст между окнами, а модель Silero скачивается скриптом download-vad-model.sh из репозитория. В Python faster-whisper принимает оба параметра в виде аргументов:
from faster_whisper import WhisperModel
model = WhisperModel("large-v3-turbo")
segments, info = model.transcribe("talk.mp4", vad_filter=True, condition_on_previous_text=False)
Как найти галлюцинации в готовом файле SRT?
Ни одна настройка не убирает все галлюцинации, поэтому файл нужно проверять. Три команды ловят большинство уцелевших галлюцинаций — в macOS и Linux либо в Git Bash и WSL в Windows:
grep -n -i -E "thank(s| you) for watching|amara\.org|subtitles by" talk.srt
awk '{ sub(/\r$/, "") } NF && !/-->/ && !/^[0-9]+$/ { if ($0 == prev) print NR": "$0; prev = $0 }' talk.srt
perl -ne 'print "$.: $_" if /(\S+(?: \S+){1,4}) \1 \1/' talk.srt
Первая находит дежурные прощальные фразы и строки с авторами субтитров. Вторая выводит любую строку субтитров, совпадающую с предыдущей: именно так обычно выглядит петля после нарезки на реплики. Третья ловит фразу из двух–пяти слов, повторённую трижды внутри одной строки.
Относитесь к каждому совпадению как к вопросу, а не как к приговору. Люди действительно говорят «thank you» и действительно повторяются. Сверьте реплику со звуком, затем оставьте её или удалите. Фантомные строки на долгих паузах и музыке не подчиняются никакому шаблону; единственная проверка для них — прочитать реплики, которые приходятся на участки без речи.
Какое исправление выбрать
«Я делаю субтитры к докладам, интервью или лекциям». Включите фильтр обнаружения речи и отключите опору на предыдущий текст. Эта пара — разумная настройка по умолчанию для любой речи, к которой вы собираетесь делать субтитры.
«В записи долгие паузы или музыкальная подложка». Здесь фильтр важнее всего. Всё равно прочитайте реплики поверх музыки.
«Это телефонный разговор или тихая запись с ограниченной полосой». Прогоните запись дважды — с фильтром и без — и сравните, чего не хватает. Фильтр, который теряет тихие слова, хуже случайного «thank you».
«Я полагаюсь на initial prompt для имён». Отключите опору на предыдущий текст и отправляйте подсказку заново в каждом окне с помощью флагов выше либо исправьте имена потом через «найти и заменить».
«Строки всё равно повторяются после обоих исправлений». Прежде чем браться за штраф за повторы, попробуйте другую модель на том же файле: на нашем клипе петля возникла у large-v3, а у medium — нет. Если no_repeat_ngram_size всё же нужен, прослушайте запись целиком, чтобы найти строки, которые он мог удалить.
Как с этим справляется Sablate
В Sablate оба исправления всегда включены: перед моделью стоит фильтр обнаружения речи, а опора на предыдущий текст отключена. Sablate запускает Whisper на вашем компьютере, а опору мы выключили после описанного выше измерения. Кроме того, мы исправили разделитель строк, который превращал транскрипт без пунктуации в однословные реплики.
Стоит знать о двух следствиях. Пользовательский словарь в Defaults → Custom vocabulary попадает в Whisper как initial prompt, поэтому при отключённой опоре на предыдущий текст он влияет только на первое окно — примерно на первые 30 секунд речи; имена из более поздних частей длинной записи — работа для функции Find & replace в редакторе, которая применяется к одному языку за раз. А раз настройки зафиксированы, подстраивать нечего. Если записи нужен выключенный фильтр, воспользуйтесь одним из инструментов с открытым кодом, перечисленных выше.
В редакторе можно пройтись по репликам, пока идёт видео, — это самый быстрый способ оценить совпадения, найденные командами выше, — а экспорт записывает исправленные субтитры в .srt, .vtt или в видео с вшитыми субтитрами. Fast и Balanced работают на бесплатном тарифе; Accurate и Best входят в Pro. Скачайте Sablate для Windows или Mac и попробуйте на своём материале.
Коротко
Whisper галлюцинирует двумя способами: пишет дежурные фразы на звуке без речи и зацикливается, когда одно плохое окно питает следующее. Фильтр обнаружения речи устраняет первое, отключение condition_on_previous_text — второе, а в стандартных инструментах не включено ни то, ни другое. Оба исправления стоят мало по сравнению с петлёй. Более крупная модель не значит более надёжная. И что бы вы ни меняли, прочитайте готовый файл субтитров раньше, чем это сделает кто-то другой, — проверки самого формата есть в руководстве по созданию SRT-файлов.