# ποΈ Alexander Smart Speaker
**ΠΠΎΠ»ΠΎΡΠΎΠ²ΠΎΠΉ Π°ΡΡΠΈΡΡΠ΅Π½Ρ Π΄Π»Ρ Linux Ρ wake word, STT/TTS ΠΈ Π½Π°Π±ΠΎΡΠΎΠΌ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΡΡ
Π½Π°Π²ΡΠΊΠΎΠ²**
[](https://www.python.org/downloads/)
[](https://www.linux.org/)
[](LICENSE.txt)
## β¨ ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ
| Π€ΡΠ½ΠΊΡΠΈΡ | ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ |
|--------|----------|
| π **ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ ΠΏΠΎ ΠΊΠ»ΡΡΠ΅Π²ΠΎΠΌΡ ΡΠ»ΠΎΠ²Ρ** | ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ ΠΏΠΎ ΠΊΠΎΠΌΠ°Π½Π΄Π΅ `Alexandr` |
| π§ **ΠΠΈΠ°Π»ΠΎΠ³ Ρ AI** | ΠΠ·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Ρ Perplexity Ρ ΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ° |
| π **ΠΠ΅ΡΠ΅Π²ΠΎΠ΄** | ΠΠ΅ΡΠ΅Π²ΠΎΠ΄ RU β EN Ρ ΠΎΠ·Π²ΡΡΠΈΠ²Π°Π½ΠΈΠ΅ΠΌ |
| π€οΈ **ΠΠΎΠ³ΠΎΠ΄Π°** | ΠΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ ΠΏΠΎΠ³ΠΎΠ΄Π΅ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ ΠΈ ΠΏΠΎ Π½Π°Π·Π²Π°Π½ΠΈΡ Π³ΠΎΡΠΎΠ΄Π° |
| β° **Π’Π°ΠΉΠΌΠ΅ΡΡ ΠΈ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊΠΈ** | Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΡΠ°ΠΉΠΌΠ΅ΡΠ°ΠΌΠΈ, Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊΠ°ΠΌΠΈ ΠΈ ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅ΡΠ°ΠΌΠΈ |
| π **Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π³ΡΠΎΠΌΠΊΠΎΡΡΡΡ** | Π Π΅Π³ΡΠ»ΠΈΡΠΎΠ²ΠΊΠ° ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠΉ Π³ΡΠΎΠΌΠΊΠΎΡΡΠΈ |
| π΅ **Spotify ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ** | Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ (play/pause/next/current track) |
| π **ΠΠ³ΡΠ° Π² Π³ΠΎΡΠΎΠ΄Π°** | ΠΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠ°Ρ ΠΈΠ³ΡΠ° Π² Π³ΠΎΡΠΎΠ΄Π° |
## ποΈ ΠΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ°
### ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²
```mermaid
graph TB
subgraph "ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠΈΠΊΠ» (main.py)"
A[ΠΠ΅ΡΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ ΡΠΈΠΊΠ»] --> B{Π Π΅ΠΆΠΈΠΌ Π°ΠΊΡΠΈΠ²Π°ΡΠΈΠΈ}
B -->|ΠΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ wake word| C[wait_for_wakeword]
B -->|Π Π΅ΠΆΠΈΠΌ Π΄ΠΈΠ°Π»ΠΎΠ³Π°| D[listen Π² ΡΠ΅ΠΆΠΈΠΌΠ΅ follow-up]
C --> E[ΠΡΠΎΡΠ»ΡΡΠΈΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ]
D --> E
E --> F[ΠΠ½Π°Π»ΠΈΠ· ΠΊΠΎΠΌΠ°Π½Π΄Ρ]
end
subgraph "ΠΡΠ΄ΠΈΠΎ ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΠ° (app/audio/)"
C1[wakeword.py
- wait_for_wakeword
- check_wakeword_once]
E1[stt.py
- listen
- get_recognizer]
G1[tts.py
- speak
- initialize]
H1[sound_level.py
- parse_volume_text
- set_volume]
C1 -.-> E1
E1 -.-> G1
H1 -.-> G1
end
subgraph "Π―Π΄ΡΠΎ (app/core/)"
F1[commands.py
- is_stop_command
- _normalize_text]
F2[ai.py
- ask_ai_stream
- translate_text]
F3[cleaner.py
- clean_response]
F4[config.py
- ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ ΠΏΡΠΎΠ΅ΠΊΡΠ°]
F5[smalltalk.py
- get_smalltalk_response]
F --> F1
F --> F2
F --> F3
F --> F5
end
subgraph "Π€ΡΠ½ΠΊΡΠΈΠΈ (app/features/)"
I1[weather.py
- get_weather_report]
I2[timer.py
- get_timer_manager]
I3[alarm.py
- get_alarm_clock]
I4[stopwatch.py
- get_stopwatch_manager]
I5[music.py
- get_music_controller]
I6[cities_game.py
- get_cities_game]
F --> I1
F --> I2
F --> I3
F --> I4
F --> I5
F --> I6
end
subgraph "ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΊΠΎΠΌΠ°Π½Π΄"
F --> J{Π’ΠΈΠΏ ΠΊΠΎΠΌΠ°Π½Π΄Ρ}
J -->|Small talk| K[get_smalltalk_response]
J -->|ΠΠΎΠ²ΡΠΎΡ| L[ΠΠΎΠ²ΡΠΎΡ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ ΠΎΡΠ²Π΅ΡΠ°]
J -->|Π‘ΡΠΎΠΏ| M[is_stop_command]
J -->|Π’Π°ΠΉΠΌΠ΅Ρ| N[parse_command timer]
J -->|ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ| O[parse_command alarm]
J -->|Π‘Π΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ| P[parse_command stopwatch]
J -->|ΠΡΠΎΠΌΠΊΠΎΡΡΡ| Q[parse_volume_text + set_volume]
J -->|ΠΠΎΠ³ΠΎΠ΄Π°| R[get_weather_report]
J -->|ΠΡΠ·ΡΠΊΠ°| S[parse_command music]
J -->|ΠΠ΅ΡΠ΅Π²ΠΎΠ΄| T[parse_translation_request]
J -->|ΠΠΎΡΠΎΠ΄Π°| U[handle cities_game]
J -->|AI| V[ask_ai_stream]
end
subgraph "ΠΡΠ²Π΅Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ"
K --> W[clean_response]
L --> W
M --> W
N --> W
O --> W
P --> W
Q --> W
R --> W
S --> W
T --> W
U --> W
V --> W
W --> X[speak]
X --> Y[ΠΠΎΠ·Π²ΡΠ°Ρ Π² ΡΠ΅ΠΆΠΈΠΌ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ]
Y --> A
end
%% Connections
C1 -.-> A
E1 -.-> F
G1 -.-> X
F2 -.-> V
F3 -.-> W
I1 -.-> R
I2 -.-> N
I3 -.-> O
I4 -.-> P
I5 -.-> S
I6 -.-> U
style A fill:#e1f5fe
style F fill:#f3e5f5
style X fill:#e8f5e8
style Y fill:#fff3e0
```
## π οΈ Π’Π΅Ρ
Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ
| ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ | Π’Π΅Ρ
Π½ΠΎΠ»ΠΎΠ³ΠΈΡ |
|-----------|------------|
| **Wake word** | `pvporcupine` |
| **STT** | `deepgram-sdk` |
| **TTS** | `Silero` (`torch`, `torchaudio`) |
| **AI** | Perplexity API |
| **ΠΠΎΠ³ΠΎΠ΄Π°** | Open-Meteo |
| **ΠΡΠ·ΡΠΊΠ°** | Spotify Web API (`spotipy`) |
## π Π’ΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡ
- **ΠΠ‘**: Linux
- **Python**: 3.9+
- **Π‘ΠΈΡΡΠ΅ΠΌΠ½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ**:
```bash
sudo apt-get update
sudo apt-get install -y portaudio19-dev libasound2-dev mpg123
```
> π‘ ΠΠ»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ Π³ΡΠΎΠΌΠΊΠΎΡΡΡΡ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌ `pactl` ΠΈΠ»ΠΈ `amixer` (ΠΎΠ±ΡΡΠ½ΠΎ ΠΈΠ· `pulseaudio-utils`/`alsa-utils`).
## π Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°
1. **ΠΠ»ΠΎΠ½ΠΈΡΡΠΉΡΠ΅ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ**:
```bash
git clone https://github.com/your-username/alexander_smart-speaker.git
cd alexander_smart-speaker
```
2. **ΠΠ°ΡΡΡΠΎΠΉΡΠ΅ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΠΎΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΠ΅**:
```bash
python -m venv venv
source venv/bin/activate # ΠΈΠ»ΠΈ venv\Scripts\activate Π½Π° Windows
pip install -r requirements.txt
```
## βοΈ ΠΠ°ΡΡΡΠΎΠΉΠΊΠ°
1. **Π‘ΠΎΠ·Π΄Π°ΠΉΡΠ΅ ΡΠ°ΠΉΠ» ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ**:
```bash
cp .env.example .env
```
2. **ΠΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ**:
```ini
PERPLEXITY_API_KEY=your_perplexity_api_key_here
DEEPGRAM_API_KEY=your_deepgram_api_key_here
PORCUPINE_ACCESS_KEY=your_porcupine_access_key_here
```
3. **ΠΠΎΠ»Π½Π°Ρ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ** (ΠΊΠ°ΠΊ Π² `.env.example`):
```ini
PERPLEXITY_API_KEY=your_perplexity_api_key_here
PERPLEXITY_MODEL=llama-3.1-sonar-small-128k-chat
DEEPGRAM_API_KEY=your_deepgram_api_key_here
PORCUPINE_ACCESS_KEY=your_porcupine_access_key_here
PORCUPINE_SENSITIVITY=0.8
TTS_EN_SPEAKER=en_0
WEATHER_LAT=63.56
WEATHER_LON=53.69
WEATHER_CITY=Π£Ρ
ΡΠ°
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret
SPOTIFY_REDIRECT_URI=http://localhost:8888/callback
```
## βΆοΈ ΠΠ°ΠΏΡΡΠΊ
```bash
make run
# ΠΈΠ»ΠΈ
python run.py
```
## π£οΈ ΠΡΠΈΠΌΠ΅ΡΡ Π³ΠΎΠ»ΠΎΡΠΎΠ²ΡΡ
ΠΊΠΎΠΌΠ°Π½Π΄
| ΠΠ°ΡΠ΅Π³ΠΎΡΠΈΡ | ΠΠΎΠΌΠ°Π½Π΄Ρ |
|-----------|---------|
| **ΠΠΊΡΠΈΠ²Π°ΡΠΈΡ** | `Alexandr` |
| **ΠΠΈΠ°Π»ΠΎΠ³** | `ΠΠΎΡΠ΅ΠΌΡ Π½Π΅Π±ΠΎ Π³ΠΎΠ»ΡΠ±ΠΎΠ΅?` |
| **ΠΠΎΠ³ΠΎΠ΄Π°** | `ΠΠ°ΠΊΠ°Ρ ΡΠ΅ΠΉΡΠ°Ρ ΠΏΠΎΠ³ΠΎΠ΄Π°?`, `ΠΠΎΠ³ΠΎΠ΄Π° Π² ΠΠΎΡΠΊΠ²Π΅` |
| **ΠΠ΅ΡΠ΅Π²ΠΎΠ΄** | `ΠΠ΅ΡΠ΅Π²Π΅Π΄ΠΈ Π½Π° Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΈΠΉ: ΠΊΠ°ΠΊ Π΄Π΅Π»Π°` |
| **Π’Π°ΠΉΠΌΠ΅Ρ** | `ΠΠΎΡΡΠ°Π²Ρ ΡΠ°ΠΉΠΌΠ΅Ρ Π½Π° 5 ΠΌΠΈΠ½ΡΡ` |
| **ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ** | `ΠΠΎΡΡΠ°Π²Ρ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ Π½Π° 7:30`, `ΠΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ ΠΏΠΎ Π±ΡΠ΄Π½ΡΠΌ Π² 8:00` |
| **Π‘Π΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ** | `ΠΠ°ΠΏΡΡΡΠΈ ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ`, `ΠΠΎΠΊΠ°ΠΆΠΈ Π°ΠΊΡΠΈΠ²Π½ΡΠ΅ ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅ΡΡ` |
| **ΠΡΠΎΠΌΠΊΠΎΡΡΡ** | `ΠΡΠΎΠΌΠΊΠΎΡΡΡ 5` |
| **Spotify** | `ΠΠΊΠ»ΡΡΠΈ ΠΌΡΠ·ΡΠΊΡ`, `ΠΠ°ΡΠ·Π°`, `Π§ΡΠΎ ΡΠ΅ΠΉΡΠ°Ρ ΠΈΠ³ΡΠ°Π΅Ρ` |
| **ΠΠ³ΡΠ°** | `ΠΠ°Π²Π°ΠΉ ΡΡΠ³ΡΠ°Π΅ΠΌ Π² Π³ΠΎΡΠΎΠ΄Π°` |
| **ΠΡΡΠ°Π½ΠΎΠ²ΠΊΠ°** | `Π‘ΡΠΎΠΏ`, `Π₯Π²Π°ΡΠΈΡ`, `ΠΠΎΠ²ΡΠΎΡΠΈ` |
## π οΈ ΠΠΎΠ»Π΅Π·Π½ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ
| ΠΠΎΠΌΠ°Π½Π΄Π° | ΠΠ°Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ |
|---------|------------|
| `make run` | ΠΠ°ΠΏΡΡΠΊ Π°ΡΡΠΈΡΡΠ΅Π½ΡΠ° |
| `make check` | ΠΠ°Π·ΠΎΠ²Π°Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ° |
| `make qwen-context` | Π‘ΠΎΠ±ΡΠ°ΡΡ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ ΠΏΡΠΎΠ΅ΠΊΡΠ° |
## π Π‘ΡΡΡΠΊΡΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ°
```
alexander_smart-speaker/
βββ run.py # ΡΠΎΡΠΊΠ° Π²Ρ
ΠΎΠ΄Π°
βββ app/
β βββ main.py # Π³Π»Π°Π²Π½ΡΠΉ ΡΠΈΠΊΠ» Π°ΡΡΠΈΡΡΠ΅Π½ΡΠ°
β βββ audio/ # wake word, STT, TTS, Π³ΡΠΎΠΌΠΊΠΎΡΡΡ
β βββ core/ # ΠΊΠΎΠ½ΡΠΈΠ³, AI, ΡΠΎΡΡΠΈΠ½Π³ ΠΊΠΎΠΌΠ°Π½Π΄, ΡΡΠΈΠ»ΠΈΡΡ
β βββ features/ # ΠΏΠΎΠ³ΠΎΠ΄Π°, Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ, ΡΠ°ΠΉΠΌΠ΅Ρ, ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅Ρ, ΠΌΡΠ·ΡΠΊΠ°, Π³ΠΎΡΠΎΠ΄Π°
βββ assets/ # ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΈ Π·Π²ΡΠΊΠΈ
βββ data/ # ΡΠΎΡ
ΡΠ°Π½Π΅Π½Π½ΡΠ΅ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊΠΈ/ΡΠ°ΠΉΠΌΠ΅ΡΡ/ΡΠ΅ΠΊΡΠ½Π΄ΠΎΠΌΠ΅ΡΡ
βββ scripts/ # ΡΠΊΡΠΈΠΏΡΡ Π΄Π»Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ ΠΈ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°Π½ΠΈΡ
```
## π§ ΠΠΈΠ°Π³Π½ΠΎΡΡΠΈΠΊΠ° ΠΏΡΠΎΠ±Π»Π΅ΠΌ
| ΠΡΠΎΠ±Π»Π΅ΠΌΠ° | Π Π΅ΡΠ΅Π½ΠΈΠ΅ |
|----------|---------|
| ΠΡΠΈΠ±ΠΊΠΈ STT/AI | ΠΡΠΎΠ²Π΅ΡΡΡΠ΅ ΠΊΠ»ΡΡΠΈ Π² `.env` |
| ΠΠ΅Ρ Π·Π²ΡΠΊΠ° | ΠΡΠΎΠ²Π΅ΡΡΡΠ΅ ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ΅ ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ Π²ΡΠ²ΠΎΠ΄Π° ΠΈ ΡΡΠΈΠ»ΠΈΡΡ `pactl`/`amixer` |
| ΠΠ΅ ΠΈΠ³ΡΠ°Π΅Ρ Π±ΡΠ΄ΠΈΠ»ΡΠ½ΠΈΠΊ/ΡΠ°ΠΉΠΌΠ΅Ρ | Π£Π±Π΅Π΄ΠΈΡΠ΅ΡΡ, ΡΡΠΎ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ `mpg123` |
| Spotify Π½Π΅ ΡΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ | ΠΡΠΎΠ²Π΅ΡΡΡΠ΅ `SPOTIFY_*`, Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΡ ΠΈ Π½Π°Π»ΠΈΡΠΈΠ΅ Π°ΠΊΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΡΡΡΡΠΎΠΉΡΡΠ²Π° |
## π ΠΠΈΡΠ΅Π½Π·ΠΈΡ
MIT, ΡΠΌ. [LICENSE.txt](LICENSE.txt).
---
**ΠΡΠ»ΠΈ Π²Π°ΠΌ ΠΏΠΎΠ½ΡΠ°Π²ΠΈΠ»ΡΡ ΠΏΡΠΎΠ΅ΠΊΡ, ΠΏΠΎΡΡΠ°Π²ΡΡΠ΅ β Π·Π²Π΅Π·Π΄Ρ!**