# Восстановление речи из исходника

`audio_fx.py` применяет **стиль** — цепочку, после которой голос звучит как
подкаст, телефон или мегафон. `voice_restore.py` делает шаг до этого: смотрит,
что именно не так с записью, и чинит только это.

```bash
python scripts/voice_restore.py source.mp4 --measure-only     # диагноз без рендера
python scripts/voice_restore.py source.mp4 source_clean.mp4   # применить
```

Видео копируется без перекодирования. Громкость здесь **не** нормализуется — это
делает `audio_fx.py` одним последним проходом.

## Что измеряется

Уровень считается на окне 1024 отсчёта (~21 мс) — это разрешение слога. Спектр
считается на окне 8192 (~5.9 Гц на бин) отдельно, и это не придирка: на 1024
точках бин шириной 47 Гц, поэтому третьоктавная полоса 125 Гц (111–140 Гц) **не
содержит ни одного бина** и читается как тишина, а пик сети 50 Гц неотличим от
соседей. На такой сетке диагноз показывает −200 дБ в басу и никогда не находит
наводку.

| Величина | Как получена |
|---|---|
| уровень речи / шумовой пол | 92-й и 8-й процентиль огибающей. Не фиксированный порог: у тихой и громкой записи разные абсолютные уровни, а важен раздел **внутри этого файла**. |
| сетевая наводка | Пик на 50/60 Гц и гармониках против медианы своего окружения ±25 Гц. Гармоника — это игла, а не холм; фильтром высоких частот её не убрать, потому что третья гармоника живёт внутри мужского голоса. |
| тональный баланс | Отклонение от долговременного среднего спектра речи (LTASS), подогнанного по 315–3150 Гц. Ноль означает «как у речи», знак говорит, куда двигать. |
| полезная полоса | Самая высокая третьоктавная полоса в пределах 12 дБ от эталона. |
| хвост комнаты | Медианный спад уровня за 250 мс после окончания фразы. |
| клиппинг | Доля отсчётов выше 0.985. |

## Почему LTASS, а не отношение полос

Первая версия сравнивала суммарную энергию полос: 200–380 Гц против 300–3400 Гц.
Это заявление о ширине полос, а не о тембре — в речевой полосе в пятнадцать раз
больше бинов, поэтому «коэффициент бубнения» выдавал одно и то же число для
гулкой комнаты и сухой кабины. Сравнение с эталонной кривой речи даёт величину,
у которой есть смысл: **на сколько децибел этот голос отличается от того, как
речь звучит вообще**. Именно такую величину и должен исправлять эквалайзер.

Остаток в пределах ±2.5 дБ — это разброс между людьми, а не дефект. Выравнивать
его — значит стирать тембр говорящего.

## Что делает цепочка

Каждый шаг в отчёте подписан числом, которое его вызвало, а пропущенный шаг —
числом, из-за которого он не понадобился. Шаг, применённый «потому что так
принято», не применяется.

Порядок: восстановление формы (declip) → срез низа → вырезание наводки →
широкополосное шумоподавление по **измеренному** профилю → снятие комнатной
бубнящей полки → полоса согласных → де-эссер → воздух → мягкая экспансия пауз →
двухступенчатое выравнивание → потолок.

Шумоподавителю передаётся настоящий шумовой пол в дБFS. Разница между
`nf=-25` наугад и измеренным значением — это разница между прозрачным проходом и
голосом, который плавает.

Де-эссер применяется, **только** если запись действительно шипит. Наложенный
вслепую, он делает глухим голос, с которым всё было в порядке.

## Проверка результата

Отчёт сравнивает диагноз до и после. На реальном телефонном исходнике:

```
SNR            25.2 → 38.3 дБ   (+13.1)
шумовой пол   −42.0 → −56.6 дБFS
бубнение       +7.6 → +4.5 дБ
согласные      −9.9 → −5.9 дБ
```

Если SNR **не вырос**, скрипт предупреждает: скорее всего, за шум принято
дыхание близкого микрофона. Тогда снижай `--strength`, а не повышай его.
