NeMo: как подготовить manifest и проверить диаризацию в RTTM
Кластерная диаризация NeMo: JSONL с путями аудио, короткая проба и чтение RTTM без путаницы между длительностью и концом реплики.
Выберите один путь обработки и зафиксируйте версию
Диаризация строит интервалы, на которых звучат разные говорящие. Она полезна, когда редактору нужно проверить смены участников в длинной записи. Сам по себе результат не содержит всех произнесённых слов и не устанавливает личность человека.
В NeMo есть разные системы диаризации. Ниже рассматривается кластерный пример offline_diar_infer.py с конфигурацией diar_infer_meeting.yaml, проверенной в официальных исходниках на 3 октября 2026 года. Команды другого пути, например Sortformer или MSDD, не следует переносить в него без проверки совместимости.
Инструкция рассчитана на уже подготовленную среду NeMo Speech и соответствующее ей дерево примеров. Запишите версию пакета и ревизию исходников. Загрузка моделей может требовать сети; скорость и доступная длина записи зависят от вашей среды. Выполнение нейросетевой обработки в рамках этой статьи не проводилось.
Начните с короткого фрагмента, где есть смена голоса, тихий ответ и перебивание. Проверка расшифровки по записи остаётся отдельным этапом: правильные слова не доказывают правильность меток участников, и наоборот.
Создайте manifest с понятными путями
Manifest для вывода подают в формате JSONL: каждый объект помещается на отдельной строке. Для одного файла достаточно одной строки. Не оборачивайте несколько записей в общий JSON-массив, если выбранный пример ожидает построчное чтение.
Обязательное audio_filepath содержит абсолютный путь к аудио. В учебной заготовке /work/audio/demo01.wav нужно заменить на существующий файл в вашей среде. Сохраните manifest вне папки вывода и проверьте его чтение до запуска моделей.
В примере offset равен нулю, duration — null: обрабатывается файл с начала без явно заданного ограниченного участка. Не путайте duration с временем конца. Если готовите отдельную аудиопробу, дайте ей собственное имя и сохраните карту её положения в исходной записи.
Неизвестное число участников задаётся null. Эталонный RTTM для оценки качества — самостоятельная ручная разметка, а не будущий путь сохранения предсказания. Если эталона нет, оставьте rttm_filepath и uem_filepath null. Не выдавайте вывод модели за разметку, с которой эта же модель сравнивается.
Запустите короткую пробу и сохраните её настройки
Из корня совместимого дерева NeMo Speech выполните заготовку ниже, заменив пути на свои. Параметр manifest_filepath указывает входной список, out_dir — отдельную папку результата. В официальном проверенном примере по умолчанию используется конфигурация встреч с моделями VAD и TitaNet; это исходная точка пробы, а не обещание одинакового качества на любых записях.
Пример запуска для подготовленной среды:
python examples/speaker_tasks/diarization/clustering_diarizer/offline_diar_infer.py \ diarizer.manifest_filepath=/work/input/manifest.jsonl \ diarizer.out_dir=/work/output/demo01 \ diarizer.oracle_vad=False \ diarizer.speaker_embeddings.parameters.save_embeddings=False
oracle_vad=False означает, что вы не используете эталонные интервалы речи из RTTM в качестве готового VAD. Сохранение embeddings отключено в этой заготовке, но сам вывод и журнал запуска всё равно нужно проверить. Если скрипт или ключ отсутствует в вашей версии, сравните её официальный пример с командой, а не добавляйте неизвестные параметры наугад.
При ошибке сначала разделите причины: доступен ли файл, читается ли manifest, найдены ли модели, хватает ли ресурсов. Успешная загрузка модели ещё не означает завершённую обработку. Дождитесь окончания запуска и найдите результат, относящийся именно к demo01.
Читайте RTTM как интервалы, а не как готовую стенограмму
В строке RTTM типа SPEAKER после идентификатора записи и канала идут начало и длительность участка в секундах. Конец вычисляют сложением. Учебная строка с началом 12.5 и длительностью 2.0 описывает интервал до 14.5, а не до 2.0 секунды.
Пример вымышленной строки:
SPEAKER demo01 1 12.500 2.000 <NA> <NA> speaker_0 <NA> <NA>
Прослушайте этот интервал и сравните его с соседними. Проверьте, не объединились ли два человека в одну метку и не разделился ли один голос на несколько меток после паузы. Короткие подтверждения и речь одновременно с другим участником требуют особого внимания.
Не складывайте длительности всех участников как длительность встречи: при перекрытии интервалы могут пересекаться. Метка speaker_0 относится к результату конкретной записи; такой же номер в другом файле не подтверждает того же человека. Имена присваивайте только по проверяемому контексту, оставляя сомнительные случаи неизвестными.
Сопоставьте интервалы с текстом и сохраните проверку
Чтобы получить читаемое содержание, можно отдельно расшифровать аудио в Транскрибаторе. Сверяйте текст и интервалы по одной и той же версии записи. В этой инструкции не обещается автоматическое объединение результата сервиса с NeMo или импорт RTTM.
Для ручного сопоставления заведите таблицу: начало, конец, метка, фраза, результат прослушивания. Если слово попадает в пограничный или перекрывающийся участок, не назначайте говорящего только по ближайшей цифре. Прослушайте контекст и отметьте неопределённость, если запись не позволяет уверенно решить вопрос.
Перед длинным запуском оцените короткую пробу по реальным ошибкам: пропущенная тихая речь, лишние интервалы на шуме, перепутанные участники. Меняйте один параметр за раз и сохраняйте обе версии. Не называйте процент точности без эталонной разметки и явно описанного способа измерения.
Архив по проектам дополните manifest, версией конфигурации, RTTM и журналом ручной проверки. Храните исходный прогноз отдельно от исправленного. Тогда можно восстановить причины правок и понять, какой результат использован в итоговом документе.
Начало плюс длительность даёт конец
Учебные интервалы вымышлены. Первый участник говорит с 12.5 секунды в течение 2 секунд, второй — с 14 секунды в течение 1.5 секунды. Сумма длительностей 3.5 секунды не равна длине общего участка: полсекунды голоса перекрываются.
| Учебная запись | Интервал | Проверка |
|---|---|---|
| speaker_0: start=12.5, duration=2.0 | 12.5–14.5 | Один голос, целая реплика |
| speaker_1: start=14.0, duration=1.5 | 14.0–15.5 | Перекрытие с предыдущим 0.5с |
| Новая запись: speaker_0 | Другой файл | Имя не переносится автоматически |
| Ручное исправление метки | Отдельная версия RTTM | Сохранён исходный прогноз |
Редактор проверяет перекрытие 14.0–14.5 отдельно и не назначает все слова одному участнику автоматически. Таблица различает прогноз модели и ручное заключение по звуку; неопределённость не заменяется придуманным именем.
Учебная строка manifest.jsonl
{"audio_filepath": "/work/audio/demo01.wav", "offset": 0, "duration": null, "label": "infer", "text": "-", "num_speakers": null, "rttm_filepath": null, "uem_filepath": null}Частые вопросы
JSONL и JSON-массив одинаковы?
Для описанного manifest каждый объект располагается на отдельной строке. Общий массив не заменяет ожидаемый построчный формат.
В rttm_filepath указывать путь будущего вывода?
В описании входного manifest это путь эталонной разметки для оценки. Если её нет, используйте null; папка результата задаётся отдельно через out_dir.
Диаризация распознаёт слова?
Рассмотренный путь строит интервалы говорящих. Получение и проверка текста выполняются отдельно.
speaker_0 — это один человек во всех файлах?
Номер относится к конкретному результату. Между записями идентичность автоматически из него не следует.
Как вычислить конец участка RTTM?
Сложите начало и длительность: 12.5 + 2.0 = 14.5 секунды. Затем проверьте границы по аудио.