面试流程性能优化处理

This commit is contained in:
2025-11-27 14:54:02 +08:00
parent 22a15188be
commit 56b6e67180
6 changed files with 106 additions and 46 deletions

View File

@@ -276,6 +276,14 @@ public class ChatWebSocketMultipleHandler {
ByteBuffer outByteBuffer = convertFileToByteBuffer(pathUrl); ByteBuffer outByteBuffer = convertFileToByteBuffer(pathUrl);
//发送文件流数据 //发送文件流数据
session.getBasicRemote().sendBinary(outByteBuffer); session.getBasicRemote().sendBinary(outByteBuffer);
try {
Thread.sleep(200);
}catch (Exception e){}
//提示已经结束
Map<String,String> dataText = new HashMap<>();
dataText.put("type","voiceEnd");
dataText.put("content","");
session.getBasicRemote().sendText(JSONUtil.toJsonStr(dataText));
// 发送响应确认 // 发送响应确认
log.info("已经成功发送了语音流给前端:{}", DateUtil.now()); log.info("已经成功发送了语音流给前端:{}", DateUtil.now());
} catch (Exception e) { } catch (Exception e) {
@@ -291,11 +299,10 @@ public class ChatWebSocketMultipleHandler {
* @param session 客户端会话ID * @param session 客户端会话ID
*/ */
private void sendTTSBuffer(String clientId, String content, Session session) { private void sendTTSBuffer(String clientId, String content, Session session) {
String resultFileName = clientId + "_" + System.currentTimeMillis() + ".wav"; // String resultFileName = clientId + "_" + System.currentTimeMillis() + ".wav";
String resultPathUrl = RuoYiConfig.getProfile() + VOICE_STORAGE_RESULT_DIR + resultFileName; // String resultPathUrl = RuoYiConfig.getProfile() + VOICE_STORAGE_RESULT_DIR + resultFileName;
ElevenLabsStreamClient elevenLabsClient = SpringUtils.getBean(ElevenLabsStreamClient.class); ElevenLabsStreamClient elevenLabsClient = SpringUtils.getBean(ElevenLabsStreamClient.class);
elevenLabsClient.handleTextToVoice(content, resultPathUrl,session); elevenLabsClient.handleTextToVoice(content,session);
//持续返回数据流给客户端 //持续返回数据流给客户端
log.info("发送语音流成功啦!!!!!!!"); log.info("发送语音流成功啦!!!!!!!");
// sendVoiceBuffer(resultPathUrl, session); // sendVoiceBuffer(resultPathUrl, session);
@@ -691,8 +698,13 @@ public class ChatWebSocketMultipleHandler {
questionResult = questionResult + content; questionResult = questionResult + content;
} }
cacheQuestionResult.put(session.getId(),questionResult); cacheQuestionResult.put(session.getId(),questionResult);
sendTTSBuffer(clientId,content,session);
//上面语音发送完成了,开始发送问题文本啦
// 实时输出内容 // 实时输出内容
try{ try{
try {
Thread.sleep(300);
}catch (Exception e){}
//把文本也给前端返回去 //把文本也给前端返回去
Map<String,String> dataText = new HashMap<>(); Map<String,String> dataText = new HashMap<>();
dataText.put("type","question"); dataText.put("type","question");
@@ -701,7 +713,7 @@ public class ChatWebSocketMultipleHandler {
}catch (Exception e){ }catch (Exception e){
e.printStackTrace(); e.printStackTrace();
} }
sendTTSBuffer(clientId,content,session);
} }
} }

View File

@@ -1,8 +1,10 @@
package com.vetti.common.ai.elevenLabs; package com.vetti.common.ai.elevenLabs;
import cn.hutool.json.JSONUtil;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.vetti.common.ai.elevenLabs.vo.VoiceSettings; import com.vetti.common.ai.elevenLabs.vo.VoiceSettings;
import com.vetti.common.ai.elevenLabs.vo.VoicesResponse; import com.vetti.common.ai.elevenLabs.vo.VoicesResponse;
import com.vetti.common.config.RuoYiConfig;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
@@ -17,6 +19,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.websocket.Session; import javax.websocket.Session;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -46,11 +49,10 @@ public class ElevenLabsStreamClient {
* *
* @param text 要转换的文本 * @param text 要转换的文本
* @param voiceId 语音ID (可从ElevenLabs网站获取) * @param voiceId 语音ID (可从ElevenLabs网站获取)
* @param outputFilePath 输出文件路径
* @throws IOException 网络请求或文件操作异常 * @throws IOException 网络请求或文件操作异常
*/ */
private void textToSpeech(String text, String voiceId, String outputFilePath, CloseableHttpClient httpClient, Session session) throws IOException { private void textToSpeech(String text, String voiceId, CloseableHttpClient httpClient, Session session) throws IOException {
HttpPost httpPost = new HttpPost(BASE_URL + "/text-to-speech/" + voiceId+"/stream?output_format=pcm_16000&optimize_streaming_latency=1"); HttpPost httpPost = new HttpPost(BASE_URL + "/text-to-speech/" + voiceId+"/stream?output_format=mp3_24000_48&optimize_streaming_latency=2");
httpPost.setHeader("xi-api-key", apiKey); httpPost.setHeader("xi-api-key", apiKey);
httpPost.setHeader("Content-Type", "application/json"); httpPost.setHeader("Content-Type", "application/json");
@@ -65,14 +67,31 @@ public class ElevenLabsStreamClient {
HttpEntity responseEntity = response.getEntity(); HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) { if (responseEntity != null) {
try (InputStream inputStream = responseEntity.getContent();) { try (InputStream inputStream = responseEntity.getContent();) {
// byte[] allData = inputStream.readAllBytes();
// InputStream stableStream = new ByteArrayInputStream(allData);
// sendAudioStream(session,stableStream);
byte[] buffer = new byte[4096]; byte[] buffer = new byte[4096];
int bytesRead; int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) { while ((bytesRead = inputStream.read(buffer)) != -1) {
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, bytesRead); ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, bytesRead);
// log.info("字符流的长度大小:{}", bytesRead);
if(bytesRead != 1 && bytesRead != 2){
session.getAsyncRemote().sendBinary(byteBuffer); session.getAsyncRemote().sendBinary(byteBuffer);
log.info("正常语音发送出去语音流啦!!!"); try {
Thread.sleep(20);
}catch (Exception e){}
// log.info("正常语音发送出去语音流啦!!!");
} }
} }
//返回结束点
try {
Thread.sleep(100);
}catch (Exception e){}
Map<String,String> dataText = new HashMap<>();
dataText.put("type","voiceEnd");
dataText.put("content","");
session.getBasicRemote().sendText(JSONUtil.toJsonStr(dataText));
}
} }
} }
} }
@@ -99,16 +118,15 @@ public class ElevenLabsStreamClient {
/** /**
* 处理文本转换成语音文件 * 处理文本转换成语音文件
* @param inputText * @param inputText
* @param outputFile
* @return * @return
*/ */
public String handleTextToVoice(String inputText, String outputFile, Session session){ public void handleTextToVoice(String inputText,Session session){
CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpClient httpClient = HttpClients.createDefault();
try { try {
// 使用第一个可用语音进行文本转语音(澳洲本地女声) // 使用第一个可用语音进行文本转语音(澳洲本地女声)
// String firstVoiceId = "56bWURjYFHyYyVf490Dp"; // String firstVoiceId = "56bWURjYFHyYyVf490Dp";
String firstVoiceId = "56bWURjYFHyYyVf490Dp"; String firstVoiceId = "56bWURjYFHyYyVf490Dp";
textToSpeech(inputText, firstVoiceId, outputFile,httpClient,session); textToSpeech(inputText, firstVoiceId,httpClient,session);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
@@ -118,6 +136,41 @@ public class ElevenLabsStreamClient {
e.printStackTrace(); e.printStackTrace();
} }
} }
return outputFile;
} }
public void sendAudioStream(Session session, InputStream inputStream) throws IOException {
byte[] buffer = new byte[2048]; // 分片大小,可调
final int[] bytesReadHolder = new int[1];
// 定义一个递归任务
final Runnable[] sender = new Runnable[1];
sender[0] = () -> {
try {
bytesReadHolder[0] = inputStream.read(buffer);
// 结束条件
if (bytesReadHolder[0] == -1) {
log.info("音频流发送完毕");
Map<String,String> dataText = new HashMap<>();
dataText.put("type","voiceEnd");
dataText.put("content","");
session.getBasicRemote().sendText(JSONUtil.toJsonStr(dataText));
return;
}
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, bytesReadHolder[0]);
session.getAsyncRemote().sendBinary(byteBuffer, result -> {
if (result.isOK()) {
log.info("正常语音发送出去语音流啦!!! 大小={} 字节", bytesReadHolder[0]);
// 当前块发送成功,继续发送下一块
sender[0].run();
} else {
log.error("发送失败: {}", result.getException().getMessage());
}
});
} catch (IOException e) {
log.error("流读取错误: {}", e.getMessage());
}
};
// 启动递归链
sender[0].run();
}
} }

View File

@@ -106,7 +106,7 @@ public class OpenAiStreamClient {
// 检查是否为结束标记 // 检查是否为结束标记
if (data.equals("[DONE]")) { if (data.equals("[DONE]")) {
listener.onMessage(bufferStr.toString()); listener.onMessage(bufferStr.toString());
bufferStr.replace(0, bufferStr.length(), ""); bufferStr.setLength(0);
listener.onComplete(); listener.onComplete();
break; break;
} }
@@ -125,7 +125,7 @@ public class OpenAiStreamClient {
if(punctuationStr.contains(content.trim())){ if(punctuationStr.contains(content.trim())){
//说明有标点啦,直接返回 //说明有标点啦,直接返回
listener.onMessage(bufferStr.toString()); listener.onMessage(bufferStr.toString());
bufferStr.replace(0, bufferStr.length(), ""); bufferStr.setLength(0);
} }
} }
// listener.onMessage(content); // listener.onMessage(content);

View File

@@ -1,5 +1,5 @@
#Generated by Maven #Generated by Maven
#Thu Nov 06 20:32:30 CST 2025 #Thu Nov 27 13:22:25 CST 2025
artifactId=vetti-hotakes artifactId=vetti-hotakes
groupId=com.vetti groupId=com.vetti
version=3.9.0 version=3.9.0

View File

@@ -1,21 +0,0 @@
com/vetti/hotake/mapper/HotakeCvInfoMapper.class
com/vetti/hotake/service/impl/HotakeSysFileServiceImpl.class
com/vetti/hotake/domain/dto/HotakeSysFileDto.class
com/vetti/hotake/service/IHotakeSysNoticeService.class
com/vetti/hotake/domain/dto/HotakeSysNoticeDto.class
com/vetti/hotake/mapper/HotakeSysFileMapper.class
com/vetti/hotake/mapper/HotakeSysNoticeMapper.class
com/vetti/hotake/domain/HotakeCvInfo.class
com/vetti/hotake/service/impl/HotakeSysNoticeServiceImpl.class
com/vetti/hotake/domain/dto/HotakeSysNoticeTypeNameDto.class
com/vetti/hotake/domain/vo/HotakeSysFileVo.class
com/vetti/hotake/domain/HotakeSysFile.class
com/vetti/hotake/domain/dto/HotakeSysNoticeViewDto.class
com/vetti/hotake/domain/HotakeProblemBaseInfo.class
com/vetti/hotake/service/IHotakeProblemBaseInfoService.class
com/vetti/hotake/service/impl/HotakeProblemBaseInfoServiceImpl.class
com/vetti/hotake/domain/HotakeSysNotice.class
com/vetti/hotake/mapper/HotakeProblemBaseInfoMapper.class
com/vetti/hotake/service/IHotakeSysFileService.class
com/vetti/hotake/service/impl/HotakeCvInfoServiceImpl.class
com/vetti/hotake/service/IHotakeCvInfoService.class

View File

@@ -1,23 +1,39 @@
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeInterviewDetailMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeSysNoticeMapper.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeSysNoticeMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeMeetingCalendarInfoServiceImpl.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeSysFileMapper.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeSysFileMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeSysFileServiceImpl.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeSysFileServiceImpl.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/dto/HotakeSysNoticeTypeNameDto.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/dto/HotakeSysNoticeTypeNameDto.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeCvInfoMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeSysFileService.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeSysFileService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeCvInfo.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeCvInfo.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeProblemBaseInfoServiceImpl.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeInterviewInfoMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeSysNotice.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeMeetingCalendarDetailServiceImpl.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeSysFile.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeSysFile.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeInterviewDetailServiceImpl.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeInterviewInfoServiceImpl.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeSysNoticeServiceImpl.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeSysNoticeServiceImpl.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/vo/HotakeSysFileVo.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeProblemBaseInfoMapper.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeProblemBaseInfoMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/dto/HotakeSysNoticeViewDto.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeMeetingCalendarDetail.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeSysNoticeTypeMapper.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeSysNoticeTypeMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/dto/HotakeSysNoticeDto.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeSysNoticeType.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeSysNoticeType.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeSysNoticeService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeCvInfoService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeProblemBaseInfo.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeProblemBaseInfo.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeCvInfoServiceImpl.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeCvInfoServiceImpl.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeProblemBaseInfoService.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeProblemBaseInfoService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeMeetingCalendarInfo.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/dto/HotakeSysFileDto.java /Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/dto/HotakeSysFileDto.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeMeetingCalendarInfoMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeInterviewDetailService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeCvInfoMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/impl/HotakeProblemBaseInfoServiceImpl.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeInterviewDetail.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeSysNotice.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/vo/HotakeSysFileVo.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeInterviewInfoService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeMeetingCalendarInfoService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/dto/HotakeSysNoticeViewDto.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/mapper/HotakeMeetingCalendarDetailMapper.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/dto/HotakeSysNoticeDto.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/domain/HotakeInterviewInfo.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeSysNoticeService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeCvInfoService.java
/Users/wangxiangshun/Public/project-aio/vetti/vetti-service/vetti-hotakes/src/main/java/com/vetti/hotake/service/IHotakeMeetingCalendarDetailService.java