import json import os import struct import time import noisereduce as nr import pvporcupine import vosk import yaml from fuzzywuzzy import fuzz from pvrecorder import PvRecorder import config from utils import execute_cmd, play class Jarvis: def __init__(self): self.recorder = None self.CDIR = os.getcwd() self.VA_CMD_LIST = yaml.safe_load(open('commands.yaml', encoding='utf8')) self.porcupine = pvporcupine.create( access_key=config.PICOVOICE_TOKEN, keywords=['jarvis'], sensitivities=[1] ) self.kaldi_rec = vosk.KaldiRecognizer(vosk.Model("model_large"), 16000) def main(self): self.recorder = PvRecorder( device_index=config.MICROPHONE_INDEX, frame_length=self.porcupine.frame_length ) self.recorder.start() self.play("run") time.sleep(0.5) ltc = time.time() - 1000 while True: try: pcm = self.recorder.read() reduced_audio = nr.reduce_noise( y=pcm, sr=16000, prop_decrease=0.6 ) if self.porcupine.process(reduced_audio) >= 0: self.recorder.stop() self.play("greet", True) self.recorder.start() ltc = time.time() while time.time() - ltc <= 10: pcm = self.recorder.read() sp = struct.pack("h" * len(pcm), *pcm) if self.kaldi_rec.AcceptWaveform(sp): if self.va_respond(json.loads(self.kaldi_rec.Result())["text"]): ltc = time.time() break except Exception as err: print(f"Unexpected {err=}, {type(err)=}") raise def va_respond(self, voice: str): print(f"Распознано: {voice}") for x in config.VA_ALIAS + config.VA_TBR: voice = voice.replace(x, "").strip() rc = {'cmd': '', 'percent': 0} for c, v in self.VA_CMD_LIST.items(): for x in v: vrt = fuzz.partial_ratio(voice.lower(), x.lower()) if vrt > rc['percent']: rc['cmd'] = c rc['percent'] = vrt if len(rc['cmd'].strip()) <= 0: return False elif rc['percent'] < 70 or rc['cmd'] not in self.VA_CMD_LIST.keys(): self.play("not_found") time.sleep(1) return False else: execute_cmd.execute_cmd(self, rc['cmd']) return True def play(self, phrase, wait_done=True): play.play(self, phrase, wait_done)