diff --git a/pom.xml b/pom.xml
index ae568d7..6158e8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -346,6 +346,11 @@
${jsoup.version}
+
+ io.github.jaredmdobson
+ concentus
+ 1.0.2
+
diff --git a/vetti-admin/pom.xml b/vetti-admin/pom.xml
index 4890e6c..d823417 100644
--- a/vetti-admin/pom.xml
+++ b/vetti-admin/pom.xml
@@ -86,6 +86,11 @@
spring-boot-starter-websocket
+
+ io.github.jaredmdobson
+ concentus
+
+
diff --git a/vetti-admin/src/main/java/com/vetti/socket/AudioSender.java b/vetti-admin/src/main/java/com/vetti/socket/AudioSender.java
new file mode 100644
index 0000000..8f41525
--- /dev/null
+++ b/vetti-admin/src/main/java/com/vetti/socket/AudioSender.java
@@ -0,0 +1,47 @@
+package com.vetti.socket;
+
+import javax.websocket.Session;
+import java.nio.ByteBuffer;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * 语音发送
+ */
+public class AudioSender {
+
+ private final Queue queue = new ConcurrentLinkedQueue<>();
+ private final AtomicBoolean sending = new AtomicBoolean(false);
+
+ public void sendAudio(Session session, byte[] data) {
+ queue.add(data);
+ trySend(session);
+ }
+
+ private void trySend(Session session) {
+ if (!sending.compareAndSet(false, true)) {
+ return; // 已在发送中,退出
+ }
+
+ byte[] chunk = queue.poll();
+ if (chunk == null) {
+ sending.set(false);
+ return;
+ }
+
+ ByteBuffer buffer = ByteBuffer.wrap(chunk);
+
+ session.getAsyncRemote().sendBinary(buffer, result -> {
+ sending.set(false);
+
+ if (!result.isOK()) {
+ result.getException().printStackTrace();
+ }
+
+ // 递归发送下一片
+ trySend(session);
+ });
+ }
+
+}
diff --git a/vetti-admin/src/main/java/com/vetti/socket/ChatWebSocketHandler.java b/vetti-admin/src/main/java/com/vetti/socket/ChatWebSocketHandler.java
index fd14ecc..60df77c 100644
--- a/vetti-admin/src/main/java/com/vetti/socket/ChatWebSocketHandler.java
+++ b/vetti-admin/src/main/java/com/vetti/socket/ChatWebSocketHandler.java
@@ -19,15 +19,12 @@ import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.File;
-import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
+
/**
* 语音面试 web处理器
*/
@@ -36,12 +33,6 @@ import java.util.concurrent.ConcurrentHashMap;
@Component
public class ChatWebSocketHandler {
- /**
- * 评分标记
- */
- private final String SCORE_FLAG = "Score:";
-
-
/**
* 缓存客户端流式解析的语音文本数据
*/
@@ -56,7 +47,10 @@ public class ChatWebSocketHandler {
* 缓存客户端,面试回答信息
*/
private final Map cacheMsgMapData = new ConcurrentHashMap<>();
-
+ /**
+ * 缓存客户端,面试回答信息
+ */
+ private final Map cacheMsgMapData1 = new ConcurrentHashMap<>();
/**
* 缓存客户端,AI提问的问题结果信息
*/
@@ -67,6 +61,11 @@ public class ChatWebSocketHandler {
*/
private final Map> cacheScoreResult = new ConcurrentHashMap<>();
+ /**
+ * 缓存客户端,回答问题次数-回答5轮就自动停止当前问答,返回对应的评分
+ */
+ private final Map cacheQuestionNum = new ConcurrentHashMap<>();
+
// 语音文件保存目录
private static final String VOICE_STORAGE_DIR = "/voice_files/";
@@ -99,6 +98,8 @@ public class ChatWebSocketHandler {
cacheReplyFlag.put(session.getId(), "YES");
//初始化面试回答数据记录
cacheMsgMapData.put(session.getId(), "");
+ //初始化面试回答数据记录
+ cacheMsgMapData1.put(session.getId(), "");
//初始化面试问题
cacheQuestionResult.put(session.getId(), "");
//初始化得分结果记录
@@ -108,6 +109,8 @@ public class ChatWebSocketHandler {
scoreResultData.put("2-3", 0);
scoreResultData.put("2-5", 0);
cacheScoreResult.put(session.getId(), scoreResultData);
+ //初始化问答次数
+ cacheQuestionNum.put(session.getId(), 0L);
//发送初始化面试官语音流
String openingPathUrl = RuoYiConfig.getProfile() + VOICE_SYSTEM_DIR + "opening.wav";
sendVoiceBuffer(openingPathUrl, session);
@@ -158,55 +161,53 @@ public class ChatWebSocketHandler {
if (StrUtil.isNotEmpty(msgMapData)) {
List