Files
my_speaker_RPi3/commands.py
T
2025-12-25 12:01:35 +03:00

169 lines
9.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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