first commit
This commit is contained in:
119
main.py
Normal file
119
main.py
Normal file
@@ -0,0 +1,119 @@
|
||||
"""
|
||||
Smart Speaker - Main Application
|
||||
Голосовой ассистент с wake word detection, STT, AI и TTS.
|
||||
|
||||
Flow:
|
||||
1. Wait for wake word ("Alexandr")
|
||||
2. Listen to user speech (STT)
|
||||
3. Send query to AI (Perplexity)
|
||||
4. Clean response from markdown
|
||||
5. Speak response (TTS)
|
||||
6. Loop back to step 1
|
||||
"""
|
||||
import signal
|
||||
import sys
|
||||
|
||||
from wakeword import wait_for_wakeword, cleanup as cleanup_wakeword, check_wakeword_once
|
||||
from stt import listen, cleanup as cleanup_stt
|
||||
from ai import ask_ai
|
||||
from cleaner import clean_response
|
||||
from tts import speak, initialize as init_tts
|
||||
from sound_level import set_volume, parse_volume_text
|
||||
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
"""Handle Ctrl+C gracefully."""
|
||||
print("\n\n👋 Завершение работы...")
|
||||
cleanup_wakeword()
|
||||
cleanup_stt()
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def main():
|
||||
"""Main application loop."""
|
||||
print("=" * 50)
|
||||
print("🔊 УМНАЯ КОЛОНКА")
|
||||
print("=" * 50)
|
||||
print("Скажите 'Alexandr' для активации")
|
||||
print("Нажмите Ctrl+C для выхода")
|
||||
print("=" * 50)
|
||||
print()
|
||||
|
||||
# Setup signal handler for graceful exit
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
# Pre-initialize TTS model (takes a few seconds)
|
||||
print("⏳ Инициализация...")
|
||||
init_tts()
|
||||
print()
|
||||
|
||||
# Main loop
|
||||
skip_wakeword = False
|
||||
while True:
|
||||
try:
|
||||
# Step 1: Wait for wake word
|
||||
if not skip_wakeword:
|
||||
wait_for_wakeword()
|
||||
|
||||
skip_wakeword = False
|
||||
|
||||
# Step 2: Listen to user speech
|
||||
user_text = listen(timeout_seconds=7.0)
|
||||
|
||||
if not user_text:
|
||||
speak("Извините, я вас не расслышал. Попробуйте ещё раз.")
|
||||
continue
|
||||
|
||||
# Check for volume command
|
||||
if user_text.lower().startswith("громкость"):
|
||||
try:
|
||||
# Remove "громкость" prefix and strip whitespace
|
||||
vol_str = user_text.lower().replace("громкость", "", 1).strip()
|
||||
|
||||
# Try to parse the number
|
||||
level = parse_volume_text(vol_str)
|
||||
|
||||
if level is not None:
|
||||
if set_volume(level):
|
||||
speak(f"Громкость установлена на {level}")
|
||||
else:
|
||||
speak("Не удалось установить громкость.")
|
||||
else:
|
||||
speak("Я не понял число громкости. Скажите число от одного до десяти.")
|
||||
|
||||
continue
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка громкости: {e}")
|
||||
speak("Не удалось изменить громкость.")
|
||||
continue
|
||||
|
||||
# Step 3: Send to AI
|
||||
ai_response = ask_ai(user_text)
|
||||
|
||||
# Step 4: Clean response
|
||||
clean_text = clean_response(ai_response)
|
||||
|
||||
# Step 5: Speak response (with wake word interrupt support)
|
||||
completed = speak(clean_text, check_interrupt=check_wakeword_once)
|
||||
|
||||
# If interrupted by wake word, go back to waiting for wake word
|
||||
if not completed:
|
||||
print("⏹️ Ответ прерван - слушаю следующий вопрос")
|
||||
skip_wakeword = True
|
||||
continue
|
||||
|
||||
print()
|
||||
print("-" * 30)
|
||||
print()
|
||||
|
||||
# Step 6: Loop continues...
|
||||
|
||||
except KeyboardInterrupt:
|
||||
signal_handler(None, None)
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка: {e}")
|
||||
speak("Произошла ошибка. Попробуйте ещё раз.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user