feat: 语音交互调整
This commit is contained in:
parent
ac37baf54b
commit
b900d854a8
@ -92,22 +92,20 @@ public class FlowNodeParamPreparer {
|
|||||||
Object loopNumVal = input.get("loopNum");
|
Object loopNumVal = input.get("loopNum");
|
||||||
int loopCount = 0;
|
int loopCount = 0;
|
||||||
|
|
||||||
if (loopNumVal instanceof Number) {
|
// 根据迭代路径找到当前层的集合对象
|
||||||
loopCount = ((Number) loopNumVal).intValue();
|
Object target = resolveLoopTarget(loopNumVal, rootMessage.getIterations(), 0);
|
||||||
} else if (loopNumVal instanceof JSONArray) {
|
|
||||||
// 支持 JSON 数组
|
if (target instanceof JSONArray) {
|
||||||
loopCount = ((JSONArray) loopNumVal).size();
|
loopCount = ((JSONArray) target).size();
|
||||||
}
|
} else if (target instanceof Collection) {
|
||||||
else if (loopNumVal instanceof Collection) {
|
loopCount = ((Collection<?>) target).size();
|
||||||
// 支持所有 Java Collection
|
} else if (target != null && target.getClass().isArray()) {
|
||||||
loopCount = ((Collection<?>) loopNumVal).size();
|
loopCount = Array.getLength(target);
|
||||||
}
|
} else if (target instanceof Number) {
|
||||||
else if (loopNumVal != null && loopNumVal.getClass().isArray()) {
|
loopCount = ((Number) target).intValue();
|
||||||
// 支持 Java 数组
|
} else if (target != null) {
|
||||||
loopCount = Array.getLength(loopNumVal);
|
|
||||||
} else if (loopNumVal != null) {
|
|
||||||
try {
|
try {
|
||||||
loopCount = Integer.parseInt(loopNumVal.toString());
|
loopCount = Integer.parseInt(target.toString());
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new GlobalException("loopNum 参数格式错误: " + loopNumVal);
|
throw new GlobalException("loopNum 参数格式错误: " + loopNumVal);
|
||||||
}
|
}
|
||||||
@ -165,4 +163,42 @@ public class FlowNodeParamPreparer {
|
|||||||
}
|
}
|
||||||
return curr;
|
return curr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据迭代路径(iterations)逐层解析嵌套集合
|
||||||
|
* 例子:
|
||||||
|
* - iterations = [] → 返回最外层对象
|
||||||
|
* - iterations = [2] → 返回 list[1]
|
||||||
|
* - iterations = [2,3] → 返回 list[1][2]
|
||||||
|
*/
|
||||||
|
private Object resolveLoopTarget(Object obj, List<Integer> iterations, int depth) {
|
||||||
|
if (obj == null) return null;
|
||||||
|
|
||||||
|
// 已经走到当前循环层,返回目标
|
||||||
|
if (depth >= iterations.size()) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = iterations.get(depth) - 1;
|
||||||
|
|
||||||
|
if (obj instanceof List) {
|
||||||
|
List<?> list = (List<?>) obj;
|
||||||
|
if (idx >= 0 && idx < list.size()) {
|
||||||
|
return resolveLoopTarget(list.get(idx), iterations, depth + 1);
|
||||||
|
}
|
||||||
|
} else if (obj instanceof JSONArray) {
|
||||||
|
JSONArray arr = (JSONArray) obj;
|
||||||
|
if (idx >= 0 && idx < arr.size()) {
|
||||||
|
return resolveLoopTarget(arr.get(idx), iterations, depth + 1);
|
||||||
|
}
|
||||||
|
} else if (obj != null && obj.getClass().isArray()) {
|
||||||
|
int length = Array.getLength(obj);
|
||||||
|
if (idx >= 0 && idx < length) {
|
||||||
|
return resolveLoopTarget(Array.get(obj, idx), iterations, depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果不是集合类型,直接返回
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -131,7 +131,7 @@ public class LLMTTSOperateService implements LLMOperateService {
|
|||||||
Map<String, Object> body = new HashMap<>();
|
Map<String, Object> body = new HashMap<>();
|
||||||
body.put("text", text);
|
body.put("text", text);
|
||||||
body.put("dialect", "普通话");
|
body.put("dialect", "普通话");
|
||||||
body.put("timbre", "标准男");
|
body.put("timbre", "员工女");
|
||||||
body.put("language", "中文");
|
body.put("language", "中文");
|
||||||
body.put("tone", "中性");
|
body.put("tone", "中性");
|
||||||
|
|
||||||
@ -219,5 +219,4 @@ public class LLMTTSOperateService implements LLMOperateService {
|
|||||||
private final long generateMs;
|
private final long generateMs;
|
||||||
private final CountDownLatch latch; // 仅最后一段有
|
private final CountDownLatch latch; // 仅最后一段有
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -7,11 +7,17 @@ import com.cmvr.edge.client.service.EdgeSpeakerService;
|
|||||||
import com.cmvr.test.enums.ActionEnum;
|
import com.cmvr.test.enums.ActionEnum;
|
||||||
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
|
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
|
||||||
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
|
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
|
||||||
import com.cmvr.test.flow.runtime.operator.edge.EdgeOperateService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.sound.sampled.AudioFormat;
|
||||||
|
import javax.sound.sampled.AudioInputStream;
|
||||||
|
import javax.sound.sampled.AudioSystem;
|
||||||
|
import javax.sound.sampled.DataLine;
|
||||||
|
import javax.sound.sampled.SourceDataLine;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ -34,21 +40,67 @@ public class ViPlayOperateService implements VIOperateService {
|
|||||||
String deviceId = inputParams.getString("deviceId");
|
String deviceId = inputParams.getString("deviceId");
|
||||||
String audioPath = inputParams.getString("audioPath");
|
String audioPath = inputParams.getString("audioPath");
|
||||||
String terminalId = message.getTerminalId();
|
String terminalId = message.getTerminalId();
|
||||||
log.info("播放语料成功,deviceId={},audioPath={},terminalId={}", deviceId, audioPath, terminalId);
|
// log.info("播放语料成功,deviceId={},audioPath={},terminalId={}", deviceId, audioPath, terminalId);
|
||||||
// edgeSpeakerService.playAudio(terminalId, deviceId, audioPath);
|
edgeSpeakerService.playAudio(terminalId, deviceId, audioPath);
|
||||||
// // 等待播放完成
|
// 等待播放完成
|
||||||
// while (true) {
|
while (true) {
|
||||||
// try {
|
try {
|
||||||
// Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
// } catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
// }
|
}
|
||||||
// SpeakerCommand.GetSpeakerStateCommand.Feedback status = edgeSpeakerService.getStatus(terminalId, deviceId);
|
SpeakerCommand.GetSpeakerStateCommand.Feedback status = edgeSpeakerService.getStatus(terminalId, deviceId);
|
||||||
// boolean isRunning = status.getState().getIsRunning();
|
boolean isRunning = status.getState().getIsRunning();
|
||||||
// if (!isRunning) {
|
if (!isRunning) {
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
// todo 本机测试播放
|
||||||
|
// playAudio(audioPath);
|
||||||
return TaskNodeExecuteResult.success();
|
return TaskNodeExecuteResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播放一个音频文件(阻塞直到播完)
|
||||||
|
*/
|
||||||
|
private void playAudio(String filePath) {
|
||||||
|
try (AudioInputStream sourceStream = AudioSystem.getAudioInputStream(new File(filePath))) {
|
||||||
|
AudioFormat baseFormat = sourceStream.getFormat();
|
||||||
|
AudioFormat targetFormat = new AudioFormat(
|
||||||
|
AudioFormat.Encoding.PCM_SIGNED,
|
||||||
|
baseFormat.getSampleRate(),
|
||||||
|
16,
|
||||||
|
baseFormat.getChannels(),
|
||||||
|
baseFormat.getChannels() * 2,
|
||||||
|
baseFormat.getSampleRate(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
try (AudioInputStream pcmStream = AudioSystem.getAudioInputStream(targetFormat, sourceStream)) {
|
||||||
|
DataLine.Info info = new DataLine.Info(SourceDataLine.class, targetFormat);
|
||||||
|
try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) {
|
||||||
|
line.open(targetFormat);
|
||||||
|
line.start();
|
||||||
|
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = pcmStream.read(buffer, 0, buffer.length)) != -1) {
|
||||||
|
line.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保缓冲区播完
|
||||||
|
line.drain();
|
||||||
|
line.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("播放完成: {}", filePath);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new GlobalException("播放失败: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user