12 KiB
12 KiB
Требования к модулю: 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);
- «Подход W на R» → подход: вес
- 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); журнал не редактируется; уходит synccommand_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. Инварианты (🛡 — нарушать запрещено)
- Офлайн-first (Ф-1.1, КУ-3): распознавание и применение команд работают без сети; сеть — только доставка модели (один раз) и SyncQueue как обычно.
- Журнал команд полон и неизменяем (Ф-1.5): каждая распознанная
фраза (принятая и отклонённая) фиксируется с исходным текстом,
семантикой и
t_offset_s; удаление/правка журнала невозможны. - Голос не обходит ядро: применение команд — только через
WorkoutCore(единственный писатель LocalDb, инвариант m09);VoiceInputне пишет в БД напрямую. - Допуск Safety не снимается голосом: команды работают только в уже начатой (допущенной) тренировке; блокировки допуска — контур m09/m10.
- Тайны:
Voice.ModelUrlможет содержать URL сервера владельца — ключи/пароли в неё не попадают; API-ключ не логируется (З-6).
4. Критерии приёмки модуля
assembleDebugсобирается; unit-тесты парсера/исполнителя зелёные.- Ручной смок на устройстве владельца (модель загружена): включить
микрофон → «Подход 60 на 10» → щелчок + «Принято, подход 60 на 10»
→ подход записан (источник «голос», метка плана); «Вес 62
с половиной» → рабочий вес 62,5; «Отдых 90» → таймер; «РПЭ 7» →
RPE у последнего подхода; фраза вне грамматики → сигнал ошибки,
состояние не изменилось, в журнале
accepted=false. - Смок синхронизации (живой docker-сервер): журнал команд уходит
command_log-пакетом, строка вsrc.command_logсодержит текст и семантику. - КУ-1 (контрольная тренировка ≥ 4 упражнений, ≥ 16 подходов, ≥ 90 % команд с первого раза) — ручная приёмка владельца в зале (tech-req 7 п. 3); автоматизации не подлежит, фиксируется в журнале приёмки.