feat(app-phone): офлайн-распознавание речи — sherpa-onnx + Whisper-small

STT-модуль для отладки (без UI): WhisperStt (offline whisper int8, CPU),
VadSegmenter (Silero VAD, фразы), WavReader (16k mono s16), SttDebug
(распознавание wav-файла по фразам с печатью в лог). Вызов: am start
--ez stt_debug true (первый wav из filesDir/samples). Модели — в
filesDir/models (вне git): small-encoder/decoder.int8.onnx,
small-tokens.txt, silero_vad.onnx (fp32!).

Грабли, найденные на эмуляторе (Android 15):
- Silero VAD int8 (643КБ) молчит в Android-рантайме — нужна fp32 (2.2МБ)
- WavReader: littleShort возвращал беззнаковое 0..65535 — сэмплы с
  DC-offset, whisper давал мусор; теперь знаковый -32768..32767
- VAD требует подачу окнами ровно window_size (целиком — переполнение)
- Модели кладутся через adb push /data/local/tmp + run-as cp
  (внешний каталог приложения на Android 15 не видит adb-файлы)

Проверено на эмуляторе (CPU): «раз два три четыре пять» → «Раз, два 3 4 5»,
грека → почти идеально, masha/anton → 21 фраза, диалог распознан.
README: таблица жестов обновлена (TripleClick — безусловный вызов).
This commit is contained in:
Hermes Agent
2026-08-20 03:29:57 +03:00
parent 97aaabeb65
commit 324c427c74
11 changed files with 330 additions and 3 deletions
+21 -3
View File
@@ -59,15 +59,33 @@ sketches/ эскизы UI: раскладка экранов + сценар
## Жесты (распознаёт RayNeo SDK, `TempleAction`)
### Вне распознавания (обычный режим)
| Жест (SDK) | Режим КИНО | Режим ЧАТ |
|------------|-----------|-----------|
| `Click` | пауза ↔ плей | старт / стоп диктовки |
| `DoubleClick` | игнор | отмена диктовки; вне диктовки — вызов локального ассистента |
| `DoubleClick` | игнор | отмена диктовки |
| `TripleClick` | **безусловный вызов ассистента** (пауза видео + затемнение + слушаем) | **безусловный вызов ассистента** (слушаем) |
| `SlideBackward` / `SlideForward` | перемотка | в `SESSION_SELECT` — листание сессий; в `TALKING` — скролл текста ответа |
| `LongClick` | (резерв) | показать / спрятать текст последнего ответа |
| `TripleClick` | (резерв) | (резерв) |
> Жесты распознаёт сам SDK (`TempleAction.Click/DoubleClick/TripleClick/SlideBackward/SlideForward/LongClick`) — своя детекция не нужна (проверено в pair-view, `MainActivity.kt`).
### Во время распознавания речи (LISTENING)
| Жест | Действие |
|------|----------|
| `Click` | **завершить распознавание**: вывести весь текст (все фразы) в консоль; затемнение уходит, видео остаётся на паузе |
| `DoubleClick` | **отмена распознавания** (текст отбрасывается) |
| `TripleClick` | игнор |
| VAD молчит 30 с | автоматическая отмена распознавания |
> **TripleClick — безусловный вызов локального ассистента из любого места**
> (поверх всего). Распознавание идёт по фразам: VAD отсёк фразу — распознал —
> отобразил на очках — слушаем дальше; ввод считается открытым до Click.
>
> Жесты распознаёт сам SDK (`TempleAction.Click/DoubleClick/SlideBackward/
> SlideForward/LongClick`) — своя детекция не нужна (проверено в pair-view,
> `MainActivity.kt`). `TripleClick`: если SDK его не отдаёт — детект по
> таймстампам кликов в `onTouchEvent`.
## Состояния ассистента (единые для обоих ассистентов)