Browse Source

对话流式实现

Zhangbw 2 months ago
parent
commit
b476908eb0

+ 1 - 1
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/controller/api/ChatController.java

@@ -122,7 +122,7 @@ public class ChatController {
         bo.setId(id);
         bo.setStatus("0");
         boolean success = talkAgentService.updateByBo(bo);
-        log.info("客服 {} 挂断电话,状态已改为正常", id);
+        log.info("客服 {} 挂断电话,状态已改为空闲中", id);
         return Map.of("success", success);
     }
 

+ 35 - 6
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/service/impl/ChatServiceImpl.java

@@ -196,14 +196,43 @@ public class ChatServiceImpl implements IChatService {
                     agentConfig = talkAgentService.queryById(agentId);
                 }
 
-                // 如果是欢迎语,直接发送
+                // 如果是欢迎语,合成语音但不发送text事件(避免前端重复显示)
                 if (Boolean.TRUE.equals(isGreeting)) {
-                    Map<String, String> textEvent = new HashMap<>();
-                    textEvent.put("name", "text");
-                    textEvent.put("data", userMessage);
-                    emitter.send(org.springframework.web.servlet.mvc.method.annotation.SseEmitter.event()
-                        .data(textEvent));
+                    TalkAgentVo finalAgentConfig = agentConfig;
+
+                    // 合成欢迎语语音
+                    java.util.concurrent.CountDownLatch latch = new java.util.concurrent.CountDownLatch(1);
+                    java.io.ByteArrayOutputStream mergedAudioBytes = new java.io.ByteArrayOutputStream();
+
+                    ttsService.synthesizeStream(userMessage, finalAgentConfig, (audioChunk, status) -> {
+                        try {
+                            byte[] audioBytes = java.util.Base64.getDecoder().decode(audioChunk);
+                            mergedAudioBytes.write(audioBytes);
+
+                            if (status == 2) {
+                                String mergedAudioBase64 = java.util.Base64.getEncoder().encodeToString(mergedAudioBytes.toByteArray());
+                                Map<String, String> audioEvent = new HashMap<>();
+                                audioEvent.put("name", "audio");
+                                audioEvent.put("data", mergedAudioBase64);
+                                emitter.send(org.springframework.web.servlet.mvc.method.annotation.SseEmitter.event()
+                                    .data(audioEvent));
+                                latch.countDown();
+                            }
+                        } catch (Exception e) {
+                            log.error("发送欢迎语音频失败", e);
+                            latch.countDown();
+                        }
+                    });
+
+                    // 等待音频合成完成
+                    try {
+                        latch.await(30, java.util.concurrent.TimeUnit.SECONDS);
+                    } catch (InterruptedException e) {
+                        log.error("等待欢迎语音频合成被中断", e);
+                        Thread.currentThread().interrupt();
+                    }
 
+                    // 发送完成信号
                     Map<String, String> doneEvent = new HashMap<>();
                     doneEvent.put("name", "done");
                     doneEvent.put("data", "");