|
@@ -165,6 +165,15 @@ public class RobotChat extends RobotBase {
|
|
|
"xf_tts_mode=" + xfTtsMode,
|
|
"xf_tts_mode=" + xfTtsMode,
|
|
|
uuid
|
|
uuid
|
|
|
);
|
|
);
|
|
|
|
|
+ EslConnectionUtil.sendExecuteCommand("set",
|
|
|
|
|
+ "xf_tts_verify_peer=false",
|
|
|
|
|
+ uuid
|
|
|
|
|
+ );
|
|
|
|
|
+ // xfyun streaming continuation relies on xf_tts_resume, which needs cached speech handles.
|
|
|
|
|
+ EslConnectionUtil.sendExecuteCommand("set",
|
|
|
|
|
+ "cache_speech_handles=true",
|
|
|
|
|
+ uuid
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
if(ttsProvider.equalsIgnoreCase(TtsProvider.MICROSOFT)) {
|
|
if(ttsProvider.equalsIgnoreCase(TtsProvider.MICROSOFT)) {
|
|
|
logger.info("{} Current tts provider is microsoft!", getTraceId());
|
|
logger.info("{} Current tts provider is microsoft!", getTraceId());
|
|
@@ -256,6 +265,12 @@ public class RobotChat extends RobotBase {
|
|
|
logger.info("{} recv PLAYBACK_STOP event for wav file {}. ", getTraceId(), playbackFilePath);
|
|
logger.info("{} recv PLAYBACK_STOP event for wav file {}. ", getTraceId(), playbackFilePath);
|
|
|
}else {
|
|
}else {
|
|
|
logger.info("{} The playback of the file {} has completed. ", getTraceId(), playbackFilePath);
|
|
logger.info("{} The playback of the file {} has completed. ", getTraceId(), playbackFilePath);
|
|
|
|
|
+ if(fileBasedTtsPlayback) {
|
|
|
|
|
+ fileBasedTtsPlayback = false;
|
|
|
|
|
+ ttsChannelClosed = true;
|
|
|
|
|
+ chatRobot.setTtsChannelState(TtsChannelState.CLOSED);
|
|
|
|
|
+ logger.info("{} file-based tts playback finished.", getTraceId());
|
|
|
|
|
+ }
|
|
|
recvPlayBackEndEvent = true;
|
|
recvPlayBackEndEvent = true;
|
|
|
playbackEndTime = System.currentTimeMillis();
|
|
playbackEndTime = System.currentTimeMillis();
|
|
|
releasePlayBackFinishedSignal();
|
|
releasePlayBackFinishedSignal();
|
|
@@ -374,6 +389,8 @@ public class RobotChat extends RobotBase {
|
|
|
chatRobot.setTtsChannelState(TtsChannelState.CLOSED);
|
|
chatRobot.setTtsChannelState(TtsChannelState.CLOSED);
|
|
|
logger.info("{} TtsChannelClosed = true.", getTraceId());
|
|
logger.info("{} TtsChannelClosed = true.", getTraceId());
|
|
|
ttsChannelClosed = true;
|
|
ttsChannelClosed = true;
|
|
|
|
|
+ recvPlayBackEndEvent = true;
|
|
|
|
|
+ playbackEndTime = System.currentTimeMillis();
|
|
|
releasePlayBackFinishedSignal();
|
|
releasePlayBackFinishedSignal();
|
|
|
}
|
|
}
|
|
|
if("Speech-Open".equalsIgnoreCase(event)){
|
|
if("Speech-Open".equalsIgnoreCase(event)){
|
|
@@ -401,6 +418,21 @@ public class RobotChat extends RobotBase {
|
|
|
if (null != asrResponse) {
|
|
if (null != asrResponse) {
|
|
|
asrResponse = headers.get("Detect-Speech-Result").trim();
|
|
asrResponse = headers.get("Detect-Speech-Result").trim();
|
|
|
}
|
|
}
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-asr-event
|
|
|
|
|
+ logger.info("{} dbg_asr_event recv event={}, recvPlayBackEndEvent={}, allowInterrupt={}, inSpeaking={}, isHangup={}, transferToAgent={}, keepAiDuringTransferWait={}, manualAnsweredTime={}, isReleased={}, response={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ speechEvent,
|
|
|
|
|
+ recvPlayBackEndEvent,
|
|
|
|
|
+ getAllowInterrupt(),
|
|
|
|
|
+ interactiveParam.checkInSpeaking(),
|
|
|
|
|
+ isHangup,
|
|
|
|
|
+ transferToAgent,
|
|
|
|
|
+ shouldKeepAiConversationDuringTransferWait(),
|
|
|
|
|
+ callDetail == null ? -1L : callDetail.getManualAnsweredTime(),
|
|
|
|
|
+ isReleased,
|
|
|
|
|
+ asrResponse
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
|
|
|
|
|
if ("NetworkError".equalsIgnoreCase(speechEvent)) {
|
|
if ("NetworkError".equalsIgnoreCase(speechEvent)) {
|
|
|
CommonUtils.setHangupCauseDetail(
|
|
CommonUtils.setHangupCauseDetail(
|
|
@@ -415,12 +447,35 @@ public class RobotChat extends RobotBase {
|
|
|
|
|
|
|
|
lastTalkTime = System.currentTimeMillis();
|
|
lastTalkTime = System.currentTimeMillis();
|
|
|
|
|
|
|
|
- if (isHangup || interactiveParam.checkInHangupState() || transferToAgent) {
|
|
|
|
|
|
|
+ boolean transferWaitingForManualAnswer = shouldKeepAiConversationDuringTransferWait();
|
|
|
|
|
+ if (isHangup || interactiveParam.checkInHangupState() || (transferToAgent && !transferWaitingForManualAnswer)) {
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-drop-hangup
|
|
|
|
|
+ logger.info("{} dbg_asr_event drop by hangup-state event={}, isHangup={}, inHangupState={}, transferToAgent={}, transferWaitingForManualAnswer={}, response={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ speechEvent,
|
|
|
|
|
+ isHangup,
|
|
|
|
|
+ interactiveParam.checkInHangupState(),
|
|
|
|
|
+ transferToAgent,
|
|
|
|
|
+ transferWaitingForManualAnswer,
|
|
|
|
|
+ asrResponse
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
logger.info("{} Session is going to be hangup or is already being transferred to human operator, drop asr result: {}", getTraceId(), asrResponse);
|
|
logger.info("{} Session is going to be hangup or is already being transferred to human operator, drop asr result: {}", getTraceId(), asrResponse);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (!getAllowInterrupt() && !recvPlayBackEndEvent) {
|
|
|
|
|
|
|
+ boolean allowTransferWaitBargeIn = shouldKeepAiConversationDuringTransferWait();
|
|
|
|
|
+ if (!getAllowInterrupt() && !recvPlayBackEndEvent && !allowTransferWaitBargeIn) {
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-drop-playback
|
|
|
|
|
+ logger.info("{} dbg_asr_event drop by playback-gate event={}, recvPlayBackEndEvent={}, allowInterrupt={}, allowTransferWaitBargeIn={}, response={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ speechEvent,
|
|
|
|
|
+ recvPlayBackEndEvent,
|
|
|
|
|
+ getAllowInterrupt(),
|
|
|
|
|
+ allowTransferWaitBargeIn,
|
|
|
|
|
+ asrResponse
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
if ("vad".equalsIgnoreCase(speechEvent)) {
|
|
if ("vad".equalsIgnoreCase(speechEvent)) {
|
|
|
dropAsrCounter.incrementAndGet();
|
|
dropAsrCounter.incrementAndGet();
|
|
|
logger.info("{} (vad event) drop asr result: {}", getTraceId(), asrResponse);
|
|
logger.info("{} (vad event) drop asr result: {}", getTraceId(), asrResponse);
|
|
@@ -438,7 +493,7 @@ public class RobotChat extends RobotBase {
|
|
|
getAllowInterrupt(),
|
|
getAllowInterrupt(),
|
|
|
!interactiveParam.checkInSpeaking()
|
|
!interactiveParam.checkInSpeaking()
|
|
|
);
|
|
);
|
|
|
- if (recvPlayBackEndEvent || getAllowInterrupt()) {
|
|
|
|
|
|
|
+ if (recvPlayBackEndEvent || getAllowInterrupt() || allowTransferWaitBargeIn) {
|
|
|
if (!interactiveParam.checkInSpeaking()) {
|
|
if (!interactiveParam.checkInSpeaking()) {
|
|
|
String lockerKey = String.format("%s%s", uuid, "checkInSpeaking");
|
|
String lockerKey = String.format("%s%s", uuid, "checkInSpeaking");
|
|
|
synchronized (lockerKey.intern()) {
|
|
synchronized (lockerKey.intern()) {
|
|
@@ -447,7 +502,12 @@ public class RobotChat extends RobotBase {
|
|
|
// Main thread awakened to extend customer speaking time beyond 6 seconds.
|
|
// Main thread awakened to extend customer speaking time beyond 6 seconds.
|
|
|
logger.info("{} customer speech detected. ", getTraceId());
|
|
logger.info("{} customer speech detected. ", getTraceId());
|
|
|
|
|
|
|
|
- if (chatRobot.getAccount().interruptFlag == 2) {
|
|
|
|
|
|
|
+ if (allowTransferWaitBargeIn && !recvPlayBackEndEvent) {
|
|
|
|
|
+ logger.info("{} transfer-wait barge-in detected by middle event, interrupt current robot speech.", getTraceId());
|
|
|
|
|
+ interruptRobotSpeech();
|
|
|
|
|
+ releasePlayBackFinishedSignal();
|
|
|
|
|
+ ThreadUtil.sleep(100);
|
|
|
|
|
+ } else if (chatRobot.getAccount().interruptFlag == 2) {
|
|
|
interruptRobotSpeech();
|
|
interruptRobotSpeech();
|
|
|
releasePlayBackFinishedSignal();
|
|
releasePlayBackFinishedSignal();
|
|
|
ThreadUtil.sleep(100);
|
|
ThreadUtil.sleep(100);
|
|
@@ -467,9 +527,21 @@ public class RobotChat extends RobotBase {
|
|
|
|
|
|
|
|
if (!StringUtil.isNullOrEmpty(asrResponse)) {
|
|
if (!StringUtil.isNullOrEmpty(asrResponse)) {
|
|
|
asrResultEx.add(asrResponse);
|
|
asrResultEx.add(asrResponse);
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-asr-cache
|
|
|
|
|
+ logger.info("{} dbg_asr_event cached vad result, queueSize={}, response={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ asrResultEx.size(),
|
|
|
|
|
+ asrResponse
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if(chatRobot.getAccount().interruptFlag == 1 && !recvPlayBackEndEvent) {
|
|
|
|
|
|
|
+ if (allowTransferWaitBargeIn && !recvPlayBackEndEvent) {
|
|
|
|
|
+ logger.info("{} transfer-wait barge-in detected by vad event, interrupt current robot speech.", getTraceId());
|
|
|
|
|
+ interruptRobotSpeech();
|
|
|
|
|
+ releasePlayBackFinishedSignal();
|
|
|
|
|
+ ThreadUtil.sleep(100);
|
|
|
|
|
+ } else if(chatRobot.getAccount().interruptFlag == 1 && !recvPlayBackEndEvent) {
|
|
|
if (checkSpeechInterrupt(asrResponse)) {
|
|
if (checkSpeechInterrupt(asrResponse)) {
|
|
|
interruptRobotSpeech();
|
|
interruptRobotSpeech();
|
|
|
releasePlayBackFinishedSignal();
|
|
releasePlayBackFinishedSignal();
|
|
@@ -479,7 +551,17 @@ public class RobotChat extends RobotBase {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if(recvPlayBackEndEvent || getAllowInterrupt()){
|
|
|
|
|
|
|
+ if(recvPlayBackEndEvent || getAllowInterrupt() || allowTransferWaitBargeIn){
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-release-signal
|
|
|
|
|
+ logger.info("{} dbg_asr_event release signal by vad event, queueSize={}, recvPlayBackEndEvent={}, allowInterrupt={}, allowTransferWaitBargeIn={}, response={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ asrResultEx.size(),
|
|
|
|
|
+ recvPlayBackEndEvent,
|
|
|
|
|
+ getAllowInterrupt(),
|
|
|
|
|
+ allowTransferWaitBargeIn,
|
|
|
|
|
+ asrResponse
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
logger.info("{} releaseSignal for vad event.", getTraceId());
|
|
logger.info("{} releaseSignal for vad event.", getTraceId());
|
|
|
releaseSignal();
|
|
releaseSignal();
|
|
|
}
|
|
}
|
|
@@ -639,6 +721,20 @@ public class RobotChat extends RobotBase {
|
|
|
if (checkCallSession()) {
|
|
if (checkCallSession()) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-interact-enter
|
|
|
|
|
+ logger.info("{} dbg_interact enter, asrQueueSize={}, recvPlayBackEndEvent={}, ttsChannelClosed={}, inSpeaking={}, noVoiceCounter={}, transferToAgent={}, keepAiDuringTransferWait={}, manualAnsweredTime={}, isReleased={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ asrResultEx.size(),
|
|
|
|
|
+ recvPlayBackEndEvent,
|
|
|
|
|
+ ttsChannelClosed,
|
|
|
|
|
+ interactiveParam.checkInSpeaking(),
|
|
|
|
|
+ noVoiceCounter.get(),
|
|
|
|
|
+ transferToAgent,
|
|
|
|
|
+ shouldKeepAiConversationDuringTransferWait(),
|
|
|
|
|
+ callDetail == null ? -1L : callDetail.getManualAnsweredTime(),
|
|
|
|
|
+ isReleased
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
interactiveParam.setAllowInterrupt(0);
|
|
interactiveParam.setAllowInterrupt(0);
|
|
|
recvPlayBackEndEvent = false;
|
|
recvPlayBackEndEvent = false;
|
|
|
firstSpeak = false;
|
|
firstSpeak = false;
|
|
@@ -653,6 +749,13 @@ public class RobotChat extends RobotBase {
|
|
|
for (String result : asrResultEx) {
|
|
for (String result : asrResultEx) {
|
|
|
asrStr.append(result);
|
|
asrStr.append(result);
|
|
|
}
|
|
}
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-question-built
|
|
|
|
|
+ logger.info("{} dbg_interact built question='{}', cachedResultCount={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ asrStr.toString(),
|
|
|
|
|
+ asrResultEx.size()
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
|
|
|
|
|
// 清空 asrResultEx; 重新初始化字段;
|
|
// 清空 asrResultEx; 重新初始化字段;
|
|
|
asrResultEx.clear();
|
|
asrResultEx.clear();
|
|
@@ -664,6 +767,14 @@ public class RobotChat extends RobotBase {
|
|
|
try {
|
|
try {
|
|
|
String question = asrStr.toString();
|
|
String question = asrStr.toString();
|
|
|
if (StringUtils.isEmpty(question)) {
|
|
if (StringUtils.isEmpty(question)) {
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-empty-question
|
|
|
|
|
+ logger.info("{} dbg_interact question empty, noVoiceCounterBefore={}, recvPlayBackEndEvent={}, ttsChannelClosed={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ noVoiceCounter.get(),
|
|
|
|
|
+ recvPlayBackEndEvent,
|
|
|
|
|
+ ttsChannelClosed
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
int counter = noVoiceCounter.incrementAndGet();
|
|
int counter = noVoiceCounter.incrementAndGet();
|
|
|
if (counter > MAX_CONSECUTIVE_NO_VOICE_NUMBER) {
|
|
if (counter > MAX_CONSECUTIVE_NO_VOICE_NUMBER) {
|
|
|
logger.info("{} There has been no sound for {} consecutive times. Play hangupTips and then hangup call.",
|
|
logger.info("{} There has been no sound for {} consecutive times. Play hangupTips and then hangup call.",
|
|
@@ -830,10 +941,31 @@ public class RobotChat extends RobotBase {
|
|
|
|
|
|
|
|
private void playResponse(LlmAiphoneRes aiphoneRes){
|
|
private void playResponse(LlmAiphoneRes aiphoneRes){
|
|
|
String ttsFilePathList = aiphoneRes.getTtsFilePathList();
|
|
String ttsFilePathList = aiphoneRes.getTtsFilePathList();
|
|
|
|
|
+ if (useXfyunCloneFilePlayback()
|
|
|
|
|
+ && talkRound.longValue() == 1
|
|
|
|
|
+ && StringUtils.isEmpty(ttsFilePathList)
|
|
|
|
|
+ && StringUtils.isNotEmpty(aiphoneRes.getBody())) {
|
|
|
|
|
+ logger.info("{} skip duplicate first-round xfyun clone playback, text={}.",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ aiphoneRes.getBody()
|
|
|
|
|
+ );
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(StringUtils.isEmpty(ttsFilePathList) && useXfyunCloneFilePlayback()) {
|
|
|
|
|
+ if (playXfyunCloneTtsIfNeeded(aiphoneRes.getBody())) {
|
|
|
|
|
+ logger.info("{} try to play xfyun clone wav file for text {}.", getTraceId(), aiphoneRes.getBody());
|
|
|
|
|
+ } else if(StringUtils.isNotEmpty(aiphoneRes.getBody())) {
|
|
|
|
|
+ logger.info("{} fallback to streaming xfyun clone tts for text {}.", getTraceId(), aiphoneRes.getBody());
|
|
|
|
|
+ chatRobot.sendTtsRequest(aiphoneRes.getBody());
|
|
|
|
|
+ chatRobot.closeTts();
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
if(!StringUtils.isEmpty(ttsFilePathList)){
|
|
if(!StringUtils.isEmpty(ttsFilePathList)){
|
|
|
TtsFileInfo ttsFileInfo = AudioUtils.joinTtsFiles(ttsFilePathList);
|
|
TtsFileInfo ttsFileInfo = AudioUtils.joinTtsFiles(ttsFilePathList);
|
|
|
logger.info("{} try to play wav file for text {}.", getTraceId(), aiphoneRes.getBody());
|
|
logger.info("{} try to play wav file for text {}.", getTraceId(), aiphoneRes.getBody());
|
|
|
startPlayback(ttsFileInfo);
|
|
startPlayback(ttsFileInfo);
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -889,25 +1021,72 @@ public class RobotChat extends RobotBase {
|
|
|
waitForPlayBackFinished(9000);
|
|
waitForPlayBackFinished(9000);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // stop_asr 的顺序很重要,需要放在播放tts之后,否则不起作用;会被uuid_break清空指令;
|
|
|
|
|
- logger.info("{} Try to stop asr {}", getTraceId(), chatRobot.getAccount().asrProvider);
|
|
|
|
|
- EslConnectionUtil.sendExecuteCommand(
|
|
|
|
|
- String.format("stop_%s_asr", chatRobot.getAccount().asrProvider), "", uuid);
|
|
|
|
|
|
|
+ boolean delayTransferMediaStopUntilManualAnswer = shouldDelayTransferMediaStopUntilManualAnswer();
|
|
|
|
|
+ if (delayTransferMediaStopUntilManualAnswer) {
|
|
|
|
|
+ logger.info("{} xfyun transfer flow keeps TTS/ASR active until manual agent answers. manualAnsweredTime={}, isReleased={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ callDetail == null ? -1L : callDetail.getManualAnsweredTime(),
|
|
|
|
|
+ isReleased);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // stop_asr 的顺序很重要,需要放在播放tts之后,否则不起作用;会被uuid_break清空指令;
|
|
|
|
|
+ logger.info("{} Try to stop asr {}", getTraceId(), chatRobot.getAccount().asrProvider);
|
|
|
|
|
+ EslConnectionUtil.sendExecuteCommand(
|
|
|
|
|
+ String.format("stop_%s_asr", chatRobot.getAccount().asrProvider), "", uuid);
|
|
|
|
|
|
|
|
- ThreadUtil.sleep(200);
|
|
|
|
|
|
|
+ ThreadUtil.sleep(200);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if(!isHangup) {
|
|
if(!isHangup) {
|
|
|
- releaseThreadNum();
|
|
|
|
|
- TransferToAgent.transfer(callDetail, chatRobot.getAccount());
|
|
|
|
|
|
|
+ // #region debug-point xfyun-transfer-wait-release-thread
|
|
|
|
|
+ logger.info("{} dbg_transfer_wait before releaseThreadNum transferToAgent={}, transferToAgentExecuted={}, keepAiDuringTransferWait={}, manualAnsweredTime={}, isReleased={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ transferToAgent,
|
|
|
|
|
+ transferToAgentExecuted,
|
|
|
|
|
+ shouldKeepAiConversationDuringTransferWait(),
|
|
|
|
|
+ callDetail == null ? -1L : callDetail.getManualAnsweredTime(),
|
|
|
|
|
+ isReleased
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
|
|
+ if (!delayTransferMediaStopUntilManualAnswer) {
|
|
|
|
|
+ releaseThreadNum();
|
|
|
|
|
+ TransferToAgent.transfer(callDetail, chatRobot.getAccount());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ logger.info("{} postpone releaseThreadNum until manual agent answers.", getTraceId());
|
|
|
|
|
+ final InboundDetail currentCallDetail = callDetail;
|
|
|
|
|
+ final AccountBaseEntity currentAccount = chatRobot.getAccount();
|
|
|
|
|
+ getRobotMainThreadPool().execute(new Runnable() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void run() {
|
|
|
|
|
+ ThreadLocalTraceId.getInstance().setTraceId(uuid);
|
|
|
|
|
+ logger.info("{} async transfer-to-agent task started while AI keeps talking before manual answer.", getTraceId());
|
|
|
|
|
+ TransferToAgent.transfer(currentCallDetail, currentAccount);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ waitForCustomerSpeakEx();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private boolean shouldDelayTransferMediaStopUntilManualAnswer() {
|
|
|
|
|
+ String voiceSource = StringUtils.trimToEmpty(chatRobot.getAccount().voiceSource);
|
|
|
|
|
+ String transferType = StringUtils.trimToEmpty(chatRobot.getAccount().aiTransferType);
|
|
|
|
|
+ return TtsProvider.XFYUN.equalsIgnoreCase(voiceSource)
|
|
|
|
|
+ && !TransferToAgent.TRANSFER_TO_ACD.equalsIgnoreCase(transferType);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean shouldKeepAiConversationDuringTransferWait() {
|
|
|
|
|
+ return transferToAgent
|
|
|
|
|
+ && shouldDelayTransferMediaStopUntilManualAnswer()
|
|
|
|
|
+ && callDetail != null
|
|
|
|
|
+ && callDetail.getManualAnsweredTime() == 0L;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Check if the call has been hung up or has been transferred to a human handler.
|
|
* Check if the call has been hung up or has been transferred to a human handler.
|
|
|
* @return
|
|
* @return
|
|
|
*/
|
|
*/
|
|
|
private boolean checkCallSession(){
|
|
private boolean checkCallSession(){
|
|
|
- return isHangup || transferToAgent;
|
|
|
|
|
|
|
+ return isHangup || (transferToAgent && !shouldKeepAiConversationDuringTransferWait());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -918,6 +1097,19 @@ public class RobotChat extends RobotBase {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-wait-enter
|
|
|
|
|
+ logger.info("{} dbg_wait_customer enter, recvPlayBackEndEvent={}, ttsChannelClosed={}, asrQueueSize={}, inSpeaking={}, transferToAgent={}, keepAiDuringTransferWait={}, manualAnsweredTime={}, isReleased={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ recvPlayBackEndEvent,
|
|
|
|
|
+ ttsChannelClosed,
|
|
|
|
|
+ asrResultEx.size(),
|
|
|
|
|
+ interactiveParam.checkInSpeaking(),
|
|
|
|
|
+ transferToAgent,
|
|
|
|
|
+ shouldKeepAiConversationDuringTransferWait(),
|
|
|
|
|
+ callDetail == null ? -1L : callDetail.getManualAnsweredTime(),
|
|
|
|
|
+ isReleased
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
logger.info("{} enter into waitForCustomerSpeak ...", getTraceId());
|
|
logger.info("{} enter into waitForCustomerSpeak ...", getTraceId());
|
|
|
|
|
|
|
|
// The duration of streaming TTS playback should not exceed 181 seconds.
|
|
// The duration of streaming TTS playback should not exceed 181 seconds.
|
|
@@ -953,6 +1145,14 @@ public class RobotChat extends RobotBase {
|
|
|
getTraceId(),
|
|
getTraceId(),
|
|
|
System.currentTimeMillis() - startWaitTimeMills
|
|
System.currentTimeMillis() - startWaitTimeMills
|
|
|
);
|
|
);
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-wait-after-acquire
|
|
|
|
|
+ logger.info("{} dbg_wait_customer after acquire, asrQueueSize={}, inSpeaking={}, recvPlayBackEndEvent={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ asrResultEx.size(),
|
|
|
|
|
+ interactiveParam.checkInSpeaking(),
|
|
|
|
|
+ recvPlayBackEndEvent
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
|
|
|
|
|
if (checkCallSession()) {
|
|
if (checkCallSession()) {
|
|
|
return;
|
|
return;
|
|
@@ -998,6 +1198,14 @@ public class RobotChat extends RobotBase {
|
|
|
if (asrResultEx.size() == 0) {
|
|
if (asrResultEx.size() == 0) {
|
|
|
acquire(500);
|
|
acquire(500);
|
|
|
}
|
|
}
|
|
|
|
|
+ // #region debug-point xfyun-asr-no-response-wait-exit
|
|
|
|
|
+ logger.info("{} dbg_wait_customer exit, asrQueueSize={}, inSpeaking={}, noVoiceCounter={}",
|
|
|
|
|
+ getTraceId(),
|
|
|
|
|
+ asrResultEx.size(),
|
|
|
|
|
+ interactiveParam.checkInSpeaking(),
|
|
|
|
|
+ noVoiceCounter.get()
|
|
|
|
|
+ );
|
|
|
|
|
+ // #endregion
|
|
|
|
|
|
|
|
if (checkCallSession()) {
|
|
if (checkCallSession()) {
|
|
|
return;
|
|
return;
|