def _non_block_listen(self, hello, lvl, file_path): max_play_time = 120 # максимальное время воспроизведения приветствия max_wait_time = 10 # ожидание после приветствия r = sr.Recognizer() mic = sr.Microphone(device_index=self.get_mic_index()) with mic as source: # Слушаем шум 1 секунду, потом распознаем, если раздажает задержка можно закомментировать. energy_threshold = self.energy.correct(r, source) if self._cfg.gts('alarmtts') and not hello: self._play.play(self._cfg.path['dong'], lvl) start_wait = time.time() if file_path: self._play.play(file_path, lvl) # Начинаем фоновое распознавание голосом после того как запустился плей. listener = NonBlockListener(r=r, source=mic, phrase_time_limit=self._cfg.gts('phrase_time_limit', 15)) if file_path: while listener.work() and self._play.really_busy() and \ time.time() - start_wait < max_play_time and self._work: # Ждем пока время не выйдет, голос не распознался и файл играет time.sleep(0.01) self._play.quiet() start_wait2 = time.time() while listener.work() and time.time() - start_wait2 < max_wait_time and self._work: # ждем еще секунд 10 time.sleep(0.01) record_time = time.time() - start_wait listener.stop() return listener.audio, record_time, energy_threshold
def __init__(self, cfg, play_, log, tts): self.log = log self._cfg = cfg self.sys_say = Phrases(log, cfg) self._lock = threading.Lock() self._work = True self._play = play_ self._tts = tts self.energy = utils.EnergyControl(cfg, play_) self._recognizer = sr.Recognizer() try: self.max_mic_index = len(sr.Microphone().list_microphone_names()) - 1 except OSError as e: self.log('Error get list microphones: {}'.format(e), logger.CRIT) self.max_mic_index = -2
def start(self): self._terminate = False while not self._interrupted(): with sr.Microphone() as source: r = sr.Recognizer(self._interrupted, self._cfg.gts('sensitivity'), self._hotword_callback) energy_threshold = self._stt.energy.correct(r, source) try: adata = r.listen(source, 5, self._cfg.gts('phrase_time_limit'), (self._cfg.path['home'], self._cfg.path['models_list'])) except sr.WaitTimeoutError: self._stt.energy.set(None) continue except sr.Interrupted: self._stt.energy.set(energy_threshold) continue model = r.get_model if model < 1: continue self._adata_parse(adata, model, energy_threshold)
def _voice_record(self, hello: str, save_to: str, convert_rate=None, convert_width=None): lvl = 5 # Включаем монопольный режим file_path = self._tts(hello)() self._play.say(file_path, lvl, True, is_file=True, blocking=120) with sr.Microphone(device_index=self.get_mic_index()) as source: r = sr.Recognizer() r.adjust_for_ambient_noise(source) self._play.play(self._cfg.path['ding'], lvl, blocking=3) record_time = time.time() try: adata = r.listen(source=source, timeout=5, phrase_time_limit=10) except sr.WaitTimeoutError as e: return str(e) if time.time() - record_time < 0.5: return LNG['err_voice_record'] try: with open(save_to, "wb") as f: f.write(adata.get_wav_data(convert_rate, convert_width)) except IOError as err: return str(err) else: return None
def _block_listen(self, hello, lvl, file_path, self_call=False): with sr.Microphone(device_index=self.get_mic_index()) as source: r = sr.Recognizer() if self._cfg.gts('alarmtts') and not hello: self._play.play(self._cfg.path['dong'], lvl, wait=0.01, blocking=2) if file_path: self._play.play(file_path, lvl, wait=0.01, blocking=120) energy_threshold = self.energy.correct(r, source) record_time = time.time() try: audio = r.listen(source, timeout=10, phrase_time_limit=self._cfg.gts('phrase_time_limit', 15)) except sr.WaitTimeoutError: audio = None record_time = time.time() - record_time if record_time < 0.5 and not self_call: # Если от инициализации микрофона до записи прошло больше 20-35 сек, то запись ломается # Игнорируем полученную запись и запускаем новую, без приветствий self.log('Long ask fix!', logger.DEBUG) return self._block_listen(hello=True, lvl=lvl, file_path=None, self_call=True) else: return audio, record_time, energy_threshold