VEU.WathBody/1-docs/4-modules/m11-voice-input/module_reqs.md

133 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Требования к модулю: m11-voice-input
> Модуль — **VoiceInput** телефона `Phone.WatchBody` (архитектура
> разд. 1.2): офлайн-STT Vosk + грамматика команд Ф-1.2 + TTS-подтверждения
> + интеграция в экран «Тренировка» (m10) поверх ядра m09. Самодостаточная
> копия требований (d-dev-6). Источники: Ф-1, Ф-3.3 (таймер), Ф-13.3
> («РПЭ N»), открытый вопрос 2 (закрыт шагом 5: Vosk, малая ru-модель,
> TTS — системный Android), tech-req 4.1/5 (`VoiceInput`, модель ~50 МБ,
> постобработка чисел), 7 п. 3 (прототип точности), ui-ux разд. 3.
## 1. Назначение и границы
Голосовой офлайн-учёт подходов: атлет на экране активной тренировки
включает микрофон и говорит команды; команды разбираются офлайн,
применяются к текущей тренировке и журналируются (🛡 Ф-1.5).
**В границах модуля:**
- **грамматика команд Ф-1.2** (разбор — чистая функция):
- «Подход **W** на **R**» → подход: вес `W` кг × `R` повторений
(вес — целые кг либо «…с половиной» → +0,5 кг; `W` — 0–500,
`R` — 1–100; решение владельца О-2-Б);
- «Вес **W**» → рабочий вес `W` кг для следующих подходов;
- «Отдых **S** (секунд)» → таймер отдыха `S` секунд (5–600);
- «РПЭ **N**» → RPE последнего подхода, `N` — 1–10 (Ф-13.3);
- числа — словами («сто двадцать») и цифрами («120»); слова «секунд»
после `S` — необязательны; постобработка «сто двадцать» → 120 —
tech-req 5;
- команда вне грамматики или число вне диапазона — **отклоняется**:
короткий сигнал ошибки, состояние не меняется, в журнал пишется
распознанный текст с `accepted=false` (Ф-1.3);
- **STT-движок**: Vosk (`com.alphacephei:vosk-android`), малая
русская модель (`vosk-model-small-ru-0.22`, ~45 МБ); распознавание
только офлайн — сеть не используется (Ф-1.1, ОВ-2); ограничение
словаря грамматикой Vosk (`setGrammar`, JSON-словарь: «подход», «вес»,
«отдых», «на», «секунд», «с половиной», числительные 0–999) —
применяется, если модель поддерживает; обязательна строгая
постобработка финальной гипотезы парсером (малые модели Vosk не
гарантируют поддержку грамматики — деградация до свободного
распознавания, лишнее отклоняет парсер по Ф-1.3);
- **доставка модели**: модель НЕ входит в APK и в репозиторий;
загружается zip-архивом по https в папку приложения при первом
включении микрофона (или из «Настроек»), распаковывается в
`filesDir`; URL — настройка `Voice.ModelUrl` (умолчание — официальный
хост alphacephei.com); статус модели и кнопка «Загрузить» — в
«Настройках» (решение гейта 1.3);
- **применение команд** (исполнитель): «Подход» → `WorkoutCore.logSet`
(source=`voice`, текущее упражнение экрана); «Вес» → рабочий вес
текущего упражнения (состояние экрана, умолчание формы); «Отдых» →
старт таймера отдыха (переиспользуется таймер m10); «РПЭ» → RPE
последнего подхода тренировки (`WorkoutCore.setLastSetRpe` —
расширение m09, как `renameExercise` в m10);
- **журнал команд 🛡** (Ф-1.5): каждая команда — принятая и отклонённая —
через `WorkoutCore.logCommand` (текст, семантика, `t_offset_s` от
начала тренировки, `accepted`); журнал не редактируется; уходит sync
`command_log` (контракт m09 spec 04);
- **подтверждения** (Ф-1.4): принятая команда — короткий «щелчок»
(ToneGenerator) + голосовое TTS-подтверждение офлайн («Принято,
подход 120 на 8» / «…вес 100» / «…отдых 90 секунд» / «…РПЭ 8»);
TTS — системный Android TTS (ru-RU, tech-req 4.1); при отсутствии
TTS-движка/русского голоса — деградация: щелчок/сигнал + текст
подтверждения на экране, работа не блокируется;
- **активация** (Ф-1.1): кнопка микрофона на экране «Тренировка»;
повторное нажатие выключает прослушивание; прослушивание активно,
пока открыт экран активной тренировки и микрофон включён — выход
с экрана останавливает; разрешение `RECORD_AUDIO` запрашивается
при первом включении (runtime);
- **текущее упражнение**: голос пишет подходы в «текущее упражнение»
экрана «Тренировка» — выбор тапом в блоке плана (подсветка),
умолчание — первый пункт плана сессии дня, иначе последнее
введённое вручную; голосовой выбор упражнения по имени в v1
отсутствует (имена произвольные — распознавание ненадёжно;
решение гейта 1.3);
- **экран «Тренировка»**: индикатор «слушаю/выключено» (иконка +
текст 🛡), строка последней команды (принято/отклонено — текстом,
не только цветом), «Вес W» меняет отображаемый рабочий вес;
- **«Настройки»** (расширение m10): блок «Распознавание речи» — статус
модели (не загружена / загружена, размер), кнопка «Загрузить»
(по `Voice.ModelUrl`, прогресс/ошибка текстом), «Проверить TTS» —
наличие ru-голоса;
- unit-тесты (pure JVM): парсер (4 команды, числа словами 0–999
и цифрами, «с половиной», границы диапазонов, мусор, регистр),
семантика журнала, NumberRu; исполнитель — на фейках ядра.
**Вне границ модуля:** wake-word (опросник 4.5 — v2), голосовой выбор
упражнения по имени (v1 нет — решение гейта), распознавание на часах,
запись аудио (только живой поток в движок, хранения нет), шумовой
профиль зала, метрики точности в БД (КУ-1 фиксируется вручную
владельцем), m12 канал часов, m13 поле данных.
## 2. Решения интерфейса (ui-ux разд. 3, tech-req 6)
- Кнопка микрофона — нижняя треть экрана, цель ≥ 48 dp, состояние
дублируется текстом («Слушаю…» / «Голос выключен»);
- строка последней команды — текстом: «Принято: подход 120 на 8» /
«Не распознано» (цвет — только дублирование);
- сигнал ошибки — короткий, не пугающий; формулировки спокойные;
- TTS-подтверждения короткие (≤ 3–4 слов + числа).
## 3. Инварианты (🛡 — нарушать запрещено)
1. **Офлайн-first** (Ф-1.1, КУ-3): распознавание и применение команд
работают без сети; сеть — только доставка модели (один раз) и
SyncQueue как обычно.
2. **Журнал команд полон и неизменяем** (Ф-1.5): каждая распознанная
фраза (принятая и отклонённая) фиксируется с исходным текстом,
семантикой и `t_offset_s`; удаление/правка журнала невозможны.
3. **Голос не обходит ядро**: применение команд — только через
`WorkoutCore` (единственный писатель LocalDb, инвариант m09);
`VoiceInput` не пишет в БД напрямую.
4. **Допуск Safety не снимается голосом**: команды работают только
в уже начатой (допущенной) тренировке; блокировки допуска —
контур m09/m10.
5. **Тайны**: `Voice.ModelUrl` может содержать URL сервера владельца —
ключи/пароли в неё не попадают; API-ключ не логируется (З-6).
## 4. Критерии приёмки модуля
1. `assembleDebug` собирается; unit-тесты парсера/исполнителя зелёные.
2. Ручной смок на устройстве владельца (модель загружена): включить
микрофон → «Подход 60 на 10» → щелчок + «Принято, подход 60 на 10»
→ подход записан (источник «голос», метка плана); «Вес 62
с половиной» → рабочий вес 62,5; «Отдых 90» → таймер; «РПЭ 7» →
RPE у последнего подхода; фраза вне грамматики → сигнал ошибки,
состояние не изменилось, в журнале `accepted=false`.
3. Смок синхронизации (живой docker-сервер): журнал команд уходит
`command_log`-пакетом, строка в `src.command_log` содержит текст
и семантику.
4. КУ-1 (контрольная тренировка ≥ 4 упражнений, ≥ 16 подходов,
≥ 90 % команд с первого раза) — ручная приёмка владельца в зале
(tech-req 7 п. 3); автоматизации не подлежит, фиксируется
в журнале приёмки.