muscriptor-large-fork / plus /README_PLUS.md
Nokia123543's picture
чистка: убрано упоминание другого движка
41030e3 verified
|
Raw History Blame Contribute Delete
7.56 kB
# PLUS — расширение MuScriptor
Пакет пост-обработки транскрипции. Ни одна стадия не требует GPU и не трогает
веса: на вход идёт MIDI (и по желанию аудио), на выходе MIDI, WAV и отчёт.
Работает поверх любого движка: MuScriptor Large, Aria-AMT.
## Что внутри
| Файл | Что делает |
| --- | --- |
| `plus_core.py` | нотная модель, чтение/запись MIDI, темп по сетке, `explained_fraction`, `ambiguity_of` |
| `plus_transcribe.py` | стадии: cleanup, quantize, hands, pedal, chords, dynamics, report |
| `plus_ensemble.py` | слияние нескольких транскрипций голосованием + оценка P/R/F1 |
| `plus_render.py` | MIDI в WAV своим синтезатором, чтобы слушать до DAW |
| `plus_batch.py` | обработка папки, возобновление, сводка в CSV |
## Стадии
**cleanup** — унисоны (тот же питч в пределах 45 мс с перекрытием > 60 %),
фантомы (нота короче 120 мс и тише медианы на 35, включая одиночные редкие
питчи), обрезка длительности до следующей ноты того же питча.
**quantize** — посадка онсетов и длительностей на сетку 1/4 доли с силой 0..1 и
свингом. Темп берётся из файла: угадывание кратного по бинарным онсетам
математически неоднозначно, поэтому при объяснении сетки ниже 0.7 в отчёт идёт
предупреждение `tempo_ambiguous` плюс список альтернатив (`bpm/2`, `bpm*2`,
`bpm*3`), а не тихая подмена.
**hands** — правая и левая рука жадным проходом по стоимости перехода (питч плюс
время) с проверкой, что левая не уехала выше правой на октаву.
**pedal** — вывод CC64 по смене гармонии: онсеты кластеризуются в аккорды
(окно 60 мс), педаль держится пока набор высотных классов не сменился или не
истёк `max_hold` (1.6 с по умолчанию). Ноты продлеваются внутри окна, но не
дальше следующей ноты того же питча.
**chords** — аккорды по одновременным онсетам, распознавание по шаблонам
(`m`, `7`, `maj7`, `dim`, `aug`, `sus2`, `sus4`, `6`, `m6`) и подписи в отчёте.
**dynamics** — громкость из аудио: RMS в окне 250 мс от онсета, перцентильный
share, степень 0.65, множитель акцента по атаке, кривая в velocity 15..118.
Отдельный баланс рук: левая на 0.88, правая на 1.0, чтобы аккомпанемент не
перекрывал мелодию.
**report** — метрики (нот, длительность, плотность, диапазон, медиана
длительности), аномалии (перекрытия, слишком короткие, всплески плотности,
плоская громкость) и разбивка по дорожкам.
## Замеры на синтетике с известной правдой
Собрано 131 нота: мелодия восьмыми при 72 BPM плюс аккорды каждую долю, джиттер
10 мс, и три вида мусора (нота 10 мс, унисон, тихий фантом).
```
cleanup short_removed=1, unisons_merged=1, ghosts_removed=1 -> ровно 128 нот
quantize explained_before=0.992 -> explained_after=1.000, темп 72 из файла
hands left=96, right=32 (аккорды 32*3 в левой, мелодия 32 в правой)
pedal spans=31, median_hold=0.432 с
chords 32 кластера, 32 распознаны
report overlaps=0, octave_leaps=0
```
Ансамбль: три «движка» по 10 % потерянных нот и 4 фантома каждый.
```
F1 слияния 0.992 против лучшего входа 0.949 (muscriptor)
точность/полнота слияния 0.99/0.99, ошибка онсета ~10 мс
```
Скорость: пачка из трёх MIDI (включая 30 000 нот) за 1.6 с; рендер 8 секунд
звука за 0.27 с.
## Использование
```bash
# полный проход по одному файлу
python3 plus_transcribe.py --midi take.mid --audio take.wav \
--out take_plus.mid --report take_plus.json
# только ритм и руки, без громкости
python3 plus_transcribe.py --midi take.mid --stages cleanup,quantize,hands
# слияние MuScriptor + Aria и оценка против эталона
python3 plus_ensemble.py --inputs mus.mid aria.mid tk.mid \
--out merged.mid --reference truth.mid
# послушать результат
python3 plus_render.py --midi merged.mid --out merged.wav
# папка целиком, с возобновлением
python3 plus_batch.py --input-dir takes --out-dir takes_plus
```
## Ограничения, о которых честно
- Темп у бинарных онсетов неоднозначен: чистые восьмые при 72 BPM и четверти при
144 дают одинаковую сетку. Скрипт об этом пишет, а не делает вид, что знает.
- Педаль и аккорды эвристические: на плотной педали или кластерах вне мажора и
минора возможны ошибки, отчёт это показывает (`named` против `clusters`).
- `dynamics` требует ту же запись, с которой снят MIDI; перекрывающиеся ноты
делят энергию окна, поэтому громкость относительная, а не абсолютная.
- Квантование при `strength 1.0` убивает человеческое дрожание: для живой игры
держите 0.7..0.9.
## PLUS Studio — веб-интерфейс
`plus_app.py` поднимает страницу на FastAPI: загрузка аудио или MIDI, чекбоксы стадий,
ползунки силы квантования и свинга, слияние нескольких файлов, скачивание MIDI, превью WAV
и отчёта JSON. Модель грузится лениво при первом запросе, веса берутся из
`Nokia123543/muscriptor-large-fork` (или из `--weights`).
python plus_app.py --port 8900 # CPU или GPU автоматически
python plus_app.py --port 8900 --device cuda --preload --weights /content/model.safetensors
Эндпоинты: `GET /health`, `POST /transcribe` (аудио), `POST /process` (MIDI),
`POST /merge` (несколько MIDI), `GET /jobs/{id}` (состояние и лог),
`GET /jobs/{id}/result.mid|preview.wav|report.json`.