发送音频逻辑优化
This commit is contained in:
@@ -4,7 +4,6 @@ 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;
|
||||||
@@ -19,7 +18,9 @@ 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.*;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -64,48 +65,50 @@ 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();) {
|
||||||
|
// 锁(数组是为了内部类可写)
|
||||||
|
boolean[] sending = new boolean[]{false};
|
||||||
//用来合并零散的碎片
|
//用来合并零散的碎片
|
||||||
ByteArrayOutputStream smallChunkBuffer = new ByteArrayOutputStream(); //
|
ByteArrayOutputStream smallChunkBuffer = new ByteArrayOutputStream();
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
int n = 0;
|
|
||||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
try{
|
||||||
|
// 如果上一包还在发送 → 阻塞等待
|
||||||
|
while (sending[0]) {
|
||||||
|
// 轻量等待,不耗 CPU
|
||||||
|
Thread.sleep(1);
|
||||||
|
}
|
||||||
|
}catch (Exception e){}
|
||||||
//语音流合并到2KB左右进行发送
|
//语音流合并到2KB左右进行发送
|
||||||
if(smallChunkBuffer.size() >= 3072){
|
if(smallChunkBuffer.size() >= 3072){
|
||||||
|
// 🔥开始发送 → 上锁
|
||||||
|
sending[0] = true;
|
||||||
log.info("语音流大于"+smallChunkBuffer.size()+"啦,发送完成!!!");
|
log.info("语音流大于"+smallChunkBuffer.size()+"啦,发送完成!!!");
|
||||||
byte[] merged = smallChunkBuffer.toByteArray();
|
byte[] merged = smallChunkBuffer.toByteArray();
|
||||||
smallChunkBuffer.reset();
|
smallChunkBuffer.reset();
|
||||||
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(merged));
|
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(merged), result -> {
|
||||||
try {
|
if (!result.isOK()) {
|
||||||
Thread.sleep(50);
|
log.info("发送失败: " + result.getException());
|
||||||
}catch (Exception e){}
|
}
|
||||||
|
// 🔥发送完毕 → 解锁
|
||||||
|
sending[0] = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
//发送三次告诉前端要合成一次语音
|
|
||||||
// if(n == 2){
|
|
||||||
// Map<String,String> dataText = new HashMap<>();
|
|
||||||
// dataText.put("type","voiceMiddleEnd");
|
|
||||||
// dataText.put("content","");
|
|
||||||
// session.getBasicRemote().sendText(JSONUtil.toJsonStr(dataText));
|
|
||||||
// //重置一下
|
|
||||||
// n = 0;
|
|
||||||
// }
|
|
||||||
// 零散的碎片 → 加入缓冲区,不立即发送
|
// 零散的碎片 → 加入缓冲区,不立即发送
|
||||||
smallChunkBuffer.write(buffer, 0, bytesRead);
|
smallChunkBuffer.write(buffer, 0, bytesRead);
|
||||||
n++;
|
|
||||||
}
|
}
|
||||||
//都加完缓冲区,最最后一次发送
|
//都加完缓冲区,最最后一次发送
|
||||||
if(smallChunkBuffer.size() > 2){
|
if(smallChunkBuffer.size() > 2){
|
||||||
log.info("最后一次发送,语音流大于"+smallChunkBuffer.size()+"啦,发送完成!!!");
|
// 如果上一包还在发送 → 阻塞等待
|
||||||
byte[] merged = smallChunkBuffer.toByteArray();
|
byte[] merged = smallChunkBuffer.toByteArray();
|
||||||
smallChunkBuffer.reset();
|
smallChunkBuffer.reset();
|
||||||
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(merged));
|
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(merged), result -> {
|
||||||
try {
|
log.info("最后一次发送,语音流大于"+smallChunkBuffer.size()+"啦,发送完成!!!");
|
||||||
Thread.sleep(50);
|
});
|
||||||
}catch (Exception e){}
|
|
||||||
}
|
}
|
||||||
//返回结束点
|
//返回结束点
|
||||||
try {
|
try {
|
||||||
Thread.sleep(50);
|
Thread.sleep(20);
|
||||||
}catch (Exception e){}
|
}catch (Exception e){}
|
||||||
Map<String,String> dataText = new HashMap<>();
|
Map<String,String> dataText = new HashMap<>();
|
||||||
dataText.put("type","voiceEnd");
|
dataText.put("type","voiceEnd");
|
||||||
|
|||||||
Reference in New Issue
Block a user