subochev
e81026b9f5
Слои записи и оверлей берут стт-статус и сессию из единого GlassesStt
2026-09-07 04:27:05 +03:00
subochev
7db0fc71de
Слои записи и оверлей берут стт-статус и сессию из единого GlassesStt
2026-09-07 03:59:15 +03:00
subochev
8083978849
Слой записи владеет микрофоном и распознаванием, движок — только диалогом
2026-09-07 03:27:31 +03:00
subochev
1b817aa9a6
Сохраняем прогресс просмотра и возобновляем с позиции
2026-09-07 01:09:44 +03:00
subochev
f68ea10342
Сборка release: подпись ключом Binom (v2+v3) + таск assembleSigned
...
signingConfigs в app-phone/app-glasses берут кестор и креды из скилла
android-sign (вне git); без кестора release собирается без подписи.
assembleSigned — собрать оба приложения одним шагом.
2026-09-04 03:08:28 +03:00
subochev
5c86ed00b4
STT: очки распознают речь локально и шлют готовый текст (SttText) в телефон
...
- glasses: локальный ASR через общий pw.binom.asr (GlassesAsr/GlassesSttSession/SttModelProvider)
- protocol: SttText — очки присылают распознанный текст в телефон; телефон кидает его в LLM
(старый SttAudio/StopStt оставлен фолбэком для старых очей)
- phone: SttStreamer делегирует общему ASR; GlassesServer роутит SttText в LLM
- lib-core: AudioPrep общий
2026-09-04 03:08:26 +03:00
subochev
f656f43e10
Сохраняем прогресс просмотра и возобновляем с позиции
2026-09-02 20:55:00 +03:00
subochev
b2e2d2697d
Добавляем индикатор рассинхронизации звука и видео в статус-панели очков
2026-09-02 19:27:11 +03:00
subochev
e18b82642f
audio-sync: учитывать латентность линка очки→телефон
...
Очки штампуют sentTs в PlaybackPosition; телефон мерит one-way
латентность (receivedTs - sentTs, EWMA) и добавляет её к мастер-позиции
в sync(), снимая системный перекос, из-за которого аудио недокручивало
на величину транспортной задержки. Плюс правки тестов под
HARD_SEEK_THRESHOLD_MS=5000 (остались незакомиченными с прошлого фикса).
2026-08-30 05:08:37 +03:00
subochev
6cd4a8de43
feat: управление яркостью/WiFi очков через Mercury + накопленные доработки
...
- Mercury (app-phone): управление яркостью (с авто-выкл. перед
применением) и WiFi (скан/подключение/список сетей с паролем);
добавлено право BLUETOOTH_ADVERTISE в манифест и runtime-запрос
(без него GATT-сервер не рекламируется → очки не подключаются)
- логирование (lib-core core.log): BatchingLogCollector + LogSink +
LogSpool + LokiLogSink; цепочка очки→телефон→Loki; lib-core log()
переадресован в коллектор
- STT: Qwen3-ASR через pw.binom.asr:asr-qwen3-android, убран in-house
whisper-фоллбек
- audio-sync: P-регулятор с насыщением вместо фиксированной скорости
- media-split: очки только video, телефон только audio (UI-чипы)
- Components: форматирование размера через Locale.ROOT
2026-08-29 23:06:52 +03:00
subochev
236ff18543
ui(glasses): оверлей ассистента накрывает весь вьюпорт (fillMaxSize, непрозрачный чёрный) — независимо от масштаба и регулятора «Высота» видео
2026-08-27 18:46:31 +03:00
subochev
412e093174
ui(glasses): отмена первой записи не закрывает оверлей — возврат в «слушаю», диалог жив даже при пустой истории; выход из режима — только явный жест ExitMode
2026-08-27 18:46:29 +03:00
subochev
4e60e11d24
stt: дамп закрывает цикл в finally (нет Stream Closed при стопе)
2026-08-25 03:13:27 +03:00
subochev
b0baa19e7d
stt: полный поток без VAD (резал речь на рваном ARGT78) — whisper распознаёт сырой поток (проверено: 1-10 идеально), усиление ×3, сырой дамп
2026-08-25 03:12:04 +03:00
subochev
d34d15ecef
stt(dump): сырой WAV всего потока микрофона (до усиления/VAD) — что реально слышат очки
2026-08-25 03:00:47 +03:00
subochev
19fe1b34bc
stt(mic): возврат на 16 кГц (48 кГц молчит на ARGT78); VAD на сыром + gain ×5 остаются
2026-08-25 02:59:00 +03:00
subochev
1009713a28
stt(mic): 48 кГц как pair-view + VAD на сыром сигнале + усиление ×5 без клиппа + FIR-даунсэмпл 48→16
2026-08-25 02:55:42 +03:00
subochev
0f235da0ed
Высота — только для видео: ассистент/коннект-экран следуют масштабу, но всегда у верха
2026-08-25 02:43:45 +03:00
subochev
74701a2108
Панель статуса сдвигается к носу вместе с контейнером (panelOffsetX): центр панели = центр контейнера
2026-08-25 02:39:43 +03:00
subochev
4f4a551c91
Панель времени/заряда: масштабируется как контент, но прибита к низу экрана
2026-08-25 02:35:24 +03:00
subochev
80236902ba
Панель времени/заряда: шрифт фиксированный (scale=1f) — не сжимается вместе с масштабом контента
2026-08-25 02:31:28 +03:00
subochev
d113ffd744
Панель времени/заряда: оверлей-слой поверх контента, у низа экрана — стабильно при любом масштабе
2026-08-25 02:28:00 +03:00
subochev
8958370507
Панель времени/заряда — вне контейнера, всегда у верха экрана (не повисает между верхом и видео при vertical=0)
2026-08-25 02:24:57 +03:00
subochev
883fd8e5e4
Высота: видео в контейнере прижимается к верху/низу по vertical (Row-центрирование съедало вертикаль)
2026-08-25 02:15:48 +03:00
subochev
6d22f56bd8
Регулятор «Высота» экрана очков (0..1, с учётом масштаба): SetVertical по протоколу, offset Y в кино/коннект/оверлее, слайдер на пульте
2026-08-25 02:11:01 +03:00
subochev
b17b5bf424
stt(glasses): VAD на очках (WebRTC, схема pair-view) — речевые сегменты с пре-роллом, межфразовая тишина не шлётся
2026-08-25 01:51:57 +03:00
subochev
d78ed4429e
stt(mic): микрофон на 48 кГц (нативная частота) + даунсемплинг 48→16 — рваность ARGT78 давала ровные провалы 100 мс
2026-08-25 01:39:12 +03:00
subochev
e21c27b0ee
stt(dump): WAV-заголовок — размеры little-endian (плееры открывают дампы)
2026-08-24 21:36:53 +03:00
subochev
0d79b5aa33
stt(mic): усиление микрофона очков ×10 — VAD/Whisper видят речь (пустая фраза)
2026-08-24 20:57:06 +03:00
subochev
40edd88c1d
stt(mic): вынести кадровую арифметику в micChunkBytes + регрессионные тесты MicChunkTest
...
- CHUNK_BYTES=3200, micChunkBytes(buf, frames): кадры read() -> байты (*2)
- 4 теста: полный чанк 3200 Б без копирования, короткий read,
документация старого бага (copyOf(кадры) = полка), inFrameCount=1600
2026-08-24 12:23:33 +03:00
subochev
fc84ba16b6
stt(mic): request frames in frames (inFrameCount), not bytes — each chunk now carries full 100 ms
2026-08-24 11:10:05 +03:00
subochev
c940a7e0eb
stt(mic): AudioRecord.read возвращает КАДРЫ, а не байты — не терять вторую половину каждого 100-мс чанка (впечатление 'пропускает через один')
2026-08-24 11:08:27 +03:00
subochev
22eb83fd17
stt: debug-дампы аудио-пути (очки: сырой микрофон в WAV; телефон: принятые PCM) по старту от stt_dump.marker
2026-08-24 05:58:59 +03:00
subochev
7557d7229f
Очки: отмена слушания двойным тапом — SttCancel reason=cancel
2026-08-24 03:01:55 +03:00
subochev
504e66f0c6
Очки: красный индикатор записи микрофона в режиме «слушаю»
2026-08-23 21:58:36 +03:00
subochev
e24caaa684
Очки: разграничение SttCancel (user/timeout) — выход из режима при тишине 30с, микрофон закрывается при потере фокуса
2026-08-23 21:17:43 +03:00
subochev
eaca47c443
Очки: единый скролл диалога на оба глаза + мгновенная пауза звука телефона при вызове ассистента
2026-08-23 21:08:40 +03:00
subochev
706cc10d1e
Очки: история диалога в свайпе + распознавание в LLM только по клику (касяки 1-3)
2026-08-23 20:15:21 +03:00
subochev
f75e672819
Очки: жесты и режимы общения с ассистентом (по docs/gestures-and-modes.md)
...
- AssistantMode: NONE/LISTENING/THINKING/ANSWER + чистая gestureDecision (матрица жестов)
- Клик в «ответ виден» = новая фраза; DoubleClick = выход (кино на паузе); свайпы = скролл
- Плавный скролл ответа: SlideContinuous delta → answerScrollDelta → scrollOffset (зажим 0..max)
- Индикатор «думаю...» (thinking, сброс на ShowText)
- AssistantOverlay: затемнение 72%, по глазам, скролл-аккумулятор
- Тесты: 22 (AssistantGesturesTest) — glasses 91 зелёных
2026-08-23 01:55:24 +03:00
subochev
bbf7a020d4
Ассистент Порфирий: тула времени, сессии, чат-UI, голосовой цикл; BT-транспорт очки↔телефон
...
- BT (RFCOMM SPP 00001105) вместо WiFi: BtGlassesTransport/BtServerTransport, реконнект 3с
- PlaybackService (foreground, WAKE_LOCK) против морозов HONOR
- Ассистент: AgentTools (TimeTool ISO 8601), TOOL_CALL-протокол, сессии SQLite (UUID)
- Чат-UI: создание/сброс/переключение сессий, автообновление ленты 2с
- LlmClient на прямом OkHttp (Koog давал пустой content на длинных историях)
- Голосовой цикл: тройной тап на очках → STT → активная сессия → ShowText
- Тесты: AgentToolsTest (3), GlassesServerTest переписан (6) — зелёные
2026-08-22 16:31:04 +03:00
subochev
ee9700c558
CICD: сборка APK на release → F-Droid; versionCode из тега; фикс скролла каталога и масштаба
build / Android APK to F-Droid (release) Failing after 36s
2026-08-21 19:27:02 +03:00
Hermes Agent
a434d5bb12
feat: потоковый локальный ассистент — фраза → LLM → ответ на очки
...
- agent/Assistant.kt: оркестратор диалога (SQLite-история + Koog), таймаут 30с,
сессия одна живая, история — последние 20 сообщений
- ChatDao.latestSessionId(); SYSTEM_PROMPT нейтральный (TODO: персона)
- PhoneApp: очередь фраз (Channel UNLIMITED), assistantLoop (THINKING/ShowText/IDLE),
ensureAssistant ленивый; ключ/модель из BuildConfig (local.properties)
- Очки: assistantText StateFlow, ShowText → оверлей (белый текст речи + серый ответ),
оверлей остаётся после Click до новой сессии
- AssistantTest (androidTest, 3 теста: сессия/история/таймаут) — OK (6 tests всего)
- README: строка про ассистента
2026-08-20 12:35:49 +03:00
Hermes Agent
3ed63012f4
build: Kotlin 2.2.0 → 2.4.10 (AGP 8.9.2, Gradle 8.14 — в официальном диапазоне)
...
- libs.versions.toml: kotlin = 2.4.10
- jvmTarget '17' (kotlinOptions, String) — в 2.4.10 ошибка → compilerOptions DSL
(JvmTarget.JVM_17) в app-phone и app-glasses
- Compose-плагин (org.jetbrains.kotlin.plugin.compose) версионируется с Kotlin — 2.4.10
- Проверено: lib-core allTests + phone/glasses тесты + оба APK — BUILD SUCCESSFUL
- Открывает дорогу Koog (требует Kotlin 2.3.10+)
2026-08-20 10:51:07 +03:00
Hermes Agent
1304c6d921
feat: голосовой ввод на очках — TripleClick + PCM → телефон → текст на очки
...
Протокол: SttAudio (PCM s16 16k mono кусками), SttPhrase/SttDone/SttCancel
(host→очки), StopStt(cancel) (очки→host).
Очки: TripleClick — безусловный вызов (кино: пауза + затемнение + слушаем);
во время распознавания Click — завершить (весь текст в консоль, затемнение
уходит, видео на паузе), DoubleClick — отмена; VAD-тишина 30с — автоотмена.
Микрофон (AudioRecord 16k) → SttAudio; на эмуляторе — PCM из filesDir/samples
(куски 3200 + пауза 200мс). Оверлей текста в Binocular (полупрозрачный фон,
текст по центру, в оба глаза). RECORD_AUDIO в манифесте. DEBUG-ресивер
(am broadcast DEBUG_GESTURE type=triple_click|click|double_click).
Телефон: SttStreamer — стриминговый VAD (Silero fp32, окна 512) → фразы →
Whisper-small int8 (executor, не блокирует приём) → SttPhrase на очки;
StopStt → SttDone (полный текст) / SttCancel; watchdog 30с тишины.
Фиксы (найдены на эмуляторе): IllegalThreadStateException — двойной старт
watchdog-потока (thread{}.apply{start()}); decode входящих — try/catch с
логом (не роняет сессию).
Проверено на эмуляторах (5554 очки + 5556 телефон, forward 8080):
triple_click → фразы «Раз, два» и «3 4 5» на очках (оверлей) → click →
«ВЕСЬ ТЕКСТ: Раз, два 3 4 5»; 30с-тишина → «отменено». Тесты: lib-core,
phone, glasses — зелёные.
2026-08-20 04:12:28 +03:00
Hermes Agent
97aaabeb65
fix(app-glasses): не застревать на fallback 10.0.2.2 — перепоиск телефона
...
Если при старте очков телефон недоступен, discoverPhoneUrl возвращал
fallback (эмуляторный 10.0.2.2), он запоминался как lastUrl — очки вечно
реконнектили туда. Теперь на устройстве fallback не используется: не
нашли — повторный поиск через 3с (connectLoop рекурсивно). На эмуляторе
fallback остался. Железо: очки сами нашли телефон после его включения.
2026-08-20 01:41:43 +03:00
Hermes Agent
9f1c6735c1
feat(app-glasses): AR-метка RayNeoX2 (com.rayneo.mercury.app) + тема + landscape
...
Из pair-view: meta-data com.rayneo.mercury.app=true — очки распознают
приложение как AR (без неё открывалось как обычное). Тема
Theme.ViewMateGlasses (чёрный фон, fullscreen), screenOrientation
landscape, hardwareAccelerated. Плюс фикс краша: prefs читались в
конструкторе Application (до attachBaseContext) — перенесено в onCreate.
Проверено на железе: открывается через лаунчер нормально.
2026-08-20 01:22:27 +03:00
Hermes Agent
896185244b
fix(app-glasses): scale на паузе — принудительная перерисовка кадра
...
На паузе ExoPlayer не шлёт кадры — поверхность меняла размер/позицию,
но кадр оставался старым (часть видео не видно). requestRedraw():
updateTexImage + drawFrame для всех outputs — вызывается при смене
scale (LaunchedEffect) и в surfaceChanged. Подтверждено на железе.
2026-08-20 00:52:21 +03:00
Hermes Agent
9f20093bbf
fix(app-glasses): панель статуса — по центру в оба глаза, процент цветной
...
Binocular-контент растягивался на весь 1280 (fillMaxSize внутри
PositionedBox) — панель оказывалась по центру экрана, половина в каждом
глазу. Теперь явная ширина половины (как у видео-Row) — панель по центру
каждой половины, бинокулярно сливается в одну. ConnectionScreen тоже
обёрнут в Binocular. Квадратик-индикатор убран — процент окрашивается
цветом статуса (зелёный/белый/красный). Скрин: обе половины идентичны.
2026-08-20 00:24:12 +03:00
Hermes Agent
3f858c4a1a
feat(app-glasses): панель статуса — время + заряд (цвет по статусу)
...
Поверх видео (GL-оверлей в EglVideoRenderer: bitmap-текстура, правый
верхний угол, обе поверхности) и композ-панель на экране соединения.
Цвета (из удачной панели pair-view StatusComponent): CHARGING/FULL —
зелёный, DISCHARGING — белый, NOT_CHARGING — красный.
Данные: StatusPanelProvider (sticky ACTION_BATTERY_CHANGED + тик 1с,
HH:mm). Тесты 4 (chargeColorArgb). Железо: «00:02 94%» + зелёный
квадрат (очки на зарядке), скрин подтверждён.
2026-08-20 00:03:23 +03:00
Hermes Agent
2b6fdb7148
fix(app-glasses): старт быстрее — mDNS-таймаут 15с → 3с
...
На RayNeo mDNS мёртв (WiFi режет multicast, 0 пакетов) — 15с уходили
впустую перед сканом /24. Теперь: mDNS 3с → скан ~1с → коннект.
Железо: старт до соединения ~9с (было ~17с).
2026-08-19 23:47:28 +03:00