# 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