Голосовой тракт Алисы¶
Как колонка слышит, распознаёт и отвечает. Снято с Amlogic-Станции (quasar 3.21): по
quasar.cfg (audiod, aliced, audiosender, bio_capability), моделям в spotter_models/
и bio_lingware/, путям исходников в strings maind и логам maind.log. Помечено (вывод)
то, что не подтверждено напрямую.
Главное
На устройстве распознаётся только ключевое слово и ~25 коротких команд. Полное
распознавание речи (ASR) и понимание (VINS/Megamind) — в облаке (withLocalVins: false).
Без доступа к uniproxy колонка не превращает речь в текст.
4 PDM-микрофона ─┐ maind --platformd (aliced)
(ALSA card0 dev2 │ ┌──────────────┐ ┌─────────────────────────────────────┐
"dmicarray", ├──►│ Yandex VQE │───►│ канал vqe_0 (16 кГц, моно) │
48 кГц, 4 кан.) │ │ AEC + beam- │ │ ├─ activation spotter "алиса"/"яндекс"
петля динамика ──┘ │ forming + NS │ │ ├─ counteractivation (ложные срабатывания)
raw_spk_0/1 └──────────────┘ │ ├─ command spotter (стоп/громче/…)
(эталон для эхоподавления) │ └─ bio: ECAPA-TDNN голосовой отпечаток,
│ пол/возраст (tflite)
└──────────────┬──────────────────────┘
срабатывание "Алиса" │ earcon + LED
▼
SpeechKit: Opus-кодирование (OggOpusEncoder)
│
wss://uniproxy.alice.yandex.net/uni.ws │ protobuf (useProtoAliceApi),
│ сжатие zstd
▼
┌──────────────── облако Яндекса ────────────────────────┐
│ VoiceInput → ASR (модель quasar-general, partials) │
│ → AsrResult (текст) → VINS/Megamind (смысл, навыки) │
│ → AliceResponse (директивы) + TtsSpeak (речь, Opus) │
└────────────────────────────┬───────────────────────────┘
▼
directive_sequencer → capabilities (музыка → mediad,
уведомления, будильники, громкость, GeoSync, …)
TTS → audio_client: appsrc ! opusparse ! opusdec ! alsasink
1. Захват звука — audiod¶
Внутри maind --platformd. ALSA card 0, device 2 (PDM-dummy, в конфиге dmicarray),
inRate 48000, micChannels 4, spkChannels 2, outRate 16000. Каналы
(audiosender.availableChannels): raw_mic_0..3, raw_spk_0..1 (что играет динамик) и vqe_0.
brokenMicDetector следит за RMS микрофонов.
2. Обработка — Yandex VQE¶
vqe.type: yandex, preset: yandexmini, omniMode: true. Эхоподавление по raw_spk_* (Алиса
слышит вас поверх своей музыки), формирование луча, шумоподавление (вывод по набору каналов).
Выход — канал vqe_0: его слушают спотеры (spotterChannelName) и его же отправляют в
облако (speechkitLogChannels).
3. Локальные нейросети¶
Движок nnet, признаки cmn:lda, модели в spotter_models/ (обновляются с CDN Яндекса в
/data/quasar/data/spotter_model, сборочные — fallback):
| Модель | Задача |
|---|---|
activation/alisa, activation/yandex |
ключевые слова «Алиса» / «Яндекс», работают всегда |
counteractivation |
подавление ложных срабатываний (например «Алиса» из рекламы по ТВ) |
command |
~25 команд без ключевого слова: дальше, назад, громче, тише, стоп, хватит, пауза, играй, включи/выключи, свет, телевизор, блютуз, лайк/дизлайк… (words.txt) |
vad |
<speech_started> / <speech_finished> |
bio_lingware/* |
голосовой отпечаток (ECAPA-TDNN) + пол/возраст — «узнавание» пользователя (MatchedUser, Biometry.Classification) |
Подтверждено логом: command_spotter_capability.cpp: Command phrase spotted: ^ дизлайк.
4. Активация → поток в облако (SpeechKit)¶
- На срабатывание: earcon (
playStartVoiceInputEarcon,activation_feedback_player) и анимация LED. RecognizerSession/Recorder→OggOpusEncoder→UniProxyImplпо WebSocket наuniProxyUrl.- Протокол: protobuf Alice API (
useProtoAliceApi: true), сжатие zstd (wsUseZstd: true). - Соединение держится постоянно (в логе
UniProxyProtocolState … PongTimeoutElapsedпри обрывах).
| Клиентские события | Серверные события |
|---|---|
VoiceInput, TextInput, AsrRecognize, LogSpotter, MatchedUser, TtsGenerate |
InputStartAck, AsrResult, SpotterValidation, AliceResponse, TtsSpeak, TtsTimings |
SpotterValidation— сервер перепроверяет ключевое слово по присланному аудио (вывод по названию).vadEnabled: false→ конец фразы определяет сервер, а не локальный VAD.
5. Облако¶
ASR: shortRecognizerModel: quasar-general, промежуточные гипотезы (enable_partials).
music_recognizer — распознавание играющей музыки. Диалог и навыки — VINS/Megamind;
experiments/supportedFeatures сообщают серверу, что умеет устройство (так он и отличает
«болталку» от команд умного дома — маршрутизация на стороне облака).
6. Ответ¶
AliceResponse→directive_sequencer routeDirective … via <Capability>(в логе:set_timezone/set_locationчерез GeoSyncCapability,notifyчерез NotificationCapability).- Речь:
TtsSpeak→audio_client_tts_player.cpp→ GStreamer:appsrc ! opusparse ! opusdec ! volume ! alsasink. Музыка — вmaind --mediad. - Текстовые запросы (из приложения) идут как
Vins.TextInputи минуют ASR.
Отправка аудио помимо запросов¶
audiosender держит кольцевой буфер historySeconds: 10 по всем 7 каналам.
cachingSoundLogSender / logsound/* (SoundLogStorage, UniProxyLogSender,
random_sound_logger) отправляют «звуковые логи» срабатываний; случайная запись включена для
групп allowedForRandomLoggingQuasmodromGroups: ["beta"].
Что это значит для своего ASR/LLM¶
Это прямо отвечает на вопросы из «Своя LLM вместо Алисы»:
- Текст запроса без uniproxy не получить — ASR облачный. Нужно либо перехватить поток на
uni.ws(TLS + protobuf, как с quasar-бэкендом), либо забирать звук самостоятельно: каналыvqe_0/raw_mic_*живут внутриmaind, ALSA-устройствоhw:0,2занятоaudiod(одновременный захват не проверялся). - Произнести свой текст проще всего локально — через API glagol на порту 1961, как это
делает интеграция YandexStation для Home Assistant (см. Сеть → glagol);
из облака это делает
AliceResponse.TtsSpeak. - Подмена адреса: пиннинга сертификатов нет (см. Подводные камни),
uniProxyUrlможно увести на свой сервер, в том числе поws://без TLS. - Рабочий пример — quasard: свой uniproxy (JSON и protobuf
AAPI), ASR, LLM и TTS вместо облака.
Приватность
Колонка постоянно держит соединение с облаком, а для «beta»-групп может отправлять случайные звуковые фрагменты. При изоляции это стоит учитывать.