Initial commit: полный проект my_speaker

This commit is contained in:
2025-12-25 12:16:19 +03:00
commit 8279fbb35f
85 changed files with 6027 additions and 0 deletions
+168
View File
@@ -0,0 +1,168 @@
# commands.py
import logging
import time
from datetime import datetime
from piper_TTS import synthesize_text
from app.core.config import get_settings
from volume import get_volume
def speak_text(text, voice_name=None):
"""
Синтезирует речь из текста и возвращает путь к аудиофайлу
Args:
text (str): Текст для синтеза
voice_name (str, optional): Имя голоса
Returns:
str: Путь к созданному аудиофайлу или None в случае ошибки
"""
logger = logging.getLogger('VADApp')
try:
logger.info(f"Синтезирую текст: '{text}'")
audio_path = synthesize_text(text, voice_name)
logger.info(f"Синтез завершен, файл: {audio_path}")
return audio_path
except Exception as e:
logger.error(f"Ошибка синтеза речи: {e}")
return None
def handle_command(command, commands, session_manager=None):
"""
Обрабатывает распознанную команду на основе commands.yaml и возвращает action
Args:
command (str): Распознанная команда
commands (dict): Словарь команд из commands.yaml
session_manager (SessionManager, optional): Менеджер сессий
Returns:
str: Действие, которое нужно выполнить, или None
"""
logger = logging.getLogger('VADApp')
try:
if not commands:
logger.warning("Команды не загружены")
return None
# Создаем список всех возможных совпадений с их приоритетами
matches = []
session_active = session_manager.is_session_active() if session_manager else True
min_priority = 0 if session_active else 90
# Проверяем wakewords (всегда проверяем, независимо от статуса сессии)
for wakeword_group in commands.get('Wakewords', []):
if isinstance(wakeword_group, dict):
phrases = wakeword_group.get('phrases', [])
action = wakeword_group.get('action', 'wake_assistant')
priority = wakeword_group.get('priority', 0)
if command.lower() in [p.lower() for p in phrases]:
matches.append({
'action': action,
'priority': priority
})
# Если обнаружено wakeword и сессия не активна, активируем её
if session_manager and not session_active and action == 'wake_assistant':
logger.info("Обнаружено wakeword, активируем сессию")
session_manager.start_session()
# Проверяем команды громкости (всегда проверяем, независимо от статуса сессии)
for volume_group in commands.get('Volume', []):
if isinstance(volume_group, dict):
volume_commands = volume_group.get('commands', {})
priority = volume_group.get('priority', 0)
if command.lower() in volume_commands:
action = volume_commands[command.lower()]
matches.append({
'action': action,
'priority': priority
})
# Обработка команды "какая громкость"
if action == 'get_volume':
config = get_settings()
playback_device = config.audio_settings.playback_device
capture_device = config.audio_settings.capture_device
playback_volume = get_volume(playback_device, mixer_type='Playback')
capture_volume = get_volume(capture_device, mixer_type='Capture')
if playback_volume is not None and capture_volume is not None:
logger.info(f"Текущая громкость: воспроизведение={playback_volume}%, запись={capture_volume}%")
# Здесь можно добавить код для озвучивания громкости, если есть такая возможность
else:
logger.error("Не удалось получить информацию о громкости")
# Если сессия активна или команда имеет высокий приоритет, проверяем остальные команды
if session_active:
# Проверяем команды сессии
for session_group in commands.get('Session', []):
if isinstance(session_group, dict):
phrases = session_group.get('phrases', [])
action = session_group.get('action', 'session_stop')
priority = session_group.get('priority', 0)
if command.lower() in [p.lower() for p in phrases]:
matches.append({
'action': action,
'priority': priority
})
# Если обнаружена команда завершения сессии
if session_manager and action == 'session_stop':
logger.info("Обнаружена команда завершения сессии")
session_manager.end_session()
# Проверяем текстовые команды
for text_group in commands.get('Text', []):
if isinstance(text_group, dict):
text_commands = text_group.get('commands', {})
priority = text_group.get('priority', 0)
if command.lower() in text_commands:
matches.append({
'action': text_commands[command.lower()],
'priority': priority
})
# Проверяем плагины
for plugin_group in commands.get('Plugin', []):
if isinstance(plugin_group, dict):
priority = plugin_group.get('priority', 0)
action = plugin_group.get('action', 'speak_plugins')
# Добавляем действие плагина только если не нашли других совпадений
# и сессия активна
if not matches and session_active:
matches.append({
'action': action,
'priority': priority
})
# Фильтруем совпадения по минимальному приоритету
matches = [m for m in matches if m['priority'] >= min_priority]
# Если есть совпадения, выбираем действие с наивысшим приоритетом
if matches:
# Сортируем по приоритету (от высшего к низшему)
matches.sort(key=lambda x: x['priority'], reverse=True)
action = matches[0]['action']
logger.info(f"Выполняется действие: {action} с приоритетом {matches[0]['priority']}")
# Тестовая пауза на выполение действия
session_manager.pause_session()
# Имитируем выполнение действия с использованием TTS
print("Выполняем синтез речи...")
audio_path = speak_text(f"Выполняю команду: {action}")
print(f"Синтез завершен, файл: {audio_path}")
time.sleep(2) # Пауза на 2 секунды
# Возобновляем сессию после паузы
session_manager.resume_session()
# Сбрасываем таймер сессии, если действие не завершает сессию
if session_manager and session_manager.is_session_active() and action != 'session_stop':
session_manager.reset_timer()
return action
else:
logger.warning(f"Команда не найдена в commands.yaml: {command}")
return None
except Exception as e:
logger.error(f"Ошибка обработки команды: {e}")
return None