# Микрофон и распознавание: результаты поиска **Задача была:** найти готовые библиотеки для работы с микрофоном и распознавания, прежде чем брать код из `ai/assistent`. **Код не пишем** — только поиск. **Ответ короткий:** и то, и другое **уже есть у нас, готовое и опубликованное**. Из `ai/assistent` брать код микрофона **не нужно вообще**. --- ## 1. Микрофон: библиотека есть — `mic-kmp` **Репозиторий:** https://git.binom.pw/subochev/mic-kmp **Каталог:** https://git.binom.pw/subochev/libraries (раздел «📦 Микрофон») KMP-библиотека: поток микрофона как `Flow` (s16le mono PCM). Три файла, вот и вся библиотека: | Файл | Что делает | |---|---| | `mic-api/src/commonMain/.../MicAudio.kt` | интерфейс `MicDevice` + объект `MicAudio.record(...)` | | `mic-api/src/jvmMain/.../MicJvm.kt` | JVM — `javax.sound.sampled` (`TargetDataLine`) | | `mic-api/src/androidMain/.../MicAndroid.kt` | Android — `AudioRecord` | **Таргеты: `jvm` и `android`.** JVM-таргет — ровно то, что нужно десктопу. JVM-код собран на `JvmTarget.JVM_17`. **Опубликована в Nexus `caffeine`, версия `1.0.0`:** - `pw.binom.mic:mic-api:1.0.0` (KMP metadata) - `pw.binom.mic:mic-api-jvm:1.0.0` (JVM — **наше**) - `pw.binom.mic:mic-api-android:1.0.0` Проверено: `maven-metadata.xml` отдаёт `HTTP 200`, latest = `1.0.0`. **Использование — одна строка:** ```kotlin MicAudio.record(sampleRate = 16000, channels = 1, chunkMillis = 100) .onEach { chunk: ByteArray -> /* s16le mono PCM, ~100 мс */ } ``` **Чем лучше кода из assistent:** отмена **структурная**. Остановил корутину-коллектор — микрофон освободился сам, в `finally`. Не надо помнить про `close()`. В assistent (`MicrophoneRecorder`, 83 строки) — ручное управление через `start()`/`stop()`, и связка «канал + флаг recording + внешний TargetDataLine». Наш вариант чище. **Вывод: копировать `MicrophoneRecorder` из assistent НЕ надо — подключить `mic-kmp`.** --- ## 2. Распознавание: библиотека есть — `asr-kmp` **Репозиторий:** https://git.binom.pw/subochev/asr-kmp **Каталог:** https://git.binom.pw/subochev/libraries (раздел «🎙 ASR») KMP, таргеты **jvm** и **android** (плюс native: linux, macos, mingw). Потоковый интерфейс — приём аудио кусками и **промежуточный текст по ходу**: ```kotlin interface Stt : AutoCloseable { fun feed(samples: FloatArray) // порция 16 кГц моно PCM, [-1, 1] fun partialText(): String? // промежуточный текст (растёт по ходу) fun endOfInput() // конец ввода fun finalText(): String // итог override fun close() } ``` **Есть `partialText` — текст появляется по мере речи**, а не после конца записи. Для нашей кнопки микрофона это именно то поведение, которое нужно. ### Движки (все опубликованы в `caffeine`) | Движок | Координаты (группа `pw.binom.asr`) | Версии в Nexus | |---|---|---| | `asr-api` — интерфейс | `asr-api` / `-jvm` / `-android` | до `4` | | `asr-vosk` — Vosk | `asr-vosk` / `-jvm` / `-android` | есть | | `asr-qwen3` — Qwen3-ASR | `asr-qwen3` / `-jvm` | есть | | `asr-whisper` — Whisper | `asr-whisper` / `-jvm` / `-android` | есть | | `asr-openai` — удалённое (OpenAI-совместимое) | `asr-openai` | есть | Под капотом нейронок — `sherpa-onnx` (`com.github.k2-fsa.sherpa-onnx`, `v1.13.6`), для JVM отдельно тянется нативная библиотека `sherpa-onnx-native-lib-linux-x64`. ### Про модели (важно) - **Qwen3-ASR** — модель уже на нашем статик-сервере, качать из-за бугра не надо: `http://static.binom.pw/models/qwen3_06/` (~940 МБ: encoder 175M, decoder 721M, frontend 43M). - **Whisper small int8** — модели на статике НЕТ, качать самостоятельно. - **Vosk** (`vosk-model-small-ru-0.22`) — **входит в комплект**, распаковывается сам. Самый простой путь для первого запуска: ничего качать не надо. --- ## 3. Рядом есть ещё три полезные библиотеки Из того же каталога `subochev/libraries`: ### VAD — детектор речи, `vad-kmp` https://git.binom.pw/subochev/vad-kmp — «VAD — Silero», KMP jvm+android, **модель внутри артефакта** (2.3 МБ, ничего качать не надо). ```kotlin VadInstance(16000).use { vad -> val prob = vad.processingWindow(windowPcmFloats) // FloatArray → [0..1] } ``` Координаты: `pw.binom.voice.vad:vad-jvm`, версия `2`. **Зачем:** определять, говорит человек или молчит — не гнать тишину в распознавание. ### Есть и второй VAD `pw.binom.ai.voice:vad` — «детектор речи (VAD) — `vad` / `vad-jvm`». Два разных VAD, при выборе разобраться, какой свежее. ### OpenAI-клиент `pw.binom.openai:api` / `api-jvm` + `ktor-impl` (HTTP-движок). Нужен для `asr-openai` (распознавание на удалённом сервере, а не локальной нейронкой). ### Speaker-эмбеддинги и text-embedding - `subochev/embedding-kmp` — voice embedding (кто говорит). - `subochev/text-embedding-kmp` — text embedding (SigLIP2). Нам сейчас не нужно, но пусть будет известно. --- ## 4. Как это собрано вместе — пример `view-mate` **Репо:** `/root/WORK/view-mate` (очки RayNeo X2), модули `app-glasses`, `app-phone`, `app-host`, `lib-core`. **Важно:** view-mate **не подключает** `mic-kmp`/`asr-kmp` как библиотеки — у него своя реализация `SttMicStream` на `android.media.AudioRecord` (`app-glasses/.../stt/SttMicStream.kt`). То есть `mic-kmp` — это **вынесенная и обобщённая** версия того же подхода. Из полезного в `SttMicStream.kt` — комментарий на строке 229: `AudioRecord.read(byte[], int, inFrameCount)` возвращает **число кадров**, а не байт. Классические грабли Android-записи. --- ## 5. Чем пользуется сам `ai/assistent` Важно для понимания разницы подходов: `chat-server/.../stt/SttClientImpl.kt` — это **не** локальное распознавание. Это HTTP-клиент к OpenAI-совместимому API: ```kotlin client.post("$base/audio/transcriptions") { ... } // multipart, как у OpenAI ``` Настройки через переменные окружения: - `STT_API_KEY` — без него голосовой адаптер выключен; - `STT_URL` — по умолчанию `https://api.openai.com/v1`; - `STT_MODEL` — по умолчанию `whisper-1`. **Вывод:** у assistent распознавание — **отправка файла на сервер**. У нас `asr-kmp` умеет и локальные нейронки (Qwen3, Whisper, Vosk), и удалённое (`asr-openai`). Наш вариант шире, а `mic-kmp` (поток) + `asr-kmp` (поток) + `vad-kmp` (детектор речи) складываются в готовую цепочку: **микрофон → детектор речи → распознавание → текст**. --- ## 6. Итог: что делать | Вопрос | Ответ | |---|---| | Та отдельная библиотечка для микрофона, которую мы делали — существует? | **Да.** `mic-kmp`, опубликована в `caffeine` версии `1.0.0`, jvm-таргет есть. | | Библиотечки распознавания с нейронками где? | **`asr-kmp`** — Qwen3, Whisper, Vosk, удалённое. Всё в `caffeine`. Плюс каталог: `subochev/libraries`. | | Есть ли где-то микрофон в каталоге библиотек? | **Да**, первым разделом — «📦 Микрофон». | | Брать ли код микрофона из `ai/assistent`? | **Нет.** Подключаем `mic-kmp` — чище, с автоосвобождением, без внешних библиотек. | | Нужны ли сторонние зависимости для звука? | **Нет.** Всё на стандартной Java (`javax.sound.sampled`) и sherpa-onnx для нейронок. | **Код не писан** — только поиск, как и просили.