Улучшенная работа погоды + ускорение работы + фикс неработоспособности после пары часов
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
112
app/main.py
112
app/main.py
@@ -20,6 +20,7 @@ import re
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from collections import deque
|
||||
|
||||
# Для воспроизведения звуков (mp3)
|
||||
@@ -61,8 +62,14 @@ def signal_handler(sig, frame):
|
||||
Позволяет корректно завершить работу программы, освободив ресурсы (микрофон, модели).
|
||||
"""
|
||||
print("\n\n👋 Завершение работы...")
|
||||
cleanup_wakeword() # Остановка Porcupine
|
||||
cleanup_stt() # Остановка Deepgram
|
||||
try:
|
||||
cleanup_wakeword() # Остановка Porcupine
|
||||
except Exception as e:
|
||||
print(f"Ошибка при остановке wakeword: {e}")
|
||||
try:
|
||||
cleanup_stt() # Остановка Deepgram
|
||||
except Exception as e:
|
||||
print(f"Ошибка при остановке STT: {e}")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@@ -180,8 +187,20 @@ def main():
|
||||
# (True = режим диалога, слушаем сразу. False = ждем "Alexandr")
|
||||
skip_wakeword = False
|
||||
|
||||
# Переменная для отслеживания последней проверки здоровья STT
|
||||
last_stt_check = time.time()
|
||||
|
||||
# БЕСКОНЕЧНЫЙ ЦИКЛ РАБОТЫ
|
||||
while True:
|
||||
# Периодическая проверка здоровья STT каждые 10 минут
|
||||
if time.time() - last_stt_check > 600: # 10 минут = 600 секунд
|
||||
try:
|
||||
recognizer = get_recognizer()
|
||||
if hasattr(recognizer, 'check_connection_health'):
|
||||
recognizer.check_connection_health()
|
||||
last_stt_check = time.time()
|
||||
except Exception as e:
|
||||
print(f"Ошибка при проверке здоровья STT: {e}")
|
||||
try:
|
||||
# Гарантируем, что микрофон детектора wake word освобожден
|
||||
stop_wakeword_monitoring()
|
||||
@@ -201,8 +220,8 @@ def main():
|
||||
|
||||
# --- Шаг 1: Активация ---
|
||||
if not skip_wakeword:
|
||||
# Ожидание фразы "Alexandr". Используем таймаут 1 сек, чтобы часто проверять будильники.
|
||||
detected = wait_for_wakeword(timeout=1.0)
|
||||
# Ожидание фразы "Alexandr". Используем таймаут 0.5 сек, чтобы чаще проверять будильники.
|
||||
detected = wait_for_wakeword(timeout=0.5)
|
||||
|
||||
# Если время вышло, а фразы не было — начинаем цикл заново (проверяем будильники)
|
||||
if not detected:
|
||||
@@ -212,13 +231,34 @@ def main():
|
||||
if ding_sound:
|
||||
ding_sound.play()
|
||||
|
||||
# Фраза услышана! Слушаем команду пользователя (7 секунд тишины макс)
|
||||
user_text = listen(timeout_seconds=7.0)
|
||||
# Фраза услышана! Слушаем команду пользователя (5 секунд тишины макс)
|
||||
try:
|
||||
user_text = listen(timeout_seconds=5.0)
|
||||
except Exception as e:
|
||||
print(f"Ошибка при прослушивании: {e}")
|
||||
print("Переинициализация STT...")
|
||||
try:
|
||||
cleanup_stt()
|
||||
get_recognizer().initialize()
|
||||
except Exception as init_error:
|
||||
print(f"Ошибка переинициализации STT: {init_error}")
|
||||
continue # Продолжаем цикл
|
||||
else:
|
||||
# Режим диалога (Follow-up): ждем продолжения речи без "Alexandr"
|
||||
print("👂 Слушаю продолжение диалога (5 сек)...")
|
||||
# Ждем начала речи 5 сек. Если начали говорить, слушаем до 10 сек.
|
||||
user_text = listen(timeout_seconds=10.0, detection_timeout=5.0)
|
||||
print("👂 Слушаю продолжение диалога (3 сек)...")
|
||||
# Ждем начала речи 3 сек. Если начали говорить, слушаем до 7 сек.
|
||||
try:
|
||||
user_text = listen(timeout_seconds=7.0, detection_timeout=3.0)
|
||||
except Exception as e:
|
||||
print(f"Ошибка при прослушивании: {e}")
|
||||
print("Переинициализация STT...")
|
||||
try:
|
||||
cleanup_stt()
|
||||
get_recognizer().initialize()
|
||||
except Exception as init_error:
|
||||
print(f"Ошибка переинициализации STT: {init_error}")
|
||||
skip_wakeword = False
|
||||
continue
|
||||
|
||||
if not user_text:
|
||||
# Пользователь промолчал — выходим из режима диалога, засыпаем.
|
||||
@@ -326,10 +366,42 @@ def main():
|
||||
"нужен ли зонт",
|
||||
"брать ли зонт",
|
||||
"прогноз погоды",
|
||||
"че там на улице",
|
||||
"что там на улице",
|
||||
"как на улице",
|
||||
"как на улице-то",
|
||||
]
|
||||
|
||||
if any(trigger in user_text.lower() for trigger in weather_triggers):
|
||||
weather_report = get_weather_report()
|
||||
# Проверяем, содержит ли запрос информацию о конкретном городе
|
||||
requested_city = None
|
||||
user_text_lower = user_text.lower()
|
||||
|
||||
# Проверяем наличие упоминания города в запросе (например, "погода в Нью-Йорке", "какая погода в Москве")
|
||||
import re
|
||||
city_patterns = [
|
||||
r"в\s+городе\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)", # "в городе Волгоград"
|
||||
r"в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)", # "в Нью-Йорке" - улучшенный паттерн для составных названий
|
||||
r"погода\s+в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)", # "погода в Москве" - улучшенный паттерн
|
||||
r"погода\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)\s+(?:какая|сейчас|там)", # "погода Москва какая"
|
||||
r"(?:какая|как)\s+погода\s+в\s+([а-яёa-z]+[-\s]*[а-яёa-z]*(?:[-\s]+[а-яёa-z]+)*)", # "какая погода в Москве"
|
||||
]
|
||||
|
||||
for pattern in city_patterns:
|
||||
match = re.search(pattern, user_text_lower, re.IGNORECASE)
|
||||
if match:
|
||||
potential_city = match.group(1).strip()
|
||||
# Проверяем, что это не местоимение или другое слово, а реально название города
|
||||
invalid_words = ["этом", "том", "той", "тут", "здесь", "там", "всё", "все", "всей", "всего", "всем", "всеми", "городе", "город", "село", "деревня", "посёлок", "аул", "станция", "область", "район", "край", "республика"]
|
||||
if potential_city and len(potential_city) > 1 and not any(word in potential_city for word in invalid_words):
|
||||
requested_city = potential_city.title() # Приводим к формату "Нью-Йорк", "Москва"
|
||||
break
|
||||
|
||||
# Проверяем, содержит ли запрос одну из погодных команд
|
||||
has_weather_trigger = any(trigger in user_text_lower for trigger in weather_triggers)
|
||||
|
||||
if has_weather_trigger:
|
||||
from .features.weather import get_weather_report
|
||||
weather_report = get_weather_report(requested_city)
|
||||
clean_report = clean_response(weather_report, language="ru")
|
||||
speak(clean_report)
|
||||
last_response = clean_report
|
||||
@@ -362,9 +434,21 @@ def main():
|
||||
)
|
||||
speak(prompt)
|
||||
# Слушаем саму фразу на нужном языке
|
||||
text_to_translate = listen(
|
||||
timeout_seconds=7.0, detection_timeout=5.0, lang=source_lang
|
||||
)
|
||||
try:
|
||||
text_to_translate = listen(
|
||||
timeout_seconds=7.0, detection_timeout=5.0, lang=source_lang
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Ошибка при прослушивании для перевода: {e}")
|
||||
print("Переинициализация STT...")
|
||||
try:
|
||||
cleanup_stt()
|
||||
get_recognizer().initialize()
|
||||
except Exception as init_error:
|
||||
print(f"Ошибка переинициализации STT: {init_error}")
|
||||
speak("Произошла ошибка при распознавании речи.")
|
||||
skip_wakeword = False
|
||||
continue
|
||||
|
||||
if not text_to_translate:
|
||||
speak("Я не расслышал текст для перевода.")
|
||||
|
||||
Reference in New Issue
Block a user