Mutty — open-source платформа для голосового общения в реальном времени, построенная на базе LiveKit. Включает веб и десктоп-клиенты с коллаборативными модулями и AI-ботом.
Проект оригинально начат как Voice App, затем ребрендирован в Mutty.
- Голосовая связь в реальном времени (WebRTC, низкая задержка)
- Discord-подобные голосовые каналы
- Шаринг экрана со звуковыми сигналами (start/stop chime)
- Плавающие окна — коллаборативный whiteboard (tldraw) и shared notepad
- Бот-агент со встроенным AI через OpenRouter — стримит YouTube/Twitch/SoundCloud и отвечает в чате
- Чат с вложениями изображений, drag-and-drop, превью твитов
- Кроссплатформенность — веб (React) + десктоп (Tauri + Rust)
- Self-hosted — полностью под твоим контролем
Whiteboard использует tldraw — коммерческую библиотеку с платной лицензией.
- Для локальной разработки — ключ не нужен, оценочный режим работает полностью.
- Для production — если whiteboard используется активно, получите бесплатный Hobby license на tldraw.dev/r/pricing (для личных/некоммерческих проектов).
- Как указать ключ:
- Получите ключ на сайте tldraw
- Добавьте в
.env:TLDRAW_LICENSE_KEY=your_key_here
- Перезапустите frontend (
pnpm dev) — ключ встроится автоматически.
| Без ключа | С ключом |
|---|---|
| Оценочный режим | Полный функционал |
| Водянит "tldraw" на canvas (subtle watermark) | Без водянок |
┌─────────────────────┐ ┌──────────────────────────────┐
│ Web/Desktop │◄───────►│ Backend (Token Server) │
│ React + Vite │ HTTP │ Node.js / tsx │
│ :1420 / :1421 │ │ :4000 │
└──────────┬──────────┘ └──────────────┬───────────────┘
│ │
│ WebSocket / WebRTC │ HTTP (внутри Docker)
▼ ▼
┌───────────────────────────────────────────────────┐
│ LiveKit Server │
│ livekit-server:latest │
│ :7880 (WS) / :7881 (TCP) / :7882 (UDP) │
└──────────────────────┬────────────────────────────┘
│
WebSocket (внутри Docker)
▼
┌───────────────────────────────────────────────────┐
│ Agent Server (Python бот) │
│ livekit-agents + OpenRouter AI │
│ :8081 │
└───────────────────────────────────────────────────┘
Voice-app/
├── backend/ # Token Server (Node.js + tsx)
├── packages/
│ ├── web/ # Веб-клиент (React + Vite)
│ ├── desktop/ # Десктоп (Tauri v2 + Rust)
│ └── shared/ # Shared компоненты (React hooks, UI, collab)
├── agent-server/ # Python бот
└── livekit/ # Конфиги LiveKit
- Ядро WebRTC-инфраструктуры (Go), образ
livekit/livekit-server:latest - Медиа-маршрутизация, сигнализация, управление комнатами
- Порты:
7880— WebSocket (сигнализация)7881— TCP (fallback для WebRTC)7882— UDP (RTC, медиа)
- Конфиг:
livekit/livekit.prod.yaml(production) - Ключи: блок
keysв YAML должен совпадать сLIVEKIT_API_KEY/LIVEKIT_API_SECRETиз.env
- Стек: TypeScript + tsx +
livekit-server-sdkv2 + dotenv - За что отвечает: выдача JWT-токенов LiveKit для аутентификации в комнатах
- Порт:
4000 - Ключевые env:
LIVEKIT_WS_URL— URL, отдаваемый браузеру (localhostили твой домен)LIVEKIT_API_URL— авто-вычисляется из WS-URL (ws/→http/)TOKEN_CORS_ORIGINS— origins через запятую (пусто =[*])TOKEN_ROOM_MAX_LENGTH/TOKEN_IDENTITY_MAX_LENGTH/TOKEN_TTL
- Стек: React + TypeScript + Vite + Tailwind CSS + shadcn/ui + LiveKit SDK + React Router
- Порт:
1420(dev) - Фичи:
- Голос/видео, screen share
- Чат с вложениями изображений, drag-and-drop
- Коллаборативный whiteboard (tldraw + LiveKit data channels)
- Shared notepad (LiveKit data channels)
- Floating windows — drag, resize, minimize
- Стек: Tauri v2 (React frontend + Rust backend)
- Порт:
1421(dev) - Фичи:
- Все фичи веб-клиента
- Глобальные горячие клавиши (настраиваемые через UI, работают даже когда окно не в фокусе)
- Трей (сворачивание в системный луч)
- Звуки шаринга экрана (start/stop chime)
- Agent controls — меню управления ботом (режимы, качество, очередь, громкость)
- Сплэш-скрин при запуске
- Стек: React + TypeScript
- Что внутри:
floating/— система плавающих окон (drag, resize, z-index, minimize)collab/— синхронизация через LiveKit data channels (Yjs для whiteboard, JSON-reducer для notes)components/livekit/— UI компоненты комнаты (control bar, settings, chat)hooks/— React hooks (audio settings, camera, screen share, hotkeys)modules/tldraw/— tldraw-интеграция с коллаборациейmodules/notes/— shared notepad с экспортом в.txt
- Стек: Python 3.11 +
livekit-agents+yt-dlp+ffmpeg - Порт:
8081 - Модульная архитектура:
src/core/agent.py— основной оркестраторsrc/chat/— чат-шлюз и парсер командsrc/media/— стриминг, очередь воспроизведения, резолвер URLsrc/llm/— OpenRouter провайдер + промпты (AI-ассистент, поиск, плейлисты)src/memory/— SQLite memory store (история разговоров)
- Команды в чате (без "!"):
<url>— воспроизвести ссылку (YouTube / Twitch / SoundCloud / Telegram)add <url>/queue <url>— добавить в очередьskip/next— пропустить трекqueue/list— показать очередьclear— очистить очередьстоп/stop— остановитьpause/resume— пауза / продолжитьrepeat— повтор текущего трекааудио <url>— только звуквидео <url>— видео + звукyoutube <запрос>/soundcloud <запрос>— поискai <вопрос>/jarvis <вопрос>/бот <вопрос>— AI-ассистентplaylist <описание>/плейлист <описание>— AI генерирует плейлист
- AI через OpenRouter:
- Установи
OPENROUTER_API_KEYв env - Бот отвечает на вопросы, может искать и играть музыку по запросу
- Генерирует плейлисты по описанию (например, "lofi для программирования")
- Помнит контекст разговора (SQLite per room)
- Установи
git clone https://github.com/Gaigen/Voice-app.git
cd Voice-apppnpm installcp .env.example .env# LiveKit ключи (в проде — ОБЯЗАТЕЛЬНО свои!)
LIVEKIT_API_KEY=devkey
LIVEKIT_API_SECRET=secret
# URL для браузера (локально = localhost)
VITE_LIVEKIT_URL=ws://localhost:7880
VITE_TOKEN_ENDPOINT=http://localhost:4000/api/token
# Token Server
LIVEKIT_WS_URL=ws://livekit:7880
LIVEKIT_PUBLIC_WS_URL=ws://localhost:7880
# Опционально
# OPENROUTER_API_KEY=sk-or-v1-...
# AGENT_MEDIA_PROXY=http://proxy:8080
# AGENT_VIDEO_FPS=30
# AGENT_VIDEO_QUALITY=720p# Собрать и запустить все сервисы
docker-compose up -d --build# 1. Инфраструктура в Docker
docker-compose -f docker-compose.dev.yml up -d
# 2. Веб-клиент локально
cd packages/web
pnpm dev # http://localhost:1420
# 3. Десктоп локально
cd packages/desktop
pnpm tauri dev # http://localhost:1421 + Tauri window| Сервис | URL | Описание |
|---|---|---|
| Web Client | http://localhost:1420 |
Веб-интерфейс |
| Desktop Client | pnpm tauri dev |
Нативное окно |
| Token Server | http://localhost:4000 |
API выдачи токенов (/health) |
| LiveKit WS | ws://localhost:7880 |
WebSocket (сигнализация) |
| LiveKit Admin | http://localhost:7880 |
HTTP API LiveKit |
| Agent Server | http://localhost:8081 |
YouTube/стриминг бот |
| Комбо | Действие |
|---|---|
Ctrl + B |
Открыть/закрыть Whiteboard |
Ctrl + N |
Открыть/закрыть Notes |
| Комбо (дефолт) | Действие | Настраиваемый |
|---|---|---|
Ctrl + B |
Whiteboard toggle | ✅ |
Ctrl + N |
Notes toggle | ✅ |
Ctrl + M |
Mute/unmute mic | ✅ |
Ctrl + F |
Full mute toggle | ✅ |
MouseBack |
(опционально) | ✅ |
Настройка — в Settings → Hotkeys. Работает глобально, даже когда окно свёрнуто (Windows).
В .env и livekit/livekit.prod.yaml — задай реальные ключи.
# С HTTPS
VITE_LIVEKIT_URL=wss://example.com/livekit
VITE_TOKEN_ENDPOINT=https://example.com/api/token
LIVEKIT_WS_URL=wss://example.com/livekit
# Без HTTPS (по IP)
VITE_LIVEKIT_URL=ws://YOUR_SERVER_IP:7880
VITE_TOKEN_ENDPOINT=http://YOUR_SERVER_IP:4000/api/tokendocker-compose build --no-cache frontend
docker-compose up -d| Маршрут | Бэкенд |
|---|---|
/ |
web :80 |
/api/token |
backend :4000 |
/livekit |
livekit :7880 |
| Порт | Назначение |
|---|---|
80 / 443 |
HTTP/HTTPS через reverse proxy |
7880 |
WebSocket (LiveKit) |
7881 |
TCP fallback (WebRTC) |
7882/UDP |
Медиа (WebRTC) |
Для пользователей за симметричным NAT — настрой TURN в livekit.prod.yaml.
Voice-app/
├── docker-compose.yml # Production
├── docker-compose.dev.yml # Development (LiveKit + Backend)
├── .env.example # Шаблон переменных
├── pnpm-workspace.yaml # pnpm monorepo
│
├── backend/ # Token Server (Node.js + tsx)
│ ├── Dockerfile
│ ├── src/index.ts
│ ├── package.json
│ └── tsconfig.json
│
├── packages/
│ ├── web/ # Веб-клиент (React + Vite)
│ │ ├── src/
│ │ │ ├── App.tsx
│ │ │ └── ...
│ │ ├── package.json
│ │ └── vite.config.ts
│ │
│ ├── desktop/ # Десктоп (Tauri v2)
│ │ ├── src/
│ │ │ ├── App.tsx
│ │ │ ├── components/
│ │ │ └── hooks/
│ │ ├── src-tauri/ # Rust код
│ │ │ ├── src/main.rs # Глобальные хоткеи, трей
│ │ │ └── tauri.conf.json
│ │ └── package.json
│ │
│ └── shared/ # Shared компоненты
│ ├── src/
│ │ ├── floating/ # Плавающие окна (drag, resize)
│ │ ├── collab/ # Коллаб-синхронизация (Yjs, LiveKit)
│ │ ├── components/livekit/ # UI комнаты
│ │ ├── modules/
│ │ │ ├── tldraw/ # tldraw + LiveKit data channels
│ │ │ └── notes/ # Shared notepad + export .txt
│ │ ├── hooks/ # React hooks
│ │ └── config.ts # Shared константы
│ └── package.json
│
├── agent-server/ # Python бот
│ ├── Dockerfile
│ ├── main.py # Entrypoint
│ ├── requirements.txt
│ └── src/
│ ├── core/agent.py # Оркестратор
│ ├── chat/ # Чат-шлюз, парсер команд
│ ├── media/ # Стриминг, очередь, резолвер
│ ├── llm/ # OpenRouter AI
│ └── memory/ # SQLite store
│
└── livekit/ # Конфиги LiveKit
└── livekit.prod.yaml
docker-compose logs -f # смотри логи
docker-compose ps # статус- Проверь
VITE_LIVEKIT_URLв.env(должен =ws://localhost:7880) - Пересобрей:
docker-compose build --no-cache frontend && docker-compose up -d
- UDP порт
7882должен быть открыт - Для внешних подключений — настрой TURN
- Без HTTPS WebRTC работает только на localhost
LIVEKIT_API_KEY/LIVEKIT_API_SECRETв.envиlivekit/livekit.prod.yamlдолжны совпадать- Healthcheck бэкенда:
http://localhost:4000/health
- Проверь
OPENROUTER_API_KEY(опционально, без него AI-фичи не работают, но стриминг да) - Проверь
AGENT_MEDIA_PROXYесли yt-dlp не достаёт YouTube - Логи:
docker-compose logs -f agent-server
MIT