169 lines
9.1 KiB
Python
169 lines
9.1 KiB
Python
# 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
|