docs(diarization): зафиксированы ADR и спецификация
- Зачем: - решения карты должны стать устойчивой основой для реализации диаризации. - Что: - добавлены ADR-007 и спецификация пословной диаризации. - дополнен доменный словарь и удалены закрытые направления из backlog. - Проверка: - git diff --cached --check.
This commit is contained in:
@@ -32,6 +32,10 @@ _Avoid_: Токен, ASR-сегмент
|
|||||||
Упорядоченный набор временных интервалов речи, каждому из которых назначена анонимная метка говорящего. Не содержит распознанного текста, имени участника или голосового эмбеддинга.
|
Упорядоченный набор временных интервалов речи, каждому из которых назначена анонимная метка говорящего. Не содержит распознанного текста, имени участника или голосового эмбеддинга.
|
||||||
_Avoid_: Результат диаризации, сегменты говорящих
|
_Avoid_: Результат диаризации, сегменты говорящих
|
||||||
|
|
||||||
|
**Голосовой кластер**:
|
||||||
|
Анонимная группа интервалов разметки говорящих, которые диаризатор относит к одному голосу. Не равен подтверждённому участнику встречи: ложный или малый кластер сохраняет отдельную метку.
|
||||||
|
_Avoid_: Участник, человек
|
||||||
|
|
||||||
**Реплика говорящего**:
|
**Реплика говорящего**:
|
||||||
Последовательность соседних слов с временной привязкой, назначенных одному говорящему. Это единица структуры готового транскрипта, а не запуска модели распознавания.
|
Последовательность соседних слов с временной привязкой, назначенных одному говорящему. Это единица структуры готового транскрипта, а не запуска модели распознавания.
|
||||||
_Avoid_: Сегмент распознавания, ASR-сегмент
|
_Avoid_: Сегмент распознавания, ASR-сегмент
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# ADR-007: Пословная диаризация через sherpa-onnx
|
||||||
|
|
||||||
|
**Статус**: Принято
|
||||||
|
**Дата**: 2026-08-14
|
||||||
|
|
||||||
|
## Контекст
|
||||||
|
|
||||||
|
Разделение говорящих — главный структурный разрыв между локальным транскриптом
|
||||||
|
и облачными сервисами в сценарии подготовки конспектов и протоколов встреч.
|
||||||
|
Диаризация при этом не является ещё одним движком распознавания: она независимо
|
||||||
|
строит [разметку говорящих](../../CONTEXT.md#language), которую затем нужно
|
||||||
|
свести с результатом ASR.
|
||||||
|
|
||||||
|
Привязка одного говорящего ко всему сегменту распознавания оказалась слишком
|
||||||
|
грубой. На трёх русскоязычных рабочих созвонах чужая реплика не короче секунды
|
||||||
|
встретилась в 6–7% сегментов разговоров на двоих и в 27% сегментов встречи
|
||||||
|
втроём. Сегменты распознавания проходят по тишине, а не по смене говорящего,
|
||||||
|
поэтому сохранить контекст RNN-T и получить реплики можно только через более
|
||||||
|
мелкую единицу сведения.
|
||||||
|
|
||||||
|
## Эксперимент
|
||||||
|
|
||||||
|
Локальная связка `sherpa-onnx` с сегментацией Pyannote 3.0 и эмбеддингами
|
||||||
|
WeSpeaker ResNet34 LM проверена на трёх записях с известным составом. Для
|
||||||
|
автоматического определения числа голосовых кластеров выбран порог 0,89: это
|
||||||
|
единственное проверенное значение, которое на трёх контрольных фрагментах дало
|
||||||
|
3 / 2 / 2 кластера. На полной встрече втроём остался ложный кластер длительностью
|
||||||
|
19,1 секунды; поэтому малые кластеры нельзя молча отбрасывать, а разметку нельзя
|
||||||
|
считать эталоном точных границ и перекрывающейся речи.
|
||||||
|
|
||||||
|
На доступном слабом Intel baseline, Core i7-6820HQ с урезанным питанием,
|
||||||
|
последовательные ASR и диаризация обработали час записи примерно за 23 минуты.
|
||||||
|
Диаризация увеличивает полное время примерно в 2,4 раза, но остаётся быстрее
|
||||||
|
реального времени и приемлема как явно включаемая функция. Конкретный Core i5
|
||||||
|
11-го поколения не проверен, поскольку такого устройства нет.
|
||||||
|
|
||||||
|
Исходные данные и ограничения зафиксированы в отчётах о
|
||||||
|
[калибровке](../benchmarks/2026-08-14-diarization-calibration.md),
|
||||||
|
[смешении говорящих](../benchmarks/2026-08-14-asr-segment-speaker-mixing.md) и
|
||||||
|
[производительности на Intel](../benchmarks/2026-08-14-diarization-intel-i7.md).
|
||||||
|
|
||||||
|
## Решение
|
||||||
|
|
||||||
|
Диаризацию реализуем как явно включаемый пост-процессинг через `sherpa-onnx`.
|
||||||
|
Первая версия использует Pyannote segmentation 3.0, WeSpeaker ResNet34 LM,
|
||||||
|
порог кластеризации 0,89 и автоматическое число кластеров; известное число
|
||||||
|
участников можно передать явно.
|
||||||
|
|
||||||
|
Говорящий назначается [слову с временной
|
||||||
|
привязкой](../../CONTEXT.md#language), а не сегменту распознавания. Каждый
|
||||||
|
ASR-бэкенд приводит свой результат к общему набору слов с положением на
|
||||||
|
временной шкале. Проходы ASR и диаризации независимо получают одно аудио, после
|
||||||
|
чего отдельная операция сводит слова с интервалами разметки говорящих и
|
||||||
|
объединяет соседние слова одного говорящего в реплики. Распознавание по-прежнему
|
||||||
|
выполняется на полных сегментах и сохраняет контекст модели.
|
||||||
|
|
||||||
|
Первая реализация последовательна на всех устройствах: ASR, диаризация,
|
||||||
|
сведение, Markdown. В батче один диаризатор создаётся после prescan,
|
||||||
|
переиспользуется для всех файлов и освобождается вместе с командой. Разметка
|
||||||
|
говорящих живёт только в памяти текущего запуска; постоянного кеша результата
|
||||||
|
нет.
|
||||||
|
|
||||||
|
Грубого fallback на целый сегмент и автоматического переключения устройства
|
||||||
|
нет. Отсутствие пословных таймкодов или ошибка инициализации диаризатора
|
||||||
|
останавливают запуск до ASR. Ошибка диаризации конкретного файла после успешного
|
||||||
|
ASR не уничтожает полезный результат: сохраняется обычный транскрипт с явным
|
||||||
|
предупреждением и ненулевым статусом, а батч продолжает остальные файлы.
|
||||||
|
Подробная матрица поведения находится в
|
||||||
|
[спецификации](../specs/2026-08-14-speaker-diarization.md).
|
||||||
|
|
||||||
|
## Последствия
|
||||||
|
|
||||||
|
- Общий контракт результата распознавания расширяется каноническими словами с
|
||||||
|
временной привязкой; сегменты распознавания сохраняются для совместимости и
|
||||||
|
контроля качества.
|
||||||
|
- FasterWhisper, ONNX-ASR и OpenVINO должны экспортировать один и тот же
|
||||||
|
пословный контракт. OpenVINO GenAI 2026.x уже предоставляет нужные таймкоды,
|
||||||
|
поэтому ограничение находится в адаптере проекта, а не в движке.
|
||||||
|
- `sherpa-onnx` становится обычной runtime-зависимостью, а две модели
|
||||||
|
диаризации скачиваются и кешируются лениво при первом запросе.
|
||||||
|
- Выход остаётся линейным Markdown с анонимными метками `Speaker N`.
|
||||||
|
Сопоставление голосов с именами и специальная запись перекрывающейся речи не
|
||||||
|
входят в ядро CLI.
|
||||||
|
- Последовательный режим задаёт корректный baseline. Параллельный запуск и
|
||||||
|
автоматическое включение на мощных устройствах требуют отдельных измерений
|
||||||
|
после стабилизации.
|
||||||
|
|
||||||
|
## Отклонённые альтернативы
|
||||||
|
|
||||||
|
| Альтернатива | Почему отклонена |
|
||||||
|
|---|---|
|
||||||
|
| Не делать диаризацию | Оставляет главный продуктовый разрыв, хотя измеренная стоимость допустима для явной функции |
|
||||||
|
| Мажоритарный говорящий на весь сегмент распознавания | Теряет чужие реплики на всех трёх проверенных записях |
|
||||||
|
| Сначала диаризация, затем ASR коротких интервалов | Лишает RNN-T длинного контекста и ухудшает согласование и пунктуацию |
|
||||||
|
| `pyannote.audio` | Тянет PyTorch и требует Hugging Face token с принятием лицензии |
|
||||||
|
| Сборка поверх приватных деталей `onnx-asr` | Экономит небольшую отдельную зависимость ценой нестабильного внутреннего API и собственной кластеризации |
|
||||||
|
| Параллельные проходы в первой версии | Нет прямого benchmark и измеренного общего пика памяти; сначала нужен корректный последовательный baseline |
|
||||||
@@ -179,75 +179,6 @@ openvino-cpu, запись 25:59) с облачным сервисом Hypescrib
|
|||||||
LLM для чистки текста, сопоставление Speaker N с именами — это работа
|
LLM для чистки текста, сопоставление Speaker N с именами — это работа
|
||||||
поверх готового транскрипта.
|
поверх готового транскрипта.
|
||||||
|
|
||||||
### Диаризация — разделение говорящих
|
|
||||||
|
|
||||||
**Что:** Опциональный пост-процессинг (не четвёртый бэкенд): диаризация
|
|
||||||
даёт интервалы «кто когда говорил», результат сводится с сегментами ASR,
|
|
||||||
formatter ломает абзац на смене спикера и подписывает `Speaker 1:`.
|
|
||||||
Ставится как extra: `uv sync --extra diarization`.
|
|
||||||
|
|
||||||
**Почему:** Без спикеров MoM не собрать — это ключевой разрыв с облаком
|
|
||||||
по внешнему ревью, и никакое качество распознавания его не компенсирует.
|
|
||||||
Заодно естественно решает «разбивку на реплики» (приоритет №4).
|
|
||||||
|
|
||||||
**Промежуточный статус 2026-08-12:** проведена разведка, описанная в
|
|
||||||
[разведочном замере диаризации](benchmarks/2026-08-12-diarization-feasibility.md).
|
|
||||||
Она закрыла вопрос о движке и открыла более важный вопрос о единице привязки.
|
|
||||||
|
|
||||||
**Движок — вопрос практически закрыт.** `sherpa-onnx` ставится на Windows с
|
|
||||||
Python 3.13, содержит готовый `OfflineSpeakerDiarization`, не тянет torch и не
|
|
||||||
требует токена Hugging Face; модели сегментации и эмбеддингов весят около 33 МБ.
|
|
||||||
Скорость — 11,1× RTFx, то есть примерно полторы длительности ASR. Вариант
|
|
||||||
`pyannote.audio` остаётся отклонённым по прежней причине: torch и HF-токен с
|
|
||||||
принятием лицензии. Отдельный ADR имеет смысл заводить вместе с решением о
|
|
||||||
единице привязки, а не только про движок.
|
|
||||||
|
|
||||||
Замечание для будущих заходов: обе ML-части диаризации уже лежат в
|
|
||||||
`onnx-asr` 0.12 — `PyAnnoteVad` содержит полную локальную сегментацию pyannote
|
|
||||||
(powerset на трёх спикеров, склейка окон), а `WespeakerEmbeddings` даёт
|
|
||||||
эмбеддинги. Публичный API схлопывает сегментацию до речь/не-речь, `load_se` не
|
|
||||||
экспортирован, кластеризации нет. Собирать диаризацию самим на этих деталях —
|
|
||||||
экономия 33 МБ ценой опоры на приватный API; при разведке этот путь не
|
|
||||||
выбирался.
|
|
||||||
|
|
||||||
**Единица привязки — настоящая развилка, решения нет.** Схема «мажоритарный
|
|
||||||
спикер на весь ASR-сегмент», записанная здесь раньше, замером не подтвердилась:
|
|
||||||
27% сегментов содержат не менее секунды чужой речи, и на них приходится больше
|
|
||||||
половины времени транскрипта. Причина — границы сегментов идут по тишине
|
|
||||||
(Silero VAD), а в ВКС собеседники отвечают встык. Варианты:
|
|
||||||
|
|
||||||
- **пословная привязка** — `onnx-asr` отдаёт потокенные таймкоды
|
|
||||||
(`TimestampedResult`), сегмент режется на границе токена при смене
|
|
||||||
говорящего; ASR по-прежнему видит длинное аудио, контекст RNN-T и пунктуация
|
|
||||||
не страдают. Недоступно на OpenVINO GenAI — там потокенных таймкодов нет;
|
|
||||||
- **диаризация первым проходом**, ASR по интервалам говорящего — чистота
|
|
||||||
гарантирована, но короткие куски лишают RNN-T контекста и портят пунктуацию;
|
|
||||||
- **привязка к сегменту с честной пометкой** — оставить огрубление, но считать
|
|
||||||
чистоту и предупреждать в шапке, как уже делается для повторов и потери
|
|
||||||
хвоста.
|
|
||||||
|
|
||||||
**Уточнить перед запуском:** воспроизводится ли доля 27% на других записях,
|
|
||||||
включая разговор на двоих; правильность границ диаризации на слух, а не только
|
|
||||||
совпадение числа говорящих; калибровка порога кластеризации (на пороге из
|
|
||||||
примеров получилось 29 спикеров вместо трёх); эмбеддинги, обученные не только
|
|
||||||
на английском; производительность на целевом Intel Core i5.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Ручка нарезки абзацев в formatter
|
|
||||||
|
|
||||||
**Что:** «Минутные простыни» в транскрипте — не свойство модели, а наши
|
|
||||||
константы группировки `_PAUSE_THRESHOLD_S = 2.0` / `_MAX_PARAGRAPH_S =
|
|
||||||
60.0` в `formatter.py` (сырых сегментов много: 23-минутная запись — 360
|
|
||||||
сегментов, ~4 с на реплику). Вынести в опцию/конфиг или уменьшить
|
|
||||||
дефолт.
|
|
||||||
|
|
||||||
**Почему откладывается:** при диаризации абзацы будут ломаться по смене
|
|
||||||
спикера естественно — сначала решить с диаризацией, чтобы не делать
|
|
||||||
ручку, которая устареет.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Словарь замен технических терминов — запасной план
|
### Словарь замен технических терминов — запасной план
|
||||||
|
|
||||||
**Что:** Пост-обработка текста сегментов словарём замен по границам слов
|
**Что:** Пост-обработка текста сегментов словарём замен по границам слов
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
# Диаризация говорящих в транскрипте
|
||||||
|
|
||||||
|
## Проблема
|
||||||
|
|
||||||
|
Текущий транскрипт знает только сегменты распознавания. Их границы проходят по
|
||||||
|
тишине и не совпадают со сменой говорящего, поэтому один сегмент может содержать
|
||||||
|
несколько реплик. Назначение одной метки всему сегменту искажает структуру
|
||||||
|
диалога и делает транскрипт слабым сырьём для конспекта или протокола встречи.
|
||||||
|
|
||||||
|
[ADR-007](../adr/007-word-level-speaker-diarization.md) выбирает явную
|
||||||
|
пословную диаризацию через `sherpa-onnx`. Эта спецификация фиксирует форму первой
|
||||||
|
реализации, не меняя принятые решения.
|
||||||
|
|
||||||
|
## Цели
|
||||||
|
|
||||||
|
- По явному запросу строить реплики говорящих, сохраняя текст и длинный контекст
|
||||||
|
ASR.
|
||||||
|
- Поддержать один контракт слов с временной привязкой на FasterWhisper,
|
||||||
|
ONNX-ASR и OpenVINO.
|
||||||
|
- Сохранить предсказуемый single- и batch-режим при отсутствии речи, ошибках
|
||||||
|
диаризации и малых голосовых кластерах.
|
||||||
|
- Выдать компактный Markdown, удобный и человеку, и последующей обработке LLM.
|
||||||
|
|
||||||
|
## Не входит
|
||||||
|
|
||||||
|
- Автоматическое включение диаризации без флага и `--no-diarize`.
|
||||||
|
- Параллельный запуск ASR и диаризации.
|
||||||
|
- Сопоставление `Speaker N` с именами участников.
|
||||||
|
- Постоянный кеш разметки говорящих, голосовые эмбеддинги и диагностические
|
||||||
|
файлы.
|
||||||
|
- Отдельный синтаксис для перекрывающейся речи.
|
||||||
|
- Изменение устройства ASR или диаризации ради восстановления функции.
|
||||||
|
|
||||||
|
## Пользовательский интерфейс
|
||||||
|
|
||||||
|
- `--diarize` включает диаризацию. По умолчанию она выключена; ключ в
|
||||||
|
`.transcriber.toml` в первой версии не добавляется.
|
||||||
|
- `--speakers N`, где `N >= 1`, задаёт известное число участников и сам включает
|
||||||
|
диаризацию. Без него число кластеров определяется автоматически.
|
||||||
|
- `--threads N` остаётся единым бюджетом активного CPU-прохода. Значение целиком
|
||||||
|
получает сначала ASR, затем диаризация; `0` оставляет настройки библиотек.
|
||||||
|
- `--verbose` показывает в консоли прогресс, число кластеров и интервалов,
|
||||||
|
длительность прохода и предупреждения, но не создаёт дополнительные файлы.
|
||||||
|
- `--force` пересчитывает и ASR, и диаризацию. Без него готовый транскрипт, как и
|
||||||
|
сейчас, пропускается целиком.
|
||||||
|
|
||||||
|
`sherpa-onnx` входит в обычные runtime-зависимости. Модели
|
||||||
|
`sherpa-onnx-pyannote-segmentation-3-0` и
|
||||||
|
`wespeaker_en_voxceleb_resnet34_LM.onnx` скачиваются и кешируются лениво при
|
||||||
|
первом запросе диаризации. Отдельного installation extra нет.
|
||||||
|
|
||||||
|
## Контракты данных
|
||||||
|
|
||||||
|
Результат ASR сохраняет существующие сегменты распознавания и дополнительно
|
||||||
|
содержит упорядоченные канонические слова. Для каждого слова известны текст,
|
||||||
|
начало и конец на временной шкале исходной записи. Backend-специфичные токены и
|
||||||
|
слова нормализуются в адаптере бэкенда; их обратная сборка должна сохранять
|
||||||
|
распознанный текст с точностью до нормализации пробелов.
|
||||||
|
|
||||||
|
Результат диаризации — отдельная упорядоченная разметка говорящих: временные
|
||||||
|
интервалы с анонимным идентификатором голосового кластера. ASR-бэкенд не знает о
|
||||||
|
кластерах, а диаризатор не знает о распознанном тексте.
|
||||||
|
|
||||||
|
Операция сведения назначает слову кластер с наибольшим временным перекрытием.
|
||||||
|
Если пересечения нет либо наибольшее перекрытие не единственно, слово получает
|
||||||
|
неизвестного говорящего. Соседние слова одного говорящего объединяются в
|
||||||
|
реплику; порядок слов и исходная временная шкала не меняются.
|
||||||
|
|
||||||
|
Все три ASR-пути обязаны предоставлять пословный контракт до включения
|
||||||
|
диаризации:
|
||||||
|
|
||||||
|
| Путь | Источник временных привязок |
|
||||||
|
|---|---|
|
||||||
|
| FasterWhisper | word timestamps CTranslate2 |
|
||||||
|
| ONNX-ASR | timestamped result модели |
|
||||||
|
| OpenVINO | word-level timestamps `WhisperPipeline` |
|
||||||
|
|
||||||
|
Грубая подстановка метки на весь сегмент распознавания запрещена.
|
||||||
|
|
||||||
|
## Пайплайн и время жизни
|
||||||
|
|
||||||
|
После prescan и только при наличии файлов для обработки загружаются ASR-модель
|
||||||
|
и один batch-owned диаризатор. До первого ASR проверяются доступность пословных
|
||||||
|
таймкодов, модели диаризации и возможность создать диаризатор. Ошибка этого
|
||||||
|
этапа останавливает весь запуск без частичных транскриптов.
|
||||||
|
|
||||||
|
Каждый файл обрабатывается последовательно:
|
||||||
|
|
||||||
|
1. ASR;
|
||||||
|
2. диаризация, если ASR нашёл речь;
|
||||||
|
3. сведение слов с разметкой говорящих;
|
||||||
|
4. форматирование и запись Markdown.
|
||||||
|
|
||||||
|
Один диаризатор последовательно переиспользуется для всех файлов батча. Данные
|
||||||
|
конкретной записи не становятся состоянием следующей. Объект освобождается при
|
||||||
|
завершении команды и не переносится через `TranscribeFileResult`.
|
||||||
|
|
||||||
|
Разметка говорящих хранится только до сведения. Единственный постоянный
|
||||||
|
продуктовый артефакт — Markdown-транскрипт; локальный кеш файлов моделей живёт
|
||||||
|
по существующим правилам загрузчиков.
|
||||||
|
|
||||||
|
## Конфигурация диаризации
|
||||||
|
|
||||||
|
Автоматический режим использует:
|
||||||
|
|
||||||
|
- Pyannote segmentation 3.0;
|
||||||
|
- WeSpeaker ResNet34 LM;
|
||||||
|
- `FastClusteringConfig.threshold = 0.89`;
|
||||||
|
- автоматическое число кластеров.
|
||||||
|
|
||||||
|
`--speakers N` передаёт явное число кластеров вместо автоматического. Малый
|
||||||
|
кластер — кластер с речью короче максимума из 5 секунд и 2% длительности записи.
|
||||||
|
Он не отбрасывается и получает обычный номер, но вызывает предупреждение.
|
||||||
|
|
||||||
|
## Формат Markdown
|
||||||
|
|
||||||
|
При двух и более найденных кластерах тело состоит из линейных реплик:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
[09:07] Speaker 1: Мы же у них не разворачиваемся…
|
||||||
|
|
||||||
|
[09:18] Speaker 2: Мне гораздо проще накатывать обновления…
|
||||||
|
```
|
||||||
|
|
||||||
|
- Печатается только начало реплики, округлённое до целой секунды. Для записей
|
||||||
|
длиннее часа используется `[HH:MM:SS]`, иначе `[MM:SS]`.
|
||||||
|
- Метка `Speaker N` не получает Markdown-выделение.
|
||||||
|
- Нумерация начинается заново для каждого файла; номера назначаются по порядку
|
||||||
|
первого появления кластера в словах транскрипта.
|
||||||
|
- Смена говорящего всегда начинает новую реплику.
|
||||||
|
- Речь одного говорящего дополнительно разбивается по паузе не меньше 2 секунд
|
||||||
|
и максимальной длительности реплики 60 секунд.
|
||||||
|
- Слова без назначенного кластера группируются под `Speaker ?`.
|
||||||
|
- Перекрывающаяся речь остаётся в хронологическом порядке без особого
|
||||||
|
синтаксиса.
|
||||||
|
- В шапку добавляется число голосовых кластеров и предупреждения. Таблица
|
||||||
|
длительности по кластерам не выводится.
|
||||||
|
|
||||||
|
Без успешной разметки нескольких говорящих сохраняется нынешний формат
|
||||||
|
обычного транскрипта с диапазонами времени.
|
||||||
|
|
||||||
|
## Деградация и статус команды
|
||||||
|
|
||||||
|
| Ситуация | Артефакт | Консоль и шапка | Статус |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Диаризация не запрошена | Обычный транскрипт | Без новых сообщений | Текущий |
|
||||||
|
| ASR не нашёл речь | Текущий пустой Markdown | Речь не обнаружена; диаризация не запускалась | 0 |
|
||||||
|
| Найдено не меньше двух кластеров | Транскрипт с `Speaker N` | Число кластеров и предупреждения | 0, если нет иной ошибки |
|
||||||
|
| Найден один кластер | Обычный транскрипт без `Speaker 1` | Причина в консоли и шапке | Ненулевой |
|
||||||
|
| Есть слова без пересечения | Транскрипт с `Speaker ?` | Число таких слов | 0 |
|
||||||
|
| Есть малый кластер | Транскрипт со всеми кластерами | Длительность малого кластера | 0 |
|
||||||
|
| Разметка пуста при непустом ASR | Обычный транскрипт | Явное предупреждение | Ненулевой |
|
||||||
|
| Ошибка диаризации конкретного файла | Обычный транскрипт | Явное предупреждение | Ненулевой |
|
||||||
|
| Нет пословных таймкодов или не инициализировался диаризатор | Файлы не обрабатываются | Понятная ошибка до ASR | Ненулевой |
|
||||||
|
|
||||||
|
В батче деградированный файл записывается, учитывается как неуспешная
|
||||||
|
диаризация, а остальные файлы продолжают обрабатываться. Итоговый статус батча
|
||||||
|
ненулевой, если хотя бы один файл деградировал или завершился ошибкой.
|
||||||
|
|
||||||
|
## Критерии приёмки
|
||||||
|
|
||||||
|
### Автоматические проверки
|
||||||
|
|
||||||
|
- Адаптер каждого ASR-бэкенда возвращает монотонные слова с временной
|
||||||
|
привязкой; сборка слов сохраняет текст сегментов с точностью до пробелов.
|
||||||
|
- Сведение покрывает смену говорящего, отсутствие пересечения, равное
|
||||||
|
перекрытие, пунктуацию на границе реплик и хронологический порядок.
|
||||||
|
- Форматтер проверяется для обычных, часовых, неизвестных и малых кластеров,
|
||||||
|
`Speaker ?`, паузы 2 секунды и предела 60 секунд.
|
||||||
|
- CLI проверяет несовместимые и граничные значения, не запускает ASR при ошибке
|
||||||
|
preflight и соблюдает всю матрицу деградации в single- и batch-режимах.
|
||||||
|
- Батч создаёт диаризатор ровно один раз, пропускает его для пустого ASR,
|
||||||
|
переиспользует между файлами и не пишет промежуточный кеш.
|
||||||
|
- `--threads`, `--verbose` и `--force` сохраняют описанную семантику.
|
||||||
|
|
||||||
|
Все автоматические тесты мокают движки и не скачивают реальные модели.
|
||||||
|
|
||||||
|
### Ручная проверка
|
||||||
|
|
||||||
|
Финальная сборка прогоняется на трёх записях из отчётов карты:
|
||||||
|
|
||||||
|
- текст до и после сведения совпадает с точностью до переносов и пробелов;
|
||||||
|
- на плотном диалоге вручную проверяются устойчивость «голос → кластер», смены
|
||||||
|
говорящего, пропуски, малый остаточный кластер и перекрывающаяся речь;
|
||||||
|
- автоматическая конфигурация воспроизводит наблюдённую форму результата:
|
||||||
|
три основных и один малый остаточный кластер на Data Test, по два кластера на
|
||||||
|
T2 BDMA и Yantar;
|
||||||
|
- последовательный прогон на доступном Intel baseline остаётся быстрее
|
||||||
|
реального времени; фактические wall time и peak RSS записываются рядом с
|
||||||
|
результатом проверки.
|
||||||
|
|
||||||
|
## Документация
|
||||||
|
|
||||||
|
README должен описать новые CLI-флаги, ленивую загрузку моделей, ожидаемую
|
||||||
|
стоимость, формат `Speaker N`, предупреждения и batch-поведение. Направления
|
||||||
|
«Диаризация» и «Ручка нарезки абзацев» удаляются из backlog: первое перешло в
|
||||||
|
эту спецификацию, второе закрыто разрывом реплики на смене говорящего.
|
||||||
|
|
||||||
|
После стабилизации отдельно рассматриваются
|
||||||
|
[параллельный запуск](https://git.dementev.space/ddmitry/local-transcriber/issues/22)
|
||||||
|
и [hardware-aware default](https://git.dementev.space/ddmitry/local-transcriber/issues/23).
|
||||||
Reference in New Issue
Block a user