diff --git a/core/recorder.py b/core/recorder.py index e8088c4..a6a56a2 100644 --- a/core/recorder.py +++ b/core/recorder.py @@ -16,11 +16,8 @@ import tempfile import wave from core import fay_core from core import interact - -import re - # 启动时间 (秒) -_ATTACK = 0.05 # 更快进入拾音,减少短唤醒词被漏掉的概率 +_ATTACK = 0.2 # 释放时间 (秒) _RELEASE = 0.7 @@ -88,31 +85,6 @@ class Recorder: with fay_core.auto_play_lock: fay_core.can_auto_play = True - def _norm_asr_text(self, s: str) -> str: - """ - 大厅场景:ASR 结果常见问题 - - 句首有空格/标点/语气词(嗯、啊、这个...) - - 唤醒词后跟逗号、冒号等 - 所以需要做最小必要的规范化,避免 front 模式误判为“待唤醒” - """ - if not s: - return "" - s = s.strip() - # 去掉句首标点/空白 - s = re.sub(r'^[\s,,。.!!?::、~~]+', '', s) - # 去掉句首常见语气词(按需可继续加) - s = re.sub(r'^(嗯|啊|呃|额|哦|唔|这个|那个)\s*', '', s) - return s - - def _strip_wake_prefix(self, full_text: str, wake_word: str) -> str: - """ - 去除前置唤醒词,只把“真正的问题”交给对话系统 - 例如:'小F,播放音乐' -> '播放音乐' - """ - rest = full_text[len(wake_word):] - # 吞掉唤醒词后的空白/标点 - return rest.lstrip(" \t,,。.!!?::、~~") - def __waitingResult(self, iat: asrclient, audio_data): self.processing = True t = time.time() @@ -169,83 +141,34 @@ class Recorder: self.timer.cancel() # 取消之前的计时器任务 self.timer = threading.Timer(60, self.reset_wakeup_status) # 重设计时器为60秒 self.timer.start() - - # 前置唤醒词模式(大厅优化版) - elif cfg.config['source']['wake_word_type'] == 'front': - wake_word = cfg.config['source']['wake_word'] - wake_word_list = [w.strip() for w in wake_word.split(',') if w.strip()] - - raw_text = text - text2 = self._norm_asr_text(raw_text) - + + #前置唤醒词模式 + elif cfg.config['source']['wake_word_type'] == 'front': + wake_word = cfg.config['source']['wake_word'] + wake_word_list = wake_word.split(',') wake_up = False - matched_word = None - - # 1) 规范化后做“严格句首匹配” - for w in wake_word_list: - w2 = self._norm_asr_text(w) - if w2 and text2.startswith(w2): + for word in wake_word_list: + if text.startswith(word): + wake_up_word = word wake_up = True - matched_word = w2 break - - # 2) 容错:允许唤醒词出现在句首很短范围内(防止语气词未完全清掉) - # 注意:范围要小,避免大厅误唤醒 - if not wake_up: - N = 4 # 建议 3~6,越大越容易误触发 - head = text2[:N] - for w in wake_word_list: - w2 = self._norm_asr_text(w) - if w2 and w2 in head: - wake_up = True - matched_word = w2 - # 从唤醒词出现的位置截断,确保 strip 正确 - idx = text2.find(w2) - text2 = text2[idx:] - break - if wake_up: - util.printInfo(1, self.username, f"唤醒成功!(front:{matched_word})") + util.printInfo(1, self.username, "唤醒成功!") if wsa_server.get_web_instance().is_connected(self.username): - wsa_server.get_web_instance().add_cmd({ - "panelMsg": "唤醒成功!", - "Username": self.username, - 'robot': f'http://{cfg.fay_url}:5000/robot/Listening.jpg' - }) + wsa_server.get_web_instance().add_cmd({"panelMsg": "唤醒成功!", "Username" : self.username , 'robot': f'http://{cfg.fay_url}:5000/robot/Listening.jpg'}) if wsa_server.get_instance().is_connected(self.username): - content = { - 'Topic': 'Unreal', - 'Data': {'Key': 'log', 'Value': "唤醒成功!"}, - 'Username': self.username, - 'robot': f'http://{cfg.fay_url}:5000/robot/Listening.jpg' - } + content = {'Topic': 'Unreal', 'Data': {'Key': 'log', 'Value': "唤醒成功!"}, 'Username' : self.username, 'robot': f'http://{cfg.fay_url}:5000/robot/Listening.jpg'} wsa_server.get_instance().add_cmd(content) - - # ✅ 关键:剥离唤醒词,把真正问题交给对话系统 - question = self._strip_wake_prefix(text2, matched_word) - - # 如果只说了唤醒词(或后面太短),给一句提示 - if not question: - question = "在呢,你说?" - + #去除唤醒词后语句 + question = text#[len(wake_up_word):].lstrip() self.on_speaking(question) self.processing = False else: - # ✅ 关键:打印原始识别和规范化后文本,现场好定位为何没匹配上 - util.printInfo(1, self.username, f"[!] 待唤醒!(front) ASR='{raw_text}' norm='{text2}'") + util.printInfo(1, self.username, "[!] 待唤醒!") if wsa_server.get_web_instance().is_connected(self.username): - wsa_server.get_web_instance().add_cmd({ - "panelMsg": "[!] 待唤醒!", - "Username": self.username, - 'robot': f'http://{cfg.fay_url}:5000/robot/Normal.jpg' - }) + wsa_server.get_web_instance().add_cmd({"panelMsg": "[!] 待唤醒!", "Username" : self.username , 'robot': f'http://{cfg.fay_url}:5000/robot/Normal.jpg'}) if wsa_server.get_instance().is_connected(self.username): - content = { - 'Topic': 'Unreal', - 'Data': {'Key': 'log', 'Value': "[!] 待唤醒!"}, - 'Username': self.username, - 'robot': f'http://{cfg.fay_url}:5000/robot/Normal.jpg' - } + content = {'Topic': 'Unreal', 'Data': {'Key': 'log', 'Value': "[!] 待唤醒!"}, 'Username' : self.username, 'robot': f'http://{cfg.fay_url}:5000/robot/Normal.jpg'} wsa_server.get_instance().add_cmd(content) #非唤醒模式 @@ -311,10 +234,7 @@ class Recorder: #计算音量是否满足激活拾音 level = audioop.rms(data, 2) - - # 把激活前缓存拉长,避免“唤醒词”在触发拾音前被漏掉 - # 1024帧@16kHz≈64ms/块,30块≈1.9秒 - if len(self.__history_data) >= 30: # 保存激活前的音频,以免信息掉失 + if len(self.__history_data) >= 10:#保存激活前的音频,以免信息掉失 self.__history_data.pop(0) if len(self.__history_level) >= 500: self.__history_level.pop(0)