66 lines
8.9 KiB
Markdown
66 lines
8.9 KiB
Markdown
# Алиса для Станции Мини 2
|
||
|
||
Собственный голосовой клиент для рутированной Mini 2, сервер на Node.js и пульт в Telegram. На колонке работает русская модель ключевого слова «Алиса». Когда клиент готов принимать команду, верхнее кольцо загорается сине-фиолетовым. Произнеси команду после включения кольца.
|
||
|
||
```text
|
||
Mini 2 → VQE → WSS с PCM16 / 16 кГц → Scribe v3 Live
|
||
← WSS с PCM16 / 24 кГц ← Eleven v4 Turbo ← OpenRouter / Haiku 5.5
|
||
```
|
||
|
||
Модель Scribe можно переключить в пульте, включая Scribe v2 Realtime. Scribe выдаёт промежуточный текст, а запрос к LLM начинается после подтверждения конца команды. После инструментов сервер озвучивает один короткий ответ. Звуковые фрагменты сразу уходят на колонку. Запрос и ответ в текстовом виде сохраняются после успешного хода. Сервер держит 50 последних ходов и использует до 10 из них как контекст. Аудио сервер не пишет на диск. Облачные провайдеры обрабатывают отправленные им аудио и текст.
|
||
|
||
## Запуск и проверка
|
||
|
||
```sh
|
||
npm ci
|
||
npm test
|
||
cp .env.example .env
|
||
# Заполнить .env локально
|
||
node --env-file=.env server/index.mjs
|
||
```
|
||
|
||
Клиент, сборка и пробный запуск описаны в [station/README.md](station/README.md). На колонку передаётся отдельный `DEVICE_TOKEN`, ключи провайдеров остаются на сервере. Для интеграционного теста с реальными STT/TTS и без OpenRouter можно отдельно запустить сервер с `LLM_MODE=echo`.
|
||
|
||
## Развёртывание
|
||
|
||
На VPS код находится в `~/projects/alice-backend`. В корне проекта нужны `.env` с правами `0600` и каталог `data/` для настроек и истории, доступный на запись UID 1000. Пример конфигурации для уже существующей Docker-сети `web` и Caddy лежит в [deploy/](deploy/).
|
||
|
||
```sh
|
||
docker compose -f deploy/compose.yaml up -d --build
|
||
```
|
||
|
||
Caddy проксирует голосовое соединение и `/healthz` на `alice.pepega.systems`, а пульт и API на `miniapp.pepega.systems`. История и редактирование настроек требуют Telegram `initData` с проверенной подписью и ID владельца из `TELEGRAM_OWNER_ID`. В пульте можно выбрать модель OpenRouter, голос и модель синтеза, изменить системный промпт, подключить Spotify и очистить историю. В текущем API распознавания в реальном времени доступна одна модель.
|
||
|
||
## Протокол колонки
|
||
|
||
`GET /v1/voice` с WebSocket Upgrade и `Authorization: Bearer <DEVICE_TOKEN>`. Один ход на соединение.
|
||
|
||
1. Сервер посылает `{"type":"ready"}`.
|
||
2. Клиент посылает `{"type":"start"}`, затем бинарные блоки mono PCM16LE 16 кГц и `{"type":"end"}`.
|
||
3. Сервер присылает JSON `partial` и `transcript` с полем `text`, затем бинарные блоки mono PCM16LE 24 кГц.
|
||
4. Для команды Spotify сервер присылает `device_tool` с полями `id`, `name` и `arguments`. Клиент возвращает `device_tool_result` с тем же `id` и полем `result`.
|
||
5. Сервер присылает `{"type":"done"}` или `{"type":"error","code":"…"}` и закрывает соединение.
|
||
|
||
## Spotify и поиск в интернете
|
||
|
||
Музыку на колонке воспроизводит официальный Spotify Soloist. На Mini 2 он запускается с отдельным ARM64 runtime и PulseAudio. Музыка и ответы идут через разные входы микшера. Во время запроса музыкальный вход затихает, а после запроса его громкость восстанавливается. Станция буферизует начало команды, пока устанавливает соединение.
|
||
|
||
[Калибровка Room EQ](room-eq/README.md) измеряет акустику возле Mini 2 или в зоне прослушивания и позволяет сравнить коррекцию с исходным звучанием Spotify.
|
||
|
||
Для поиска по названию создай Spotify Web API приложение с Redirect URI `https://miniapp.pepega.systems/api/spotify/callback`, задай его Client ID в `SPOTIFY_CLIENT_ID` на сервере и подключи аккаунт в пульте. Soloist отдельно требует свой ключ и первый выбор устройства «Pepega Mini 2» в приложении Spotify. Сессия Connect сохраняется на колонке.
|
||
|
||
Клод вызывает `spotify_play` для трека, исполнителя, альбома или плейлиста. Поддерживаются пауза, продолжение, следующий и предыдущий трек и установка громкости. Короткие команды «пауза», «выключи музыку» и «громкость 50» выполняются без озвучивания подтверждения. Для актуальных сведений и проверки неизвестных фактов Клод может вызвать [серверный веб-поиск OpenRouter](https://openrouter.ai/docs/guides/features/server-tools/web-search).
|
||
|
||
[Spotify Soloist](https://developer.spotify.com/documentation/soloist) · [Рецепт librespot для сравнения](https://hackalice.me/recipes/spotify/)
|
||
|
||
|
||
### Разговор и Spotify
|
||
|
||
В «Пульте Алисы» можно включить сигнал активации и настроить окно продолжения разговора. По умолчанию сигнал отключён, а окно открывается на три секунды после голосового ответа. «Стоп» и «хватит» распознаются на колонке и прекращают текущий ответ. Spotify продолжает воспроизведение с обычным уровнем.
|
||
|
||
Штатный локальный детектор также принимает «громче», «тише», «пауза», «продолжи», «дальше» и «назад». Голосовой ассистент может показать состояние Spotify Connect, назвать текущий трек, перемотать, включить повтор или перемешивание, посмотреть и дополнить очередь. Для изменения плейлистов нужно повторно авторизовать Spotify в Mini App. Пульт показывает состояние колонки и последний известный трек. Источник состояния воспроизведения — Spotify Connect.
|
||
|
||
Тап по центру переключает воспроизведение Spotify или останавливает активный ответ. Удержание центра три секунды открывает прослушивание. Тап «−» или «+» меняет громкость на 10 процентных пунктов, удержание повторяет шаг. Свайп через три зоны от «−» к «+» включает следующий трек. Свайп обратно возвращает к началу текущего трека после пяти секунд воспроизведения и включает предыдущий в первые пять секунд.
|
||
|
||
Eleven v4 Turbo и Eleven v3 Conversational могут получать один тег интонации в начале ответа. Модель выбирает подачу при генерации текста ответа. Повседневные фразы и короткие команды остаются нейтральными. В истории сохраняется чистый текст.
|