| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- #!/usr/bin/env python3
- # coding=utf-8
- from utils.logger import logger
- from core.aiui.recorder import Recorder
- import handlers.aiui.pyaiui as pyaiui
- from handlers.aiui.pyAIUIConstant import AIUIConstant
- import json5
- import os
- import sys
- import random
- import json
- from threading import Thread
- import time
- from handlers.aiui.EventListener import EventListener, EventData
- from pathlib import Path
- CHUNK = 2048
- # 使用相对路径配置
- script_path = Path(__file__).resolve()
- BASE_DIR = script_path.parent.parent.parent
- cfg_file = os.path.join(BASE_DIR, "config", "aiui", "cfg", "aiui.cfg")
- WAITING = 0
- ABORT = -1
- ALLOW = 1
- def read_json5(path):
- try:
- with open(path, "r", encoding="utf-8") as f:
- return json5.loads(f.read())
- except Exception as e:
- logger.error("{},{}".format(e, __file__))
- return None
- class AIUINode():
- def __init__(self, event_listener, debug=False, wakeup_mute=False):
- self.agent_status = None
- event_listener.set_agent(self)
- self.event_listener = event_listener
- self.agent = pyaiui.IAIUIAgent.createAgent(json5.dumps(
- read_json5(cfg_file), quote_keys=True), event_listener)
- self.__recorder_ = None
- self.is_recording = False
- self.recorder_states = WAITING # -1:中断状态;0:等待状态;1:允许录音状态
- self.wakeup_mute = wakeup_mute
- self.is_hlw = False
- self.set_is_hlw()
- self.running = True
- def text_to_speak_multiple_options_callback(self, text, vcn="qige", speed=50, pitch=50, volume=50):
- self.cmd_tts(text, vcn, speed, pitch, volume)
- return True
- def direct_control_callback(self, text):
- self.event_listener.EventNLP(EventData({"text": text}))
- return True
- def text_to_speak_callback(self, text):
- self.cmd_tts(text)
- return True
- def set_is_hlw(self):
- # 简化HLW检测逻辑
- self.is_hlw = False
- def cmd_tts(self, text, vcn="qige", speed=50, pitch=50, volume=50):
- text = pyaiui.Buffer.create(bytes(text, encoding="utf-8"))
- TTSMsg = pyaiui.IAIUIMessage.create(
- AIUIConstant.CMD_TTS, 1, 0, "text_encoding=utf-8,vcn={},ent=x,speed={},pitch={},volume={}".format(vcn, speed, pitch, volume), text)
- self.agent.sendMessage(TTSMsg)
- TTSMsg.destroy()
- def cmd_tts_stop(self):
- text = pyaiui.Buffer.create(bytes("", encoding="utf-8"))
- TTSMsg = pyaiui.IAIUIMessage.create(
- AIUIConstant.CMD_TTS, 2, 0, "text_encoding=utf-8,vcn=qige,ent=x", text)
- self.agent.sendMessage(TTSMsg)
- TTSMsg.destroy()
- def wakeup_callback(self, msg=None):
- self.recorder_states = ABORT # 中断上一次录音等待
- self.getState()
- if self.is_recording:
- self.reset_wakeup_agent()
- self.is_recording = False
- if self.agent_status != AIUIConstant.STATE_WORKING:
- self.wakeup_agent()
- # 简化唤醒处理,直接开始录音
- logger.info("🎤 AIUI唤醒,开始录音")
- self.recorder_states = ALLOW # 直接允许录音
- Thread(target=self.__wait_play_to_start_record).start()
- def __wait_play_to_start_record(self):
- # 简化等待逻辑,直接开始录音
- self.recorder_states = ALLOW # 直接赋值允许录音
- self.start_record()
- def start_record(self):
- logger.info("开始录音...")
- self.is_recording = True
- if self.is_hlw == False:
- logger.info("启动非HLW录音模式")
- # 使用连续录音循环
- import threading
- threading.Thread(target=self.__continuous_record,
- daemon=True).start()
- else:
- logger.info("HLW录音模式已启用")
- @property
- def __recorder(self):
- if self.__recorder_ == None:
- self.__recorder_ = Recorder(CHUNK)
- return self.__recorder_
- def __start_record(self):
- """单次录音会话"""
- logger.info("录音流已启动,开始接收音频数据...")
- audio_count = 0
- for data in self.__recorder.read():
- if self.is_recording:
- audio_count += 1
- if audio_count % 100 == 0: # 每100个音频块记录一次
- logger.info(f"已接收 {audio_count} 个音频块")
- self.audio_stream_callback(data)
- else:
- logger.info("录音已停止")
- break
- logger.info(f"录音流结束,总共接收 {audio_count} 个音频块")
- def __continuous_record(self):
- """连续录音循环"""
- while self.running and self.recorder_states == ALLOW:
- self.is_recording = True
- self.__start_record()
- # 录音结束后短暂等待
- if self.running and self.recorder_states == ALLOW:
- logger.info("等待重新开始录音...")
- time.sleep(1)
- def audio_stream_callback(self, data):
- if self.is_recording:
- if self.is_hlw:
- audio_buffer = pyaiui.Buffer.create(data.data)
- self.record_stream_call_back(data.data)
- else:
- audio_buffer = pyaiui.Buffer.create(data)
- self.record_stream_call_back(data)
- self.cmd_write_audio(audio_buffer)
- else:
- logger.debug("录音已停止,跳过音频数据处理")
- def record_stream_call_back(self, buffer):
- pass
- def wakeup_agent(self):
- wakeup_msg = pyaiui.IAIUIMessage.create(AIUIConstant.CMD_WAKEUP)
- self.agent.sendMessage(wakeup_msg)
- wakeup_msg.destroy()
- def reset_wakeup_agent(self):
- reset_wakeup_msg = pyaiui.IAIUIMessage.create(
- AIUIConstant.CMD_RESET_WAKEUP)
- self.agent.sendMessage(reset_wakeup_msg)
- reset_wakeup_msg.destroy()
- def getState(self):
- get_state_msg = pyaiui.IAIUIMessage.create(AIUIConstant.CMD_GET_STATE)
- self.agent.sendMessage(get_state_msg)
- get_state_msg.destroy()
- def cmd_write_audio(self, audio_buffer):
- writeMsg = pyaiui.IAIUIMessage.create(
- AIUIConstant.CMD_WRITE, 0, 0, "data_type=audio", audio_buffer)
- self.agent.sendMessage(writeMsg)
- writeMsg.destroy()
- # 添加调试日志,每1000个音频块记录一次
- if hasattr(self, '_audio_sent_count'):
- self._audio_sent_count += 1
- else:
- self._audio_sent_count = 1
- if self._audio_sent_count % 1000 == 0:
- logger.info(f"已发送 {self._audio_sent_count} 个音频块给AIUI引擎")
- def cmd_write_text(self, text):
- text = pyaiui.Buffer.create(bytes(text, encoding="utf-8"))
- writeMsg = pyaiui.IAIUIMessage.create(
- AIUIConstant.CMD_WRITE, 0, 0, "data_type=text", text)
- self.agent.sendMessage(writeMsg)
- writeMsg.destroy()
- def stop_write(self):
- writeMsgStop = pyaiui.IAIUIMessage.create(
- AIUIConstant.CMD_STOP_WRITE, params="data_type=audio")
- self.agent.sendMessage(writeMsgStop)
- writeMsgStop.destroy()
- def start(self, spin=True):
- self.cmd_tts_stop()
- # 唤醒AIUI引擎
- logger.info("正在唤醒AIUI引擎...")
- self.wakeup_agent()
- # 等待引擎启动
- time.sleep(1)
- # 设置录音状态为允许录音
- logger.info("设置录音状态为允许录音...")
- self.recorder_states = ALLOW
- # 启动录音
- logger.info("正在启动录音...")
- self.start_record()
- if spin: # 是否阻塞运行
- while self.running:
- time.sleep(0.1)
- def shutdown(self):
- self.running = False
- def load_sn():
- return "yd-00:00:00:00:00:01"
- pyaiui.AIUISetting.setSystemInfo("sn", load_sn())
|