面试流程性能优化处理

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);
//发送文件流数据
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());
} catch (Exception e) {
@@ -291,11 +299,10 @@ public class ChatWebSocketMultipleHandler {
* @param session 客户端会话ID
*/
private void sendTTSBuffer(String clientId, String content, Session session) {
String resultFileName = clientId + "_" + System.currentTimeMillis() + ".wav";
String resultPathUrl = RuoYiConfig.getProfile() + VOICE_STORAGE_RESULT_DIR + resultFileName;
// String resultFileName = clientId + "_" + System.currentTimeMillis() + ".wav";
// String resultPathUrl = RuoYiConfig.getProfile() + VOICE_STORAGE_RESULT_DIR + resultFileName;
ElevenLabsStreamClient elevenLabsClient = SpringUtils.getBean(ElevenLabsStreamClient.class);
elevenLabsClient.handleTextToVoice(content, resultPathUrl,session);
elevenLabsClient.handleTextToVoice(content,session);
//持续返回数据流给客户端
log.info("发送语音流成功啦!!!!!!!");
// sendVoiceBuffer(resultPathUrl, session);
@@ -691,8 +698,13 @@ public class ChatWebSocketMultipleHandler {
questionResult = questionResult + content;
}
cacheQuestionResult.put(session.getId(),questionResult);
sendTTSBuffer(clientId,content,session);
//上面语音发送完成了,开始发送问题文本啦
// 实时输出内容
try{
try {
Thread.sleep(300);
}catch (Exception e){}
//把文本也给前端返回去
Map<String,String> dataText = new HashMap<>();
dataText.put("type","question");
@@ -701,7 +713,7 @@ public class ChatWebSocketMultipleHandler {
}catch (Exception e){
e.printStackTrace();
}
sendTTSBuffer(clientId,content,session);
}
}

View File

@@ -1,8 +1,10 @@
package com.vetti.common.ai.elevenLabs;
import cn.hutool.json.JSONUtil;
import com.google.gson.Gson;
import com.vetti.common.ai.elevenLabs.vo.VoiceSettings;
import com.vetti.common.ai.elevenLabs.vo.VoicesResponse;
import com.vetti.common.config.RuoYiConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -17,6 +19,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.websocket.Session;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -46,11 +49,10 @@ public class ElevenLabsStreamClient {
*
* @param text 要转换的文本
* @param voiceId 语音ID (可从ElevenLabs网站获取)
* @param outputFilePath 输出文件路径
* @throws IOException 网络请求或文件操作异常
*/
private void textToSpeech(String text, String voiceId, String outputFilePath, 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");
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=mp3_24000_48&optimize_streaming_latency=2");
httpPost.setHeader("xi-api-key", apiKey);
httpPost.setHeader("Content-Type", "application/json");
@@ -65,13 +67,30 @@ public class ElevenLabsStreamClient {
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
try (InputStream inputStream = responseEntity.getContent();) {
// byte[] allData = inputStream.readAllBytes();
// InputStream stableStream = new ByteArrayInputStream(allData);
// sendAudioStream(session,stableStream);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, 0, bytesRead);
session.getAsyncRemote().sendBinary(byteBuffer);
log.info("正常语音发送出去语音流啦!!!");
// log.info("字符流的长度大小:{}", bytesRead);
if(bytesRead != 1 && bytesRead != 2){
session.getAsyncRemote().sendBinary(byteBuffer);
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 outputFile
* @return
*/
public String handleTextToVoice(String inputText, String outputFile, Session session){
public void handleTextToVoice(String inputText,Session session){
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
// 使用第一个可用语音进行文本转语音(澳洲本地女声)
// String firstVoiceId = "56bWURjYFHyYyVf490Dp";
String firstVoiceId = "56bWURjYFHyYyVf490Dp";
textToSpeech(inputText, firstVoiceId, outputFile,httpClient,session);
textToSpeech(inputText, firstVoiceId,httpClient,session);
} catch (IOException e) {
e.printStackTrace();
} finally {
@@ -118,6 +136,41 @@ public class ElevenLabsStreamClient {
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]")) {
listener.onMessage(bufferStr.toString());
bufferStr.replace(0, bufferStr.length(), "");
bufferStr.setLength(0);
listener.onComplete();
break;
}
@@ -125,7 +125,7 @@ public class OpenAiStreamClient {
if(punctuationStr.contains(content.trim())){
//说明有标点啦,直接返回
listener.onMessage(bufferStr.toString());
bufferStr.replace(0, bufferStr.length(), "");
bufferStr.setLength(0);
}
}
// listener.onMessage(content);

View File

@@ -1,5 +1,5 @@
#Generated by Maven
#Thu Nov 06 20:32:30 CST 2025
#Thu Nov 27 13:22:25 CST 2025
artifactId=vetti-hotakes
groupId=com.vetti
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/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/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/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/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/domain/HotakeSysNotice.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/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/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/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/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/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/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/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/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/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