|
@@ -71,6 +71,7 @@ class MyAudioMediaPort(pj.AudioMediaPort):
|
|
if self.asr: # 如果ASR实例存在,则发送音频数据
|
|
if self.asr: # 如果ASR实例存在,则发送音频数据
|
|
self.asr.send_audio(frame.buf)
|
|
self.asr.send_audio(frame.buf)
|
|
|
|
|
|
|
|
+ current_time = time.time() # 实时当前时间
|
|
try:
|
|
try:
|
|
asr_text = self.get_asr_text()
|
|
asr_text = self.get_asr_text()
|
|
play_complete = self.call.is_play_complete()
|
|
play_complete = self.call.is_play_complete()
|
|
@@ -79,29 +80,26 @@ class MyAudioMediaPort(pj.AudioMediaPort):
|
|
if asr_text and play_complete:
|
|
if asr_text and play_complete:
|
|
self.call.cur_player_file = None
|
|
self.call.cur_player_file = None
|
|
self.user_asr_texts.append(asr_text)
|
|
self.user_asr_texts.append(asr_text)
|
|
- user_asr_text = asr_text if len(self.user_asr_texts) == 1 else '###'.join(self.user_asr_texts)
|
|
|
|
- self.user_asr_texts.clear()
|
|
|
|
- self.call.chat(user_asr_text)
|
|
|
|
-
|
|
|
|
|
|
+ if self.call.inputType == '1.0' and current_time - self.call.inputLongStart > 35:
|
|
|
|
+ self.user_asr_texts.append(self.call.digit)
|
|
|
|
+ user_asr_text = asr_text if len(self.user_asr_texts) == 1 else '###'.join(self.user_asr_texts)
|
|
|
|
+ self.call.chat(user_asr_text)
|
|
|
|
+ else:
|
|
|
|
+ user_asr_text = asr_text if len(self.user_asr_texts) == 1 else '###'.join(self.user_asr_texts)
|
|
|
|
+ self.user_asr_texts.clear()
|
|
|
|
+ self.call.chat(user_asr_text)
|
|
|
|
|
|
- #超时处理
|
|
|
|
- current_time = time.time()
|
|
|
|
# print(f'onFrameReceived:self.wait_time={self.call.wait_time}, self.call.digit ={self.call.digit},asr_text:{asr_text},play_complete:{play_complete},self.call.inputType:{self.call.inputType}')
|
|
# print(f'onFrameReceived:self.wait_time={self.call.wait_time}, self.call.digit ={self.call.digit},asr_text:{asr_text},play_complete:{play_complete},self.call.inputType:{self.call.inputType}')
|
|
- if self.call.wait_time and self.call.wait_time != "0" and play_complete and not asr_text and not self.call.digit :
|
|
|
|
|
|
+ if self.call.wait_time and self.call.wait_time != "0" and play_complete and not asr_text:
|
|
self.call.wait_time_check(current_time, self.call.wait_time)
|
|
self.call.wait_time_check(current_time, self.call.wait_time)
|
|
|
|
|
|
- # 如果为超长类型的按键服务 超过30s未输入完成执行超时操作
|
|
|
|
- if self.call.inputType == '1.0' and play_complete and not asr_text:
|
|
|
|
- self.call.wait_time_check(current_time, 30)
|
|
|
|
-
|
|
|
|
message_queue_size = self.call.message_queue.qsize()
|
|
message_queue_size = self.call.message_queue.qsize()
|
|
if (message_queue_size > 0 and not self.call.cur_player_file) or (message_queue_size > 0 and play_complete):
|
|
if (message_queue_size > 0 and not self.call.cur_player_file) or (message_queue_size > 0 and play_complete):
|
|
print('onFrameReceived:message_queue_size=', message_queue_size, 'play_complete=', play_complete, asr_text)
|
|
print('onFrameReceived:message_queue_size=', message_queue_size, 'play_complete=', play_complete, asr_text)
|
|
self.call.cur_player_file, self.call.wait_time, self.call.inputType,self.call.action, self.call.node_id = self.get_player_file()
|
|
self.call.cur_player_file, self.call.wait_time, self.call.inputType,self.call.action, self.call.node_id = self.get_player_file()
|
|
- self.call.send_bot_speaker(self.call.cur_player_file)
|
|
|
|
-
|
|
|
|
# 重置播放完成标志和超时计时器,确保新的播放从头开始计时
|
|
# 重置播放完成标志和超时计时器,确保新的播放从头开始计时
|
|
self.call.reset_wait_time()
|
|
self.call.reset_wait_time()
|
|
|
|
+ self.call.send_bot_speaker(self.call.cur_player_file)
|
|
#播放完毕执行的动作
|
|
#播放完毕执行的动作
|
|
self.call.say_end_action(self.call.action)
|
|
self.call.say_end_action(self.call.action)
|
|
except:
|
|
except:
|
|
@@ -123,9 +121,10 @@ class MyAudioMediaPort(pj.AudioMediaPort):
|
|
def get_player_file(self):
|
|
def get_player_file(self):
|
|
try:
|
|
try:
|
|
message = self.call.message_queue.get(block=False)
|
|
message = self.call.message_queue.get(block=False)
|
|
- # player_file = [f"http://{SERVE_HOST}{item.voice_url}" for item in message.contents if item.content_type == 'voice']
|
|
|
|
player_file = [item.voice_url for item in message.contents if item.content_type == 'voice']
|
|
player_file = [item.voice_url for item in message.contents if item.content_type == 'voice']
|
|
print('get_player_file:', player_file,message.wait_time, message.inputType, message.action, message.node_id)
|
|
print('get_player_file:', player_file,message.wait_time, message.inputType, message.action, message.node_id)
|
|
|
|
+ if message.inputType== '1.0':
|
|
|
|
+ self.call.inputLongStart = time.time()
|
|
return player_file, message.wait_time, message.inputType, message.action, message.node_id
|
|
return player_file, message.wait_time, message.inputType, message.action, message.node_id
|
|
except Exception as e:
|
|
except Exception as e:
|
|
traceback.print_exc()
|
|
traceback.print_exc()
|
|
@@ -204,44 +203,39 @@ class MyCall(pj.Call):
|
|
self.call_phone, self.callIdString = self.get_phone()
|
|
self.call_phone, self.callIdString = self.get_phone()
|
|
|
|
|
|
# 超时设置
|
|
# 超时设置
|
|
- self.play_start_time = time.time() # 记录播放开始时间
|
|
|
|
- self.play_complete_flag = False # 播放完成标志
|
|
|
|
|
|
+ self.play_start_time = time.time() # 倒计时开始时间
|
|
|
|
+ self.play_complete_flag = False # 倒计时开始标志
|
|
|
|
|
|
self.txtLock = False
|
|
self.txtLock = False
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- # 开始说话
|
|
|
|
- def begin_callback(self, message, *args):
|
|
|
|
- self.reset_wait_time()
|
|
|
|
- print("开始说话")
|
|
|
|
|
|
+ self.inputLongStart = 0 #长按键开始时间
|
|
|
|
|
|
def wait_time_check(self, current_time, wait_time):
|
|
def wait_time_check(self, current_time, wait_time):
|
|
- if not hasattr(self, 'play_complete_flag') or self.txtLock:
|
|
|
|
- self.play_complete_flag = False
|
|
|
|
- self.play_start_time = time.time()
|
|
|
|
- # 播放完成后开始计时
|
|
|
|
- if not self.play_complete_flag:
|
|
|
|
- self.play_complete_flag = True
|
|
|
|
- self.play_start_time = current_time
|
|
|
|
- # 检查超时时间是否已到
|
|
|
|
- print("current_time:", current_time, self.play_start_time)
|
|
|
|
- elapsed_time = current_time - self.play_start_time
|
|
|
|
- wait_time = int(wait_time)
|
|
|
|
- if elapsed_time > wait_time:
|
|
|
|
- if wait_time >= 30:
|
|
|
|
- print("DTMF:超时", self.digit)
|
|
|
|
- self.user_asr_text_queue.put(f"DTMF({self.digit})DTMF")
|
|
|
|
- else:
|
|
|
|
- print("DTMF:超时6shehehehehehhehhehehe")
|
|
|
|
|
|
+ try:
|
|
|
|
+ # 确保 wait_time 是整数类型
|
|
|
|
+ wait_time = int(wait_time)
|
|
|
|
+ # 如果播放尚未完成,重置标志并返回
|
|
|
|
+ if not self.play_complete_flag:
|
|
|
|
+ self.play_complete_flag = True
|
|
|
|
+ self.play_start_time = current_time
|
|
|
|
+ print(f"开始计时: {self.play_start_time}")
|
|
|
|
+
|
|
|
|
+ # 播放完成后,检查是否超时
|
|
|
|
+ elapsed_time = current_time - self.play_start_time
|
|
|
|
+ print(f"当前时间: {current_time}, 已过时间: {elapsed_time}, 最大等待时间: {wait_time}")
|
|
|
|
+
|
|
|
|
+ if elapsed_time >= wait_time:
|
|
|
|
+ print("ASR输入超时")
|
|
self.user_asr_text_queue.put("ASR408error")
|
|
self.user_asr_text_queue.put("ASR408error")
|
|
- self.play_complete_flag = False
|
|
|
|
|
|
+ self.reset_wait_time()
|
|
|
|
+
|
|
|
|
+ except ValueError as e:
|
|
|
|
+ print(f"无效的等待时间参数: {wait_time}, 错误: {e}")
|
|
|
|
+ self.reset_wait_time()
|
|
|
|
|
|
def reset_wait_time(self):
|
|
def reset_wait_time(self):
|
|
self.play_complete_flag = False # 重置播放完成标志
|
|
self.play_complete_flag = False # 重置播放完成标志
|
|
- # self.play_start_time = time.time() # 重新开始计时
|
|
|
|
- self.digit = "" # 重新把超长类型按键内容digit置为空
|
|
|
|
-
|
|
|
|
|
|
+ self.play_start_time = None # 重置开始计时时间
|
|
|
|
+ print("计时器已重置")
|
|
def get_phone(self):
|
|
def get_phone(self):
|
|
import re
|
|
import re
|
|
call_info = self.getInfo()
|
|
call_info = self.getInfo()
|
|
@@ -259,15 +253,14 @@ class MyCall(pj.Call):
|
|
if not self.is_play_complete() or self.txtLock: # 判断是否播放完成 否则不记录用户说的内容
|
|
if not self.is_play_complete() or self.txtLock: # 判断是否播放完成 否则不记录用户说的内容
|
|
return
|
|
return
|
|
digit = prm.digit
|
|
digit = prm.digit
|
|
|
|
+ self.reset_wait_time()
|
|
# 假设为超长类型按键 把用户输入的按键进行拼接 如果为# 则把用户输入所有按键放入队列并发送文本机器人
|
|
# 假设为超长类型按键 把用户输入的按键进行拼接 如果为# 则把用户输入所有按键放入队列并发送文本机器人
|
|
# 如果为非正常按键服务 输入以后直接发送文本机器人
|
|
# 如果为非正常按键服务 输入以后直接发送文本机器人
|
|
if self.inputType == '1.0':
|
|
if self.inputType == '1.0':
|
|
if digit != '#':
|
|
if digit != '#':
|
|
self.digit += digit
|
|
self.digit += digit
|
|
- # print(f"Received DTMF digit12: {self.digit}")
|
|
|
|
else:
|
|
else:
|
|
self.user_asr_text_queue.put(f"DTMF({self.digit})DTMF")
|
|
self.user_asr_text_queue.put(f"DTMF({self.digit})DTMF")
|
|
- # print(f"Received DTMF digit34: {self.digit}")
|
|
|
|
else:
|
|
else:
|
|
print(f"Received DTMF digit: {digit}")
|
|
print(f"Received DTMF digit: {digit}")
|
|
self.user_asr_text_queue.put(f"DTMF({digit})DTMF")
|
|
self.user_asr_text_queue.put(f"DTMF({digit})DTMF")
|
|
@@ -291,7 +284,6 @@ class MyCall(pj.Call):
|
|
|
|
|
|
if call_info.state == pj.PJSIP_INV_STATE_DISCONNECTED:
|
|
if call_info.state == pj.PJSIP_INV_STATE_DISCONNECTED:
|
|
print("通话结束", self.user_part)
|
|
print("通话结束", self.user_part)
|
|
- sys.stdout.flush() # 强制刷新输出缓冲区
|
|
|
|
if self.audio_port:
|
|
if self.audio_port:
|
|
self.audio_port = None # 或调用相关销毁方法
|
|
self.audio_port = None # 或调用相关销毁方法
|
|
if self.player:
|
|
if self.player:
|
|
@@ -324,6 +316,7 @@ class MyCall(pj.Call):
|
|
return
|
|
return
|
|
player_id = murmur3_32(player_file)
|
|
player_id = murmur3_32(player_file)
|
|
self.player_complete_dict[player_id] = False
|
|
self.player_complete_dict[player_id] = False
|
|
|
|
+ self.txtLock = False
|
|
# print('self.player_complete_dict[player_id]D:', player_id, player_file, self.player_complete_dict[player_id])
|
|
# print('self.player_complete_dict[player_id]D:', player_id, player_file, self.player_complete_dict[player_id])
|
|
print(f"[DEBUG] Sending bot speaker, player_file: {player_file}, player_id: {player_id}")
|
|
print(f"[DEBUG] Sending bot speaker, player_file: {player_file}, player_id: {player_id}")
|
|
self.player = MyAudioMediaPlayer(player_id, self.aud_med, on_complete=self.on_media_player_complete)
|
|
self.player = MyAudioMediaPlayer(player_id, self.aud_med, on_complete=self.on_media_player_complete)
|
|
@@ -335,6 +328,7 @@ class MyCall(pj.Call):
|
|
if not self.is_play_complete() or self.txtLock: # 判断是否播放完成 否则不记录用户说的内容
|
|
if not self.is_play_complete() or self.txtLock: # 判断是否播放完成 否则不记录用户说的内容
|
|
print('机器人播放过程asr返回内容:',message)
|
|
print('机器人播放过程asr返回内容:',message)
|
|
return
|
|
return
|
|
|
|
+ self.reset_wait_time()
|
|
message = json.loads(message)
|
|
message = json.loads(message)
|
|
if message["header"]["status"] == 20000000:
|
|
if message["header"]["status"] == 20000000:
|
|
# 获取 result 内容
|
|
# 获取 result 内容
|
|
@@ -351,7 +345,7 @@ class MyCall(pj.Call):
|
|
self.player_complete_dict[player_id] = True
|
|
self.player_complete_dict[player_id] = True
|
|
|
|
|
|
def bot_say_hello(self):
|
|
def bot_say_hello(self):
|
|
- print('bot_say_hello, come in ')
|
|
|
|
|
|
+ # print('bot_say_hello, come in ')
|
|
self.chat(user_asr_text="start")
|
|
self.chat(user_asr_text="start")
|
|
|
|
|
|
def chat(self, user_asr_text=None):
|
|
def chat(self, user_asr_text=None):
|
|
@@ -410,7 +404,6 @@ class ToTextBotAgent:
|
|
response_data = response.json()
|
|
response_data = response.json()
|
|
if "data" in response_data and response_data["code"]==0:
|
|
if "data" in response_data and response_data["code"]==0:
|
|
data = response_data["data"]
|
|
data = response_data["data"]
|
|
- print(f"响应数据:{data}")
|
|
|
|
parsed_response = ChatMessage.from_json(data)
|
|
parsed_response = ChatMessage.from_json(data)
|
|
self.call_agent.message_queue.put(parsed_response)
|
|
self.call_agent.message_queue.put(parsed_response)
|
|
sys.stdout.flush() # 强制刷新输出缓冲区
|
|
sys.stdout.flush() # 强制刷新输出缓冲区
|
|
@@ -419,10 +412,9 @@ class ToTextBotAgent:
|
|
else:
|
|
else:
|
|
# 错误处理
|
|
# 错误处理
|
|
print(f"请求失败,状态码: {response.status_code}, 响应内容: {response.text}")
|
|
print(f"请求失败,状态码: {response.status_code}, 响应内容: {response.text}")
|
|
- self.call_agent.txtLock = False
|
|
|
|
except requests.RequestException as e:
|
|
except requests.RequestException as e:
|
|
print(f"请求发生异常: {e}")
|
|
print(f"请求发生异常: {e}")
|
|
- self.call_agent.txtLock = False
|
|
|
|
|
|
+
|
|
|
|
|
|
# 模拟接口请求返回
|
|
# 模拟接口请求返回
|
|
def test_request(self, params: BotChatRequest):
|
|
def test_request(self, params: BotChatRequest):
|
|
@@ -501,7 +493,7 @@ class BotAgent:
|
|
def create_pjsua2(self):
|
|
def create_pjsua2(self):
|
|
# Create and initialize the library
|
|
# Create and initialize the library
|
|
ep_cfg = pj.EpConfig()
|
|
ep_cfg = pj.EpConfig()
|
|
- ep_cfg.uaConfig.threadCnt = 32
|
|
|
|
|
|
+ ep_cfg.uaConfig.threadCnt = 12
|
|
ep_cfg.uaConfig.mainThreadOnly = False
|
|
ep_cfg.uaConfig.mainThreadOnly = False
|
|
ep_cfg.uaConfig.maxCalls = 20
|
|
ep_cfg.uaConfig.maxCalls = 20
|
|
ep_cfg.uaConfig.maxAccounts = 20
|
|
ep_cfg.uaConfig.maxAccounts = 20
|