# app/core/vad.py from fastapi import Request import os from app.core.config import get_settings from typing import Tuple, Dict, Any, Optional import logging from app.core.status import status_tracker, SystemStatus # Добавлено from app.core.history import add_recognized_phrase logger = logging.getLogger('VADApp') def get_vad_instance(request: Request): """Получение экземпляра VAD из состояния приложения""" return getattr(request.app.state, 'vad_instance', None) def get_stt_instance(request: Request): """Получение экземпляра STT из состояния приложения""" return getattr(request.app.state, 'stt_instance', None) def get_commands(request: Request): """Получение команд из состояния приложения""" return getattr(request.app.state, 'commands', None) def init_vad_and_stt(request: Request = None) -> Tuple[Any, Any, Dict[str, Any], Any]: """Инициализация VAD и STT""" logger.debug("Инициализация VAD и STT") status_tracker.set_status(SystemStatus.INITIALIZATION) # Добавлено try: # Импортируем здесь, чтобы избежать циклических импортов from vad_core import VADPolling from vosk_local_STT import VoskSTT # Исправлено с vosk_stt на vosk_local_STT from commands import handle_command from session_manager import SessionManager from volume import set_volume config = get_settings() commands = {} # Инициализация громкости аудиоустройств try: # Устанавливаем громкость для устройства воспроизведения set_volume(config.audio_settings.playback_device, config.audio_settings.playback_volume, mixer_type='Playback') # Устанавливаем громкость для устройства записи set_volume(config.audio_settings.capture_device, config.audio_settings.capture_volume, mixer_type='Capture') logger.info(f"Громкость устройств инициализирована: воспроизведение={config.audio_settings.playback_volume}%, запись={config.audio_settings.capture_volume}%") except Exception as e: logger.error(f"Ошибка при инициализации громкости: {e}") # Загружаем команды из файла if config.commands.commands_file and os.path.exists(config.commands.commands_file): from ruamel.yaml import YAML yaml = YAML() with open(config.commands.commands_file, 'r', encoding='utf-8') as f: commands = yaml.load(f) or {} # Инициализируем SessionManager session_manager = SessionManager(config.session.session_timeout_seconds) logger.info(f"SessionManager инициализирован с таймаутом {config.session.session_timeout_seconds} секунд") # Инициализируем STT stt_instance = VoskSTT( model_path=config.stt.model_path, commands_file=config.commands.commands_file, sample_rate=config.vad.sample_rate ) # Функция обработки распознанной речи def process_speech(audio_data, sample_rate): try: status_tracker.set_status(SystemStatus.RECOGNITION) # Добавлено recognized = stt_instance.recognize(audio_data) if recognized: logger.info(f"Команда распознана: {recognized}") status_tracker.set_status(SystemStatus.COMMAND_PROCESSING) # Добавлено action = handle_command(recognized, commands, session_manager) status_tracker.set_status(SystemStatus.RESPONSE) # Добавлено (предполагая, что здесь происходит ответ; если нет, удалите) # Добавляем распознанную фразу в историю if action: add_recognized_phrase(recognized, action=action) except Exception as e: logger.error(f"Ошибка обработки речи: {e}") status_tracker.set_status(SystemStatus.LISTENING) # Добавлено (возврат к прослушиванию) # Инициализируем VAD vad_config = config.vad.dict() vad_config['polling_interval_ms'] = config.system.polling_interval_ms vad_config['history_maxlen'] = config.system.history_maxlen vad_instance = VADPolling(vad_config, on_speech_end_callback=process_speech) logger.info("VAD и STT инициализированы") status_tracker.set_status(SystemStatus.LISTENING) # Добавлено return vad_instance, stt_instance, commands, session_manager except Exception as e: logger.error(f"Ошибка инициализации VAD/STT: {e}", exc_info=True) raise def cleanup_vad_and_stt(vad_instance, stt_instance): """Завершение работы VAD и STT""" logger.debug("Завершение работы VAD и STT") try: if vad_instance: logger.info("Завершаем VAD...") vad_instance.close() if stt_instance: logger.info("Завершаем STT...") stt_instance = None logger.info("VAD и STT завершены") except Exception as e: logger.error(f"Ошибка завершения VAD/STT: {e}") def restart_vad_and_stt(request: Request): """Перезапуск VAD и STT с новыми настройками""" logger.info("Перезапуск VAD и STT") status_tracker.set_status(SystemStatus.INITIALIZATION) # Добавлено try: # Завершаем текущие экземпляры vad_instance = get_vad_instance(request) stt_instance = get_stt_instance(request) cleanup_vad_and_stt(vad_instance, stt_instance) # Инициализируем новые экземпляры vad_instance, stt_instance, commands = init_vad_and_stt() # Обновляем состояние приложения request.app.state.vad_instance = vad_instance request.app.state.stt_instance = stt_instance request.app.state.commands = commands logger.info("VAD и STT перезапущены") status_tracker.set_status(SystemStatus.LISTENING) # Добавлено return True except Exception as e: logger.error(f"Ошибка перезапуска VAD/STT: {e}", exc_info=True) raise