Initial commit

This commit is contained in:
2025-12-25 12:01:35 +03:00
commit c574533f63
85 changed files with 6027 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
# 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