Initial commit: полный проект my_speaker
This commit is contained in:
+152
@@ -0,0 +1,152 @@
|
||||
# app/utils.py
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from ruamel.yaml import YAML
|
||||
from vad_core import VADPolling
|
||||
from vosk_local_STT import VoskSTT
|
||||
from commands import handle_command
|
||||
from volume import set_volume
|
||||
|
||||
# Инициализация логгера
|
||||
logger = logging.getLogger('VADApp')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.handlers.clear()
|
||||
log_format = logging.Formatter('[%(asctime)s] %(levelname)s] %(message)s', datefmt='%H:%M:%S')
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setFormatter(log_format)
|
||||
logger.addHandler(console_handler)
|
||||
logger.debug("Логгер VADApp инициализирован")
|
||||
|
||||
CONFIG_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'config.yaml')
|
||||
|
||||
def setup_logging(logging_level='INFO'):
|
||||
logger.debug(f"Установка уровня логирования: {logging_level}")
|
||||
try:
|
||||
logger.setLevel(getattr(logging, logging_level.upper(), logging.INFO))
|
||||
logger.info(f"Уровень логирования установлен: {logging_level}")
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка настройки логирования: {e}", exc_info=True)
|
||||
raise
|
||||
|
||||
def load_config():
|
||||
logger.debug("Загрузка конфигурации")
|
||||
try:
|
||||
yaml = YAML()
|
||||
yaml.preserve_quotes = True
|
||||
if not os.path.exists(CONFIG_PATH):
|
||||
logger.error(f"Файл конфигурации не найден: {CONFIG_PATH}")
|
||||
raise FileNotFoundError(f"Файл конфигурации не найден: {CONFIG_PATH}")
|
||||
with open(CONFIG_PATH, 'r', encoding='utf-8') as f:
|
||||
config = yaml.load(f) or {}
|
||||
|
||||
commands_file = config.get('commands', {}).get('commands_file', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'commands', 'commands.yaml'))
|
||||
if commands_file:
|
||||
if not os.path.exists(commands_file):
|
||||
logger.error(f"Файл команд не найден: {commands_file}")
|
||||
raise FileNotFoundError(f"Файл команд не найден: {commands_file}")
|
||||
with open(commands_file, 'r', encoding='utf-8') as cmd_file:
|
||||
config['commands'] = yaml.load(cmd_file) or {}
|
||||
config['commands_file'] = commands_file
|
||||
logger.debug(f"Команды загружены: {commands_file}")
|
||||
|
||||
config.setdefault('system', {})
|
||||
config['system'].setdefault('history_maxlen', 100)
|
||||
config['system'].setdefault('polling_interval_ms', 500)
|
||||
config['system'].setdefault('logging_level', 'INFO')
|
||||
|
||||
config.setdefault('vad', {})
|
||||
config['vad'].setdefault('mode', 1)
|
||||
config['vad'].setdefault('sample_rate', 16000)
|
||||
config['vad'].setdefault('frame_duration_ms', 30)
|
||||
config['vad'].setdefault('ring_buffer_size', 20)
|
||||
config['vad'].setdefault('speech_threshold', 0.5)
|
||||
config['vad'].setdefault('energy_threshold', 1000)
|
||||
config['vad'].setdefault('min_speech_duration_ms', 300)
|
||||
config['vad'].setdefault('record_stop_delay_sec', 1.0)
|
||||
config['vad'].setdefault('prebuffer_duration_sec', 1.0)
|
||||
config['vad'].setdefault('max_record_duration_sec', 5.0)
|
||||
config['vad'].setdefault('target_rms', 2000.0)
|
||||
config['vad'].setdefault('max_gain', 5.0)
|
||||
config['vad'].setdefault('noise_reduction_factor', 1.5)
|
||||
config['vad'].setdefault('noise_update_alpha', 0.05)
|
||||
config['vad'].setdefault('min_rms_threshold_factor', 2.0)
|
||||
config['vad'].setdefault('gain_smoothing_alpha', 0.1)
|
||||
config['vad'].setdefault('adaptive_energy_std_factor', 2.5)
|
||||
config['vad'].setdefault('adaptive_energy', True)
|
||||
config['vad'].setdefault('noise_reduction_enabled', True)
|
||||
config['vad'].setdefault('auto_gain_enabled', True)
|
||||
config['vad'].setdefault('record_on_speech', True)
|
||||
|
||||
config.setdefault('auth', {})
|
||||
config['auth'].setdefault('username', 'admin')
|
||||
config['auth'].setdefault('password', 'admin')
|
||||
|
||||
setup_logging(config['system']['logging_level'])
|
||||
logger.info("Конфигурация загружена")
|
||||
return config
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка загрузки конфигурации: {e}", exc_info=True)
|
||||
raise
|
||||
|
||||
def save_config(config):
|
||||
logger.debug("Сохранение конфигурации")
|
||||
try:
|
||||
yaml = YAML()
|
||||
yaml.indent(mapping=2, sequence=4, offset=2)
|
||||
yaml.preserve_quotes = True
|
||||
config_to_save = config.copy()
|
||||
if 'commands_file' in config_to_save:
|
||||
del config_to_save['commands_file']
|
||||
with open(CONFIG_PATH, 'w', encoding='utf-8') as f:
|
||||
yaml.dump(config_to_save, f)
|
||||
logger.info("Конфигурация сохранена")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка сохранения конфигурации: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
def init_vad_and_stt():
|
||||
logger.debug("Инициализация VAD и STT")
|
||||
try:
|
||||
config = load_config()
|
||||
commands = config.get('commands', {})
|
||||
|
||||
stt_instance = VoskSTT(
|
||||
model_path=config.get('stt', {}).get('model_path', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'models', 'vosk-model-small-ru-0.22')),
|
||||
commands_file=config.get('commands_file', os.path.join(os.path.dirname(os.path.dirname(__file__)), 'commands', 'commands.yaml')),
|
||||
sample_rate=config.get('vad', {}).get('sample_rate', 16000)
|
||||
)
|
||||
|
||||
def process_speech(audio_data, sample_rate):
|
||||
try:
|
||||
recognized = stt_instance.recognize(audio_data)
|
||||
if recognized:
|
||||
logger.info(f"Команда распознана: {recognized}")
|
||||
handle_command(recognized, commands)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка обработки речи: {e}")
|
||||
|
||||
vad_config = config.get('vad', {})
|
||||
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 инициализированы")
|
||||
return vad_instance, stt_instance, commands
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка инициализации VAD/STT: {e}", exc_info=True)
|
||||
raise
|
||||
|
||||
def cleanup_vad_and_stt(vad_instance, stt_instance):
|
||||
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}")
|
||||
Reference in New Issue
Block a user