remove(@NotEmpty(message = "主键不能为空")
- @PathVariable Integer[] ids) {
- return toAjax(aihumanRealConfigService.deleteWithValidByIds(List.of(ids), true));
- }
-
- /**
- * 1.执行以下命令:
- * cd F:\Projects\AI-Human\LiveTalking
- * conda activate D:\zg117\C\Users\zg117\.conda\envs\livetalking_new
- * python app.py --transport webrtc --model wav2lip --avatar_id wav2lip256_avatar1
- *
- * 2.监听 python app.py --transport webrtc --model wav2lip --avatar_id wav2lip256_avatar1 执行情况
- *
- * 3.返回执行结果并打开页面
- * http://127.0.0.1:8010/webrtcapi-diy.html
- */
- @SaCheckPermission("aihuman:aihumanRealConfig:run")
- //@Log(title = "真人交互数字人配置", businessType = BusinessType.UPDATE, operatorType = OperatorType.OTHER)
- @RepeatSubmit()
- @PutMapping("/run")
- public R run(@Validated(EditGroup.class) @RequestBody AihumanRealConfigBo bo) {
- boolean result = aihumanRealConfigService.runByBo(bo);
- if (result) {
- // 返回前端页面URL,前端可以根据这个URL跳转或打开新页面
- // http://127.0.0.1:8010/webrtcapi-diy.html 其中的 http://127.0.0.1 获取当前java服务的IP地址
- // return R.ok("http://127.0.0.1:8010/webrtcapi-diy.html");
- // 运行状态
- bo.setRunStatus("1");
- return R.ok("http://127.0.0.1:8010/webrtcapi-diy.html");
- } else {
- return R.fail("启动真人交互数字人失败");
- }
- }
-
- /**
- * 停止真人交互数字人配置任务
- */
- @SaCheckPermission("aihuman:aihumanRealConfig:stop")
- //@Log(title = "真人交互数字人配置", businessType = BusinessType.UPDATE, operatorType = OperatorType.OTHER)
- @RepeatSubmit()
- @PutMapping("/stop")
- public R stop(@Validated(EditGroup.class) @RequestBody AihumanRealConfigBo bo) {
- boolean result = aihumanRealConfigService.stopByBo(bo);
- if (result) {
- // 运行状态
- bo.setRunStatus("0");
- return R.ok("真人交互数字人任务已停止");
- } else {
- return R.fail("停止真人交互数字人任务失败或没有正在运行的任务");
- }
- }
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanVolcengineController.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanVolcengineController.java
deleted file mode 100644
index e9b3e99a..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/controller/AihumanVolcengineController.java
+++ /dev/null
@@ -1,502 +0,0 @@
-package org.ruoyi.aihuman.controller;
-
-import cn.dev33.satoken.annotation.SaIgnore;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.ruoyi.aihuman.domain.VoiceRequest;
-import org.ruoyi.aihuman.protocol.EventType;
-import org.ruoyi.aihuman.protocol.Message;
-import org.ruoyi.aihuman.protocol.MsgType;
-import org.ruoyi.aihuman.protocol.SpeechWebSocketClient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.io.ResourceLoader;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-/**
- * 火山引擎相关接口
- *
- * @author ruoyi
- */
-// 临时免登录
-@SaIgnore
-
-@Validated
-@RequiredArgsConstructor
-@Slf4j
-@RestController
-@RequestMapping("/aihuman/volcengine")
-public class AihumanVolcengineController {
-
- private static final ObjectMapper objectMapper = new ObjectMapper();
- private static final Logger logger = LoggerFactory.getLogger(AihumanVolcengineController.class);
- @Autowired
- private ResourceLoader resourceLoader;
-
- @PostMapping("/generate-voice-direct")
- public ResponseEntity generateVoiceDirect(@RequestBody VoiceRequest request) {
- try {
- // 生成唯一的语音ID
- String voiceId = UUID.randomUUID().toString().replace("-", "");
-
- log.info("开始生成语音,voiceId: {}", voiceId);
-
- // 调用火山引擎TTS API获取音频数据
- byte[] audioData = generateVoiceData(request, voiceId);
-
- // 设置响应头,返回音频数据
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.parseMediaType("audio/wav"));
- headers.setContentDispositionFormData("attachment", "voice_" + System.currentTimeMillis() + ".wav");
- headers.setContentLength(audioData.length);
-
- log.info("语音生成成功并返回,长度: {} bytes", audioData.length);
- return new ResponseEntity<>(audioData, headers, HttpStatus.OK);
- } catch (Exception e) {
- log.error("生成语音失败", e);
- return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
- }
- }
-
- private byte[] generateVoiceData(VoiceRequest request, String voiceId) {
- try {
- // 这里是调用火山引擎TTS API的核心逻辑
- // 您需要根据火山引擎的API文档实现具体的调用逻辑
- // 注意:这只是一个示例框架,您需要根据实际情况进行实现
-
- // 调用火山引擎API并获取音频数据
- // 假设您已经有现有的调用逻辑,这里保留原有的实现
- String endpoint = request.getEndpoint();
- String appId = request.getAppId();
- String accessToken = request.getAccessToken();
- String resourceId = request.getResourceId();
- String voice = request.getVoice();
- String text = request.getText();
- String encoding = request.getEncoding();
-
- // 调用原有的火山引擎API调用方法(如果有)
- // 或者直接在这里实现API调用逻辑
- byte[] audioData = callVolcengineTtsApiByte(endpoint, appId, accessToken,
- resourceId, voice, text, encoding);
-
- log.info("成功生成语音数据,大小: {} bytes", audioData.length);
- return audioData;
- } catch (Exception e) {
- log.error("生成语音数据失败", e);
- throw new RuntimeException("生成语音数据失败", e);
- }
-
- }
-
- private byte[] callVolcengineTtsApiByte(String endpoint, String appId, String accessToken,
- String resourceId, String voice, String text, String encoding) {
- try {
- // 确保resourceId不为空,如果为空则根据voice类型获取默认值
- if (resourceId == null || resourceId.isEmpty()) {
- resourceId = voiceToResourceId(voice);
- }
-
- // 设置请求头
- Map headers = new HashMap<>();
- headers.put("X-Api-App-Key", appId);
- headers.put("X-Api-Access-Key", accessToken);
- headers.put("X-Api-Resource-Id", resourceId);
- headers.put("X-Api-Connect-Id", UUID.randomUUID().toString());
-
- // 创建WebSocket客户端
- SpeechWebSocketClient client = new SpeechWebSocketClient(new URI(endpoint), headers);
- ByteArrayOutputStream totalAudioStream = new ByteArrayOutputStream();
- boolean audioReceived = false;
-
- try {
- // 连接WebSocket
- client.connectBlocking();
-
- // 构建请求参数
- Map request = new HashMap<>();
- request.put("user", Map.of("uid", UUID.randomUUID().toString()));
- request.put("namespace", "BidirectionalTTS");
-
- Map reqParams = new HashMap<>();
- reqParams.put("speaker", voice);
-
- Map audioParams = new HashMap<>();
- audioParams.put("format", encoding);
- audioParams.put("sample_rate", 24000);
- audioParams.put("enable_timestamp", true);
-
- reqParams.put("audio_params", audioParams);
- reqParams.put("additions", objectMapper.writeValueAsString(Map.of("disable_markdown_filter", false)));
-
- request.put("req_params", reqParams);
-
- // 开始连接
- client.sendStartConnection();
- // 等待连接成功
- client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.CONNECTION_STARTED);
-
- // 处理每个句子
- String[] sentences = text.split("。");
- for (int i = 0; i < sentences.length; i++) {
- if (sentences[i].trim().isEmpty()) {
- continue;
- }
-
- String sessionId = UUID.randomUUID().toString();
- ByteArrayOutputStream sentenceAudioStream = new ByteArrayOutputStream();
-
- // 开始会话
- Map startReq = new HashMap<>();
- startReq.put("user", request.get("user"));
- startReq.put("namespace", request.get("namespace"));
- startReq.put("req_params", request.get("req_params"));
- startReq.put("event", EventType.START_SESSION.getValue());
- client.sendStartSession(objectMapper.writeValueAsBytes(startReq), sessionId);
- // 等待会话开始
- client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.SESSION_STARTED);
-
- // 发送文本内容
- for (char c : sentences[i].toCharArray()) {
- @SuppressWarnings("unchecked")
- Map currentReqParams = new HashMap<>((Map) request.get("req_params"));
- currentReqParams.put("text", String.valueOf(c));
-
- Map currentRequest = new HashMap<>();
- currentRequest.put("user", request.get("user"));
- currentRequest.put("namespace", request.get("namespace"));
- currentRequest.put("req_params", currentReqParams);
- currentRequest.put("event", EventType.TASK_REQUEST.getValue());
-
- client.sendTaskRequest(objectMapper.writeValueAsBytes(currentRequest), sessionId);
- }
-
- // 结束会话
- client.sendFinishSession(sessionId);
-
- // 接收响应
- while (true) {
- Message msg = client.receiveMessage();
- switch (msg.getType()) {
- case FULL_SERVER_RESPONSE:
- break;
- case AUDIO_ONLY_SERVER:
- if (!audioReceived && sentenceAudioStream.size() > 0) {
- audioReceived = true;
- }
- if (msg.getPayload() != null) {
- sentenceAudioStream.write(msg.getPayload());
- }
- break;
- default:
- // 不抛出异常,记录日志并继续处理
- log.warn("Unexpected message type: {}", msg.getType());
- }
- if (msg.getEvent() == EventType.SESSION_FINISHED) {
- break;
- }
- }
-
- // 将当前句子的音频追加到总音频流
- if (sentenceAudioStream.size() > 0) {
- totalAudioStream.write(sentenceAudioStream.toByteArray());
- }
- }
-
- // 验证是否收到音频数据
- if (totalAudioStream.size() > 0) {
- log.info("Audio data generated successfully, size: {} bytes", totalAudioStream.size());
- return totalAudioStream.toByteArray();
- } else {
- throw new RuntimeException("No audio data received");
- }
- } finally {
- // 结束连接
- client.sendFinishConnection();
- client.closeBlocking();
- }
- } catch (Exception e) {
- log.error("Error calling Volcengine TTS API: {}", e.getMessage(), e);
- throw new RuntimeException("Failed to generate voice", e);
- }
- }
-
-
- /**
- * 生成语音文件接口
- * 用户传入JSON参数,返回音频文件的播放地址
- */
- @PostMapping("/generate-voice")
- public ResponseEntity> generateVoice(@RequestBody VoiceRequest request) {
- try {
- // 1. 解析请求参数
- String endpoint = request.getEndpoint();
- String appId = request.getAppId();
- String accessToken = request.getAccessToken();
- String resourceId = request.getResourceId();
- String voice = request.getVoice();
- String text = request.getText();
- String encoding = request.getEncoding();
-
- // 1.1 验证必要参数
- if (endpoint == null || endpoint.isEmpty()) {
- return ResponseEntity.badRequest().body(Map.of("error", "endpoint cannot be null or empty"));
- }
- if (appId == null || appId.isEmpty()) {
- return ResponseEntity.badRequest().body(Map.of("error", "appId cannot be null or empty"));
- }
- if (accessToken == null || accessToken.isEmpty()) {
- return ResponseEntity.badRequest().body(Map.of("error", "accessToken cannot be null or empty"));
- }
- if (text == null || text.isEmpty()) {
- return ResponseEntity.badRequest().body(Map.of("error", "text cannot be null or empty"));
- }
-
- // 1.2 设置默认值
- if (encoding == null || encoding.isEmpty()) {
- encoding = "mp3";
- }
-
- // 2. 调用火山引擎API生成音频文件
- String audioUrl = callVolcengineTtsApi(endpoint, appId, accessToken, resourceId, voice, text, encoding);
-
- // 3. 构造并返回响应
- Map response = new HashMap<>();
- response.put("audioUrl", audioUrl);
-
- return ResponseEntity.ok(response);
- } catch (Exception e) {
- // 处理异常情况
- Map errorResponse = new HashMap<>();
- errorResponse.put("error", "生成音频文件失败: " + e.getMessage());
- return ResponseEntity.status(500).body(errorResponse);
- }
- }
-
- /**
- * 调用火山引擎TTS API生成音频文件
- */
- private String callVolcengineTtsApi(String endpoint, String appId, String accessToken,
- String resourceId, String voice, String text, String encoding) {
- try {
- // 确保resourceId不为空,如果为空则根据voice类型获取默认值
- if (resourceId == null || resourceId.isEmpty()) {
- resourceId = voiceToResourceId(voice);
- }
-
- // 生成唯一的文件名
- String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
- String randomId = UUID.randomUUID().toString().substring(0, 8);
- String fileName = "voice_" + timestamp + "_" + randomId + "." + encoding;
-
- // 获取resources/voice目录路径
- String voiceDirPath = getVoiceDirectoryPath();
- File voiceDir = new File(voiceDirPath);
- if (!voiceDir.exists()) {
- voiceDir.mkdirs();
- }
-
- String filePath = voiceDirPath + File.separator + fileName;
-
- // 设置请求头
- Map headers = new HashMap<>();
- headers.put("X-Api-App-Key", appId);
- headers.put("X-Api-Access-Key", accessToken);
- headers.put("X-Api-Resource-Id", resourceId);
- headers.put("X-Api-Connect-Id", UUID.randomUUID().toString());
-
- // 创建WebSocket客户端
- SpeechWebSocketClient client = new SpeechWebSocketClient(new URI(endpoint), headers);
- ByteArrayOutputStream totalAudioStream = new ByteArrayOutputStream();
- boolean audioReceived = false;
-
- try {
- // 连接WebSocket
- client.connectBlocking();
-
- // 构建请求参数
- Map request = new HashMap<>();
- request.put("user", Map.of("uid", UUID.randomUUID().toString()));
- request.put("namespace", "BidirectionalTTS");
-
- Map reqParams = new HashMap<>();
- reqParams.put("speaker", voice);
-
- Map audioParams = new HashMap<>();
- audioParams.put("format", encoding);
- audioParams.put("sample_rate", 24000);
- audioParams.put("enable_timestamp", true);
-
- reqParams.put("audio_params", audioParams);
- reqParams.put("additions", objectMapper.writeValueAsString(Map.of("disable_markdown_filter", false)));
-
- request.put("req_params", reqParams);
-
- // 开始连接
- client.sendStartConnection();
- // 等待连接成功
- client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.CONNECTION_STARTED);
-
- // 处理每个句子
- String[] sentences = text.split("。");
- for (int i = 0; i < sentences.length; i++) {
- if (sentences[i].trim().isEmpty()) {
- continue;
- }
-
- String sessionId = UUID.randomUUID().toString();
- ByteArrayOutputStream sentenceAudioStream = new ByteArrayOutputStream();
-
- // 开始会话
- Map startReq = new HashMap<>();
- startReq.put("user", request.get("user"));
- startReq.put("namespace", request.get("namespace"));
- startReq.put("req_params", request.get("req_params"));
- startReq.put("event", EventType.START_SESSION.getValue());
- client.sendStartSession(objectMapper.writeValueAsBytes(startReq), sessionId);
- // 等待会话开始
- client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.SESSION_STARTED);
-
- // 发送文本内容
- for (char c : sentences[i].toCharArray()) {
- @SuppressWarnings("unchecked")
- Map currentReqParams = new HashMap<>((Map) request.get("req_params"));
- currentReqParams.put("text", String.valueOf(c));
-
- Map currentRequest = new HashMap<>();
- currentRequest.put("user", request.get("user"));
- currentRequest.put("namespace", request.get("namespace"));
- currentRequest.put("req_params", currentReqParams);
- currentRequest.put("event", EventType.TASK_REQUEST.getValue());
-
- client.sendTaskRequest(objectMapper.writeValueAsBytes(currentRequest), sessionId);
- }
-
- // 结束会话
- client.sendFinishSession(sessionId);
-
- // 接收响应
- while (true) {
- Message msg = client.receiveMessage();
- switch (msg.getType()) {
- case FULL_SERVER_RESPONSE:
- break;
- case AUDIO_ONLY_SERVER:
- if (!audioReceived && sentenceAudioStream.size() > 0) {
- audioReceived = true;
- }
- if (msg.getPayload() != null) {
- sentenceAudioStream.write(msg.getPayload());
- }
- break;
- default:
- // 不抛出异常,记录日志并继续处理
- log.warn("Unexpected message type: {}", msg.getType());
- }
- if (msg.getEvent() == EventType.SESSION_FINISHED) {
- break;
- }
- }
-
- // 将当前句子的音频追加到总音频流
- if (sentenceAudioStream.size() > 0) {
- totalAudioStream.write(sentenceAudioStream.toByteArray());
- }
- }
-
- // 保存音频文件
- if (totalAudioStream.size() > 0) {
- Files.write(Paths.get(filePath), totalAudioStream.toByteArray(), StandardOpenOption.CREATE);
- log.info("Audio saved to file: {}", filePath);
- } else {
- throw new RuntimeException("No audio data received");
- }
-
- // 结束连接
- client.sendFinishConnection();
- } finally {
- client.closeBlocking();
- }
-
- // 返回音频文件的访问路径
- return "/voice/" + fileName;
- } catch (Exception e) {
- log.error("Error calling Volcengine TTS API: {}", e.getMessage(), e);
- throw new RuntimeException("Failed to generate voice", e);
- }
- }
-
- /**
- * 根据voice类型获取resourceId
- */
- private String voiceToResourceId(String voice) {
- if (voice != null && voice.startsWith("S_")) {
- return "volc.megatts.default";
- }
- return "volc.service_type.10029";
- }
-
- /**
- * 获取voice目录路径
- */
- private String getVoiceDirectoryPath() {
- try {
- // 获取当前项目根目录
- String projectRoot = System.getProperty("user.dir");
-
- // 构建目标目录路径:ruoyi-ai/ruoyi-modules/ruoyi-aihuman/src/main/resources/voice
- File targetDir = new File(projectRoot, "ruoyi-modules/ruoyi-aihuman/src/main/resources/voice");
-
- // 确保目录存在
- if (!targetDir.exists()) {
- boolean created = targetDir.mkdirs();
- if (created) {
- logger.info("成功创建目录: {}", targetDir.getAbsolutePath());
- } else {
- logger.warn("无法创建目录: {}", targetDir.getAbsolutePath());
-
- // 降级方案:直接使用项目根目录下的voice文件夹
- File fallbackDir = new File(projectRoot, "voice");
- if (!fallbackDir.exists()) {
- fallbackDir.mkdirs();
- }
- return fallbackDir.getAbsolutePath();
- }
- }
-
- return targetDir.getAbsolutePath();
- } catch (Exception e) {
- logger.error("获取音频目录路径失败", e);
-
- // 异常情况下的安全降级
- File safeDir = new File("voice");
- if (!safeDir.exists()) {
- safeDir.mkdirs();
- }
- return safeDir.getAbsolutePath();
- }
- }
-}
-
-
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanConfig.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanConfig.java
deleted file mode 100644
index 5e9fadbb..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanConfig.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.ruoyi.aihuman.domain;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 交互数字人配置对象 aihuman_config
- *
- * @author ageerle
- * @date Fri Sep 26 22:27:00 GMT+08:00 2025
- */
-@Data
-@TableName("aihuman_config")
-public class AihumanConfig implements Serializable {
-
-
- /**
- * id
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Integer id;
-
- /**
- * name
- */
- private String name;
-
- /**
- * modelName
- */
- private String modelName;
-
- /**
- * modelPath
- */
- private String modelPath;
-
- /**
- * modelParams
- */
- private String modelParams;
-
- /**
- * agentParams
- */
- private String agentParams;
-
- /**
- * createTime
- */
- private LocalDateTime createTime;
-
- /**
- * updateTime
- */
- private LocalDateTime updateTime;
-
- /**
- * status
- */
- private Integer status;
-
- /**
- * publish
- */
- private Integer publish;
-
-
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanInfo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanInfo.java
deleted file mode 100644
index 9be681f2..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanInfo.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.ruoyi.aihuman.domain;
-
-import com.baomidou.mybatisplus.annotation.*;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * AI人类交互信息实体类
- *
- * @author QingYunAI
- */
-@Data
-@TableName("aihuman_info")
-public class AihumanInfo implements Serializable {
- private static final long serialVersionUID = 1L;
-
- /**
- * 主键ID
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Long id;
-
- /**
- * 交互名称
- */
- private String name;
-
- /**
- * 交互内容
- */
- private String content;
-
- /**
- * 创建时间
- */
- @TableField(fill = FieldFill.INSERT)
- private Date createTime;
-
- /**
- * 更新时间
- */
- @TableField(fill = FieldFill.INSERT_UPDATE)
- private Date updateTime;
-
- /**
- * 删除标志(0代表存在 2代表删除)
- */
- @TableLogic
- private String delFlag;
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanRealConfig.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanRealConfig.java
deleted file mode 100644
index c87f9bcd..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/AihumanRealConfig.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package org.ruoyi.aihuman.domain;
-
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 真人交互数字人配置对象 aihuman_real_config
- *
- * @author ageerle
- * @date Tue Oct 21 11:46:52 GMT+08:00 2025
- */
-@Data
-@TableName("aihuman_real_config")
-public class AihumanRealConfig implements Serializable {
-
-
- /**
- * 主键id
- */
- @TableId(value = "id", type = IdType.AUTO)
- private Integer id;
-
- /**
- * 场景名称
- */
- private String name;
-
- /**
- * 真人形象名称
- */
- private String avatars;
-
- /**
- * 模型名称
- */
- private String models;
-
- /**
- * 形象参数(预留)
- */
- private String avatarsParams;
-
- /**
- * 模型参数(预留)
- */
- private String modelsParams;
-
- /**
- * 智能体参数(扣子)
- */
- private String agentParams;
-
- /**
- * 创建时间
- */
- private LocalDateTime createTime;
-
- /**
- * 更新时间
- */
- private LocalDateTime updateTime;
-
- /**
- * 状态
- */
- private Integer status;
-
- /**
- * 发布状态
- */
- private Integer publish;
-
- /**
- * 运行参数
- */
- private String runParams;
-
- /**
- * 运行状态
- */
- private String runStatus;
-
- /**
- * 创建部门
- */
- private String createDept;
-
- /**
- * 创建用户
- */
- private String createBy;
-
- /**
- * 更新用户
- */
- private String updateBy;
-
-
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/VoiceRequest.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/VoiceRequest.java
deleted file mode 100644
index 4ed0d017..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/VoiceRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.ruoyi.aihuman.domain;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Data;
-
-
-/**
- * 语音请求参数实体类
- */
-@Data
-public class VoiceRequest {
-
- @JsonProperty("ENDPOINT")
- private String endpoint;
- private String appId;
- private String accessToken;
- private String resourceId;
- private String voice;
- private String text;
- private String encoding;
-
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanConfigBo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanConfigBo.java
deleted file mode 100644
index ac9ffad0..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanConfigBo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.ruoyi.aihuman.domain.bo;
-
-import io.github.linpeilie.annotations.AutoMapper;
-import jakarta.validation.constraints.NotNull;
-import lombok.Data;
-import org.ruoyi.aihuman.domain.AihumanConfig;
-import org.ruoyi.common.core.validate.AddGroup;
-import org.ruoyi.common.core.validate.EditGroup;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 交互数字人配置业务对象 aihuman_config
- *
- * @author ageerle
- * @date Fri Sep 26 22:27:00 GMT+08:00 2025
- */
-@Data
-
-@AutoMapper(target = AihumanConfig.class, reverseConvertGenerate = false)
-public class AihumanConfigBo implements Serializable {
-
- private Integer id;
-
- /**
- * name
- */
- private String name;
- /**
- * modelName
- */
- private String modelName;
- /**
- * modelPath
- */
- private String modelPath;
- /**
- * modelParams
- */
- private String modelParams;
- /**
- * agentParams
- */
- private String agentParams;
- /**
- * createTime
- */
- private LocalDateTime createTime;
- /**
- * updateTime
- */
- private LocalDateTime updateTime;
- /**
- * status
- */
- @NotNull(message = "status不能为空", groups = {AddGroup.class, EditGroup.class})
- private Integer status;
- /**
- * publish
- */
- @NotNull(message = "publish不能为空", groups = {AddGroup.class, EditGroup.class})
- private Integer publish;
-
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanInfoBo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanInfoBo.java
deleted file mode 100644
index c6e49989..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanInfoBo.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.ruoyi.aihuman.domain.bo;
-
-import io.github.linpeilie.annotations.AutoMapper;
-import lombok.Data;
-import org.ruoyi.aihuman.domain.AihumanInfo;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 数字人信息管理业务对象 aihuman_info
- *
- * @author ageerle
- * @date Fri Sep 26 20:03:06 GMT+08:00 2025
- */
-@Data
-
-@AutoMapper(target = AihumanInfo.class, reverseConvertGenerate = false)
-public class AihumanInfoBo implements Serializable {
-
- private Long id;
-
- /**
- * 交互名称
- */
- private String name;
- /**
- * 交互内容
- */
- private String content;
- /**
- * 创建时间
- */
- private LocalDateTime createTime;
- /**
- * 更新时间
- */
- private LocalDateTime updateTime;
- /**
- * 删除标志(0代表存在 2代表删除)
- */
- private String delFlag;
-
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanRealConfigBo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanRealConfigBo.java
deleted file mode 100644
index 2008c97c..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/bo/AihumanRealConfigBo.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.ruoyi.aihuman.domain.bo;
-
-import io.github.linpeilie.annotations.AutoMapper;
-import lombok.Data;
-import org.ruoyi.aihuman.domain.AihumanRealConfig;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-/**
- * 真人交互数字人配置业务对象 aihuman_real_config
- *
- * @author ageerle
- * @date Tue Oct 21 11:46:52 GMT+08:00 2025
- */
-@Data
-
-@AutoMapper(target = AihumanRealConfig.class, reverseConvertGenerate = false)
-public class AihumanRealConfigBo implements Serializable {
-
- private Integer id;
-
- /**
- * 场景名称
- */
- private String name;
- /**
- * 真人形象名称
- */
- private String avatars;
- /**
- * 模型名称
- */
- private String models;
- /**
- * 形象参数(预留)
- */
- private String avatarsParams;
- /**
- * 模型参数(预留)
- */
- private String modelsParams;
- /**
- * 智能体参数(扣子)
- */
- private String agentParams;
- /**
- * 创建时间
- */
- private LocalDateTime createTime;
- /**
- * 更新时间
- */
- private LocalDateTime updateTime;
- /**
- * 状态
- */
- private Integer status;
- /**
- * 发布状态
- */
- private Integer publish;
-
- /**
- * 运行参数
- */
- private String runParams;
-
- /**
- * 运行状态
- */
- private String runStatus;
-
- /**
- * 创建部门
- */
- private String createDept;
- /**
- * 创建用户
- */
- private String createBy;
- /**
- * 更新用户
- */
- private String updateBy;
-
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanConfigVo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanConfigVo.java
deleted file mode 100644
index 93fffa76..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanConfigVo.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.ruoyi.aihuman.domain.vo;
-
-import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
-import cn.idev.excel.annotation.ExcelProperty;
-import io.github.linpeilie.annotations.AutoMapper;
-import lombok.Data;
-import org.ruoyi.aihuman.domain.AihumanConfig;
-import org.ruoyi.common.excel.annotation.ExcelDictFormat;
-import org.ruoyi.common.excel.convert.ExcelDictConvert;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-
-/**
- * 交互数字人配置视图对象 aihuman_config
- *
- * @author ageerle
- * @date Fri Sep 26 22:27:00 GMT+08:00 2025
- */
-@Data
-@ExcelIgnoreUnannotated
-@AutoMapper(target = AihumanConfig.class)
-public class AihumanConfigVo implements Serializable {
-
- private Integer id;
- /**
- * name
- */
- @ExcelProperty(value = "name")
- private String name;
- /**
- * modelName
- */
- @ExcelProperty(value = "modelName")
- private String modelName;
- /**
- * modelPath
- */
- @ExcelProperty(value = "modelPath")
- private String modelPath;
- /**
- * modelParams
- */
- @ExcelProperty(value = "modelParams")
- private String modelParams;
- /**
- * agentParams
- */
- @ExcelProperty(value = "agentParams")
- private String agentParams;
- /**
- * createTime
- */
- @ExcelProperty(value = "createTime")
- private LocalDateTime createTime;
- /**
- * updateTime
- */
- @ExcelProperty(value = "updateTime")
- private LocalDateTime updateTime;
- /**
- * status
- */
- @ExcelProperty(value = "status", converter = ExcelDictConvert.class)
- @ExcelDictFormat(dictType = "sys_common_status")
- private Integer status;
- /**
- * publish
- */
- @ExcelProperty(value = "publish", converter = ExcelDictConvert.class)
- @ExcelDictFormat(dictType = "sys_common_status")
- private Integer publish;
-
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanInfoVo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanInfoVo.java
deleted file mode 100644
index a36d7fbd..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanInfoVo.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.ruoyi.aihuman.domain.vo;
-
-import io.github.linpeilie.annotations.AutoMapper;
-import lombok.Data;
-import org.ruoyi.aihuman.domain.AihumanInfo;
-
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * AI人类交互信息视图对象
- *
- * @author QingYunAI
- */
-@Data
-@AutoMapper(target = AihumanInfo.class)
-public class AihumanInfoVo implements Serializable {
- private static final long serialVersionUID = 1L;
-
- /**
- * 主键ID
- */
- private Long id;
-
- /**
- * 交互名称
- */
- private String name;
-
- /**
- * 交互内容
- */
- private String content;
-
- /**
- * 创建时间
- */
- private Date createTime;
-
- /**
- * 更新时间
- */
- private Date updateTime;
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanRealConfigVo.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanRealConfigVo.java
deleted file mode 100644
index f6fe020e..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/vo/AihumanRealConfigVo.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package org.ruoyi.aihuman.domain.vo;
-
-import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
-import cn.idev.excel.annotation.ExcelProperty;
-import io.github.linpeilie.annotations.AutoMapper;
-import lombok.Data;
-import org.ruoyi.aihuman.domain.AihumanRealConfig;
-import org.ruoyi.common.excel.annotation.ExcelDictFormat;
-import org.ruoyi.common.excel.convert.ExcelDictConvert;
-
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
-
-/**
- * 真人交互数字人配置视图对象 aihuman_real_config
- *
- * @author ageerle
- * @date Tue Oct 21 11:46:52 GMT+08:00 2025
- */
-@Data
-@ExcelIgnoreUnannotated
-@AutoMapper(target = AihumanRealConfig.class)
-public class AihumanRealConfigVo implements Serializable {
-
- private Integer id;
- /**
- * 场景名称
- */
- @ExcelProperty(value = "场景名称")
- private String name;
- /**
- * 真人形象名称
- */
- @ExcelProperty(value = "真人形象名称")
- private String avatars;
- /**
- * 模型名称
- */
- @ExcelProperty(value = "模型名称")
- private String models;
- /**
- * 形象参数(预留)
- */
- @ExcelProperty(value = "形象参数", converter = ExcelDictConvert.class)
- @ExcelDictFormat(readConverterExp = "$column.readConverterExp()")
- private String avatarsParams;
- /**
- * 模型参数(预留)
- */
- @ExcelProperty(value = "模型参数", converter = ExcelDictConvert.class)
- @ExcelDictFormat(readConverterExp = "$column.readConverterExp()")
- private String modelsParams;
- /**
- * 智能体参数(扣子)
- */
- @ExcelProperty(value = "智能体参数", converter = ExcelDictConvert.class)
- @ExcelDictFormat(readConverterExp = "$column.readConverterExp()")
- private String agentParams;
- /**
- * 创建时间
- */
- @ExcelProperty(value = "创建时间")
- private LocalDateTime createTime;
- /**
- * 更新时间
- */
- @ExcelProperty(value = "更新时间")
- private LocalDateTime updateTime;
- /**
- * 状态
- */
- @ExcelProperty(value = "状态")
- private Integer status;
- /**
- * 发布状态
- */
- @ExcelProperty(value = "发布状态")
- private Integer publish;
-
- /**
- * 运行参数
- */
- @ExcelProperty(value = "运行参数")
- private String runParams;
-
- /**
- * 运行状态
- */
- @ExcelProperty(value = "运行状态")
- private String runStatus;
-
- /**
- * 创建部门
- */
- @ExcelProperty(value = "创建部门")
- private String createDept;
- /**
- * 创建用户
- */
- @ExcelProperty(value = "创建用户")
- private String createBy;
- /**
- * 更新用户
- */
- @ExcelProperty(value = "更新用户")
- private String updateBy;
-
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanConfigMapper.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanConfigMapper.java
deleted file mode 100644
index 3a26ef0b..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanConfigMapper.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.ruoyi.aihuman.mapper;
-
-import org.apache.ibatis.annotations.Mapper;
-import org.ruoyi.aihuman.domain.AihumanConfig;
-import org.ruoyi.aihuman.domain.vo.AihumanConfigVo;
-import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
-
-/**
- * 交互数字人配置Mapper接口
- *
- * @author ageerle
- * @date Fri Sep 26 22:27:00 GMT+08:00 2025
- */
-@Mapper
-public interface AihumanConfigMapper extends BaseMapperPlus {
-
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanInfoMapper.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanInfoMapper.java
deleted file mode 100644
index a64d0b13..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanInfoMapper.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.ruoyi.aihuman.mapper;
-
-import org.apache.ibatis.annotations.Mapper;
-import org.ruoyi.aihuman.domain.AihumanInfo;
-import org.ruoyi.aihuman.domain.vo.AihumanInfoVo;
-import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
-
-/**
- * AI人类交互信息Mapper接口
- *
- * @author QingYunAI
- */
-@Mapper
-public interface AihumanInfoMapper extends BaseMapperPlus {
-
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanRealConfigMapper.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanRealConfigMapper.java
deleted file mode 100644
index 9ae4768e..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/mapper/AihumanRealConfigMapper.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.ruoyi.aihuman.mapper;
-
-import org.apache.ibatis.annotations.Mapper;
-import org.ruoyi.aihuman.domain.AihumanRealConfig;
-import org.ruoyi.aihuman.domain.vo.AihumanRealConfigVo;
-import org.ruoyi.common.mybatis.core.mapper.BaseMapperPlus;
-
-/**
- * 真人交互数字人配置Mapper接口
- *
- * @author ageerle
- * @date Tue Oct 21 11:46:52 GMT+08:00 2025
- */
-@Mapper
-public interface AihumanRealConfigMapper extends BaseMapperPlus {
-
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/CompressionBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/CompressionBits.java
deleted file mode 100644
index 78794aa4..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/CompressionBits.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.Getter;
-
-@Getter
-public enum CompressionBits {
- None_((byte) 0),
- Gzip((byte) 0b1),
- Custom((byte) 0b11),
- ;
-
- private final byte value;
-
- CompressionBits(byte b) {
- this.value = b;
- }
-
- public static CompressionBits fromValue(int value) {
- for (CompressionBits type : CompressionBits.values()) {
- if (type.value == value) {
- return type;
- }
- }
- throw new IllegalArgumentException("Unknown CompressionBits value: " + value);
- }
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/EventType.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/EventType.java
deleted file mode 100644
index ece69af3..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/EventType.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.Getter;
-
-@Getter
-public enum EventType {
- // Default event
- NONE(0),
-
- // Upstream Connection events (1-49)
- START_CONNECTION(1),
- START_TASK(1),
- FINISH_CONNECTION(2),
- FINISH_TASK(2),
-
- // Downstream Connection events (50-99)
- CONNECTION_STARTED(50),
- TASK_STARTED(50),
- CONNECTION_FAILED(51),
- TASK_FAILED(51),
- CONNECTION_FINISHED(52),
- TASK_FINISHED(52),
-
- // Upstream Session events (100-149)
- START_SESSION(100),
- CANCEL_SESSION(101),
- FINISH_SESSION(102),
-
- // Downstream Session events (150-199)
- SESSION_STARTED(150),
- SESSION_CANCELED(151),
- SESSION_FINISHED(152),
- SESSION_FAILED(153),
- USAGE_RESPONSE(154),
- CHARGE_DATA(154),
-
- // Upstream General events (200-249)
- TASK_REQUEST(200),
- UPDATE_CONFIG(201),
-
- // Downstream General events (250-299)
- AUDIO_MUTED(250),
-
- // Upstream TTS events (300-349)
- SAY_HELLO(300),
-
- // Downstream TTS events (350-399)
- TTS_SENTENCE_START(350),
- TTS_SENTENCE_END(351),
- TTS_RESPONSE(352),
- TTS_ENDED(359),
- PODCAST_ROUND_START(360),
- PODCAST_ROUND_RESPONSE(361),
- PODCAST_ROUND_END(362),
-
- // Downstream ASR events (450-499)
- ASR_INFO(450),
- ASR_RESPONSE(451),
- ASR_ENDED(459),
-
- // Upstream Chat events (500-549)
- CHAT_TTS_TEXT(500),
-
- // Downstream Chat events (550-599)
- CHAT_RESPONSE(550),
- CHAT_ENDED(559),
-
- // Subtitle events (650-699)
- SOURCE_SUBTITLE_START(650),
- SOURCE_SUBTITLE_RESPONSE(651),
- SOURCE_SUBTITLE_END(652),
- TRANSLATION_SUBTITLE_START(653),
- TRANSLATION_SUBTITLE_RESPONSE(654),
- TRANSLATION_SUBTITLE_END(655);
-
- private final int value;
-
- EventType(int value) {
- this.value = value;
- }
-
- public static EventType fromValue(int value) {
- for (EventType type : EventType.values()) {
- if (type.value == value) {
- return type;
- }
- }
- throw new IllegalArgumentException("Unknown EventType value: " + value);
- }
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/HeaderSizeBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/HeaderSizeBits.java
deleted file mode 100644
index 6c09a20d..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/HeaderSizeBits.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.Getter;
-
-@Getter
-public enum HeaderSizeBits {
- HeaderSize4((byte) 1),
- HeaderSize8((byte) 2),
- HeaderSize12((byte) 3),
- HeaderSize16((byte) 4),
- ;
-
- private final byte value;
-
- HeaderSizeBits(byte b) {
- this.value = b;
- }
-
- public static HeaderSizeBits fromValue(int value) {
- for (HeaderSizeBits type : HeaderSizeBits.values()) {
- if (type.value == value) {
- return type;
- }
- }
- throw new IllegalArgumentException("Unknown HeaderSizeBits value: " + value);
- }
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/Message.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/Message.java
deleted file mode 100644
index d3605edc..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/Message.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.charset.StandardCharsets;
-
-@Slf4j
-@Data
-public class Message {
- private byte version = VersionBits.Version1.getValue();
- private byte headerSize = HeaderSizeBits.HeaderSize4.getValue();
- private MsgType type;
- private MsgTypeFlagBits flag;
- private byte serialization = SerializationBits.JSON.getValue();
- private byte compression = 0;
-
- private EventType event;
- private String sessionId;
- private String connectId;
- private int sequence;
- private int errorCode;
-
- private byte[] payload;
-
- public Message(MsgType type, MsgTypeFlagBits flag) {
- this.type = type;
- this.flag = flag;
- }
-
- public static Message unmarshal(byte[] data) throws Exception {
- ByteBuffer buffer = ByteBuffer.wrap(data);
-
- byte type_and_flag = data[1];
- MsgType type = MsgType.fromValue((type_and_flag >> 4) & 0x0F);
- MsgTypeFlagBits flag = MsgTypeFlagBits.fromValue(type_and_flag & 0x0F);
-
- // Read version and header size
- int versionAndHeaderSize = buffer.get();
- VersionBits version = VersionBits.fromValue((versionAndHeaderSize >> 4) & 0x0F);
- HeaderSizeBits headerSize = HeaderSizeBits.fromValue(versionAndHeaderSize & 0x0F);
-
- // Skip second byte
- buffer.get();
-
- // Read serialization and compression method
- int serializationCompression = buffer.get();
- SerializationBits serialization = SerializationBits.fromValue((serializationCompression >> 4) & 0x0F);
- CompressionBits compression = CompressionBits.fromValue(serializationCompression & 0x0F);
-
- // Skip padding bytes
- int headerSizeInt = 4 * (int) headerSize.getValue();
- int paddingSize = headerSizeInt - 3;
- while (paddingSize > 0) {
- buffer.get();
- paddingSize -= 1;
- }
-
- Message message = new Message(type, flag);
- message.setVersion(version.getValue());
- message.setHeaderSize(headerSize.getValue());
- message.setSerialization(serialization.getValue());
- message.setCompression(compression.getValue());
-
- // Read sequence if present
- if (flag == MsgTypeFlagBits.POSITIVE_SEQ || flag == MsgTypeFlagBits.NEGATIVE_SEQ) {
- // Read 4 bytes from ByteBuffer and parse as int (big-endian)
- byte[] sequeueBytes = new byte[4];
- if (buffer.remaining() >= 4) {
- buffer.get(sequeueBytes); // Read 4 bytes into array
- ByteBuffer wrapper = ByteBuffer.wrap(sequeueBytes);
- wrapper.order(ByteOrder.BIG_ENDIAN); // Set big-endian order
- message.setSequence(wrapper.getInt());
- }
- }
-
- // Read event if present
- if (flag == MsgTypeFlagBits.WITH_EVENT) {
- // Read 4 bytes from ByteBuffer and parse as int (big-endian)
- byte[] eventBytes = new byte[4];
- if (buffer.remaining() >= 4) {
- buffer.get(eventBytes); // Read 4 bytes into array
- ByteBuffer wrapper = ByteBuffer.wrap(eventBytes);
- wrapper.order(ByteOrder.BIG_ENDIAN); // Set big-endian order
- message.setEvent(EventType.fromValue(wrapper.getInt()));
- }
-
- if (type != MsgType.ERROR && !(message.event == EventType.START_CONNECTION
- || message.event == EventType.FINISH_CONNECTION ||
- message.event == EventType.CONNECTION_STARTED
- || message.event == EventType.CONNECTION_FAILED ||
- message.event == EventType.CONNECTION_FINISHED)) {
- // Read sessionId if present
- int sessionIdLength = buffer.getInt();
- if (sessionIdLength > 0) {
- byte[] sessionIdBytes = new byte[sessionIdLength];
- buffer.get(sessionIdBytes);
- message.setSessionId(new String(sessionIdBytes, StandardCharsets.UTF_8));
- }
- }
-
- if (message.event == EventType.CONNECTION_STARTED || message.event == EventType.CONNECTION_FAILED
- || message.event == EventType.CONNECTION_FINISHED) {
- // Read connectId if present
- int connectIdLength = buffer.getInt();
- if (connectIdLength > 0) {
- byte[] connectIdBytes = new byte[connectIdLength];
- buffer.get(connectIdBytes);
- message.setConnectId(new String(connectIdBytes, StandardCharsets.UTF_8));
- }
- }
- }
-
- // Read errorCode if present
- if (type == MsgType.ERROR) {
- // Read 4 bytes from ByteBuffer and parse as int (big-endian)
- byte[] errorCodeBytes = new byte[4];
- if (buffer.remaining() >= 4) {
- buffer.get(errorCodeBytes); // Read 4 bytes into array
- ByteBuffer wrapper = ByteBuffer.wrap(errorCodeBytes);
- wrapper.order(ByteOrder.BIG_ENDIAN); // Set big-endian order
- message.setErrorCode(wrapper.getInt());
- }
- }
-
- // Read remaining bytes as payload
- if (buffer.remaining() > 0) {
- // 4 bytes length
- int payloadLength = buffer.getInt();
- if (payloadLength > 0) {
- byte[] payloadBytes = new byte[payloadLength];
- buffer.get(payloadBytes);
- message.setPayload(payloadBytes);
- }
- }
-
- return message;
- }
-
- public byte[] marshal() throws Exception {
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-
- // Write header
- buffer.write((version & 0x0F) << 4 | (headerSize & 0x0F));
- buffer.write((type.getValue() & 0x0F) << 4 | (flag.getValue() & 0x0F));
- buffer.write((serialization & 0x0F) << 4 | (compression & 0x0F));
-
- int headerSizeInt = 4 * (int) headerSize;
- int padding = headerSizeInt - buffer.size();
- while (padding > 0) {
- buffer.write(0);
- padding -= 1;
- }
-
- // Write event if present
- if (event != null) {
- byte[] eventBytes = ByteBuffer.allocate(4).putInt(event.getValue()).array();
- buffer.write(eventBytes);
- }
-
- // Write sessionId if present
- if (sessionId != null) {
- byte[] sessionIdBytes = sessionId.getBytes(StandardCharsets.UTF_8);
- buffer.write(ByteBuffer.allocate(4).putInt(sessionIdBytes.length).array());
- buffer.write(sessionIdBytes);
- }
-
- // Write connectId if present
- if (connectId != null) {
- byte[] connectIdBytes = connectId.getBytes(StandardCharsets.UTF_8);
- buffer.write(ByteBuffer.allocate(4).putInt(connectIdBytes.length).array());
- buffer.write(connectIdBytes);
- }
-
- // Write sequence if present
- if (sequence != 0) {
- buffer.write(ByteBuffer.allocate(4).putInt(sequence).array());
- }
-
- // Write errorCode if present
- if (errorCode != 0) {
- buffer.write(ByteBuffer.allocate(4).putInt(errorCode).array());
- }
-
- // Write payload if present
- if (payload != null && payload.length > 0) {
- buffer.write(ByteBuffer.allocate(4).putInt(payload.length).array());
- buffer.write(payload);
- }
- return buffer.toByteArray();
- }
-
- @Override
- public String toString() {
- switch (this.type) {
- case AUDIO_ONLY_SERVER:
- case AUDIO_ONLY_CLIENT:
- if (this.flag == MsgTypeFlagBits.POSITIVE_SEQ || this.flag == MsgTypeFlagBits.NEGATIVE_SEQ) {
- return String.format("MsgType: %s, EventType: %s, Sequence: %d, PayloadSize: %d", this.type, this.event, this.sequence,
- this.payload != null ? this.payload.length : 0);
- }
- return String.format("MsgType: %s, EventType: %s, PayloadSize: %d", this.type, this.event,
- this.payload != null ? this.payload.length : 0);
- case ERROR:
- return String.format("MsgType: %s, EventType: %s, ErrorCode: %d, Payload: %s", this.type, this.event, this.errorCode,
- this.payload != null ? new String(this.payload) : "null");
- default:
- if (this.flag == MsgTypeFlagBits.POSITIVE_SEQ || this.flag == MsgTypeFlagBits.NEGATIVE_SEQ) {
- return String.format("MsgType: %s, EventType: %s, Sequence: %d, Payload: %s",
- this.type, this.event, this.sequence,
- this.payload != null ? new String(this.payload) : "null");
- }
- return String.format("MsgType: %s, EventType: %s, Payload: %s", this.type, this.event,
- this.payload != null ? new String(this.payload) : "null");
- }
- }
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgType.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgType.java
deleted file mode 100644
index 965f40e8..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgType.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.Getter;
-
-@Getter
-public enum MsgType {
- INVALID((byte) 0),
- FULL_CLIENT_REQUEST((byte) 0b1),
- AUDIO_ONLY_CLIENT((byte) 0b10),
- FULL_SERVER_RESPONSE((byte) 0b1001),
- AUDIO_ONLY_SERVER((byte) 0b1011),
- FRONT_END_RESULT_SERVER((byte) 0b1100),
- ERROR((byte) 0b1111);
-
- private final byte value;
-
- MsgType(byte value) {
- this.value = value;
- }
-
- public static MsgType fromValue(int value) {
- for (MsgType type : MsgType.values()) {
- if (type.value == value) {
- return type;
- }
- }
- throw new IllegalArgumentException("Unknown MsgType value: " + value);
- }
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgTypeFlagBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgTypeFlagBits.java
deleted file mode 100644
index 393a24dc..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/MsgTypeFlagBits.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.Getter;
-
-@Getter
-public enum MsgTypeFlagBits {
- NO_SEQ((byte) 0), // Non-terminating packet without sequence number
- POSITIVE_SEQ((byte) 0b1), // Non-terminating packet with positive sequence number
- LAST_NO_SEQ((byte) 0b10), // Terminating packet without sequence number
- NEGATIVE_SEQ((byte) 0b11), // Terminating packet with negative sequence number
- WITH_EVENT((byte) 0b100); // Packet containing event number
-
- private final byte value;
-
- MsgTypeFlagBits(byte value) {
- this.value = value;
- }
-
- public static MsgTypeFlagBits fromValue(int value) {
- for (MsgTypeFlagBits flag : MsgTypeFlagBits.values()) {
- if (flag.value == value) {
- return flag;
- }
- }
- throw new IllegalArgumentException("Unknown MsgTypeFlagBits value: " + value);
- }
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SerializationBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SerializationBits.java
deleted file mode 100644
index 01e8f102..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SerializationBits.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.Getter;
-
-@Getter
-public enum SerializationBits {
- Raw((byte) 0),
- JSON((byte) 0b1),
- Thrift((byte) 0b11),
- Custom((byte) 0b1111),
- ;
-
- private final byte value;
-
- SerializationBits(byte b) {
- this.value = b;
- }
-
- public static SerializationBits fromValue(int value) {
- for (SerializationBits type : SerializationBits.values()) {
- if (type.value == value) {
- return type;
- }
- }
- throw new IllegalArgumentException("Unknown SerializationBits value: " + value);
- }
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SpeechWebSocketClient.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SpeechWebSocketClient.java
deleted file mode 100644
index c41e57b3..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/SpeechWebSocketClient.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.extern.slf4j.Slf4j;
-import org.java_websocket.client.WebSocketClient;
-import org.java_websocket.handshake.ServerHandshake;
-
-import java.net.URI;
-import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-
-@Slf4j
-public class SpeechWebSocketClient extends WebSocketClient {
- private final BlockingQueue messageQueue = new LinkedBlockingQueue<>();
-
- public SpeechWebSocketClient(URI serverUri, Map headers) {
- super(serverUri, headers);
- }
-
- @Override
- public void onOpen(ServerHandshake handshakedata) {
- log.info("WebSocket connection established, Logid: {}", handshakedata.getFieldValue("x-tt-logid"));
- }
-
- @Override
- public void onMessage(String message) {
- log.warn("Received unexpected text message: {}", message);
- }
-
- @Override
- public void onMessage(ByteBuffer bytes) {
- try {
- Message message = Message.unmarshal(bytes.array());
- messageQueue.put(message);
- } catch (Exception e) {
- log.error("Failed to parse message", e);
- }
- }
-
- @Override
- public void onClose(int code, String reason, boolean remote) {
- log.info("WebSocket connection closed: code={}, reason={}, remote={}", code, reason, remote);
- }
-
- @Override
- public void onError(Exception ex) {
- log.error("WebSocket error", ex);
- }
-
- public void sendStartConnection() throws Exception {
- Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT);
- message.setEvent(EventType.START_CONNECTION);
- message.setPayload("{}".getBytes());
- sendMessage(message);
- }
-
- public void sendFinishConnection() throws Exception {
- Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT);
- message.setEvent(EventType.FINISH_CONNECTION);
- sendMessage(message);
- }
-
- public void sendStartSession(byte[] payload, String sessionId) throws Exception {
- Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT);
- message.setEvent(EventType.START_SESSION);
- message.setSessionId(sessionId);
- message.setPayload(payload);
- sendMessage(message);
- }
-
- public void sendFinishSession(String sessionId) throws Exception {
- Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT);
- message.setEvent(EventType.FINISH_SESSION);
- message.setSessionId(sessionId);
- message.setPayload("{}".getBytes());
- sendMessage(message);
- }
-
- public void sendTaskRequest(byte[] payload, String sessionId) throws Exception {
- Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.WITH_EVENT);
- message.setEvent(EventType.TASK_REQUEST);
- message.setSessionId(sessionId);
- message.setPayload(payload);
- sendMessage(message);
- }
-
- public void sendFullClientMessage(byte[] payload) throws Exception {
- Message message = new Message(MsgType.FULL_CLIENT_REQUEST, MsgTypeFlagBits.NO_SEQ);
- message.setPayload(payload);
- sendMessage(message);
- }
-
- public void sendMessage(Message message) throws Exception {
- log.info("Send: {}", message);
- send(message.marshal());
- }
-
- public Message receiveMessage() throws InterruptedException {
- Message message = messageQueue.take();
- log.info("Receive: {}", message);
- return message;
- }
-
- public Message waitForMessage(MsgType type, EventType event) throws InterruptedException {
- while (true) {
- Message message = receiveMessage();
- if (message.getType() == type && message.getEvent() == event) {
- return message;
- } else {
- throw new RuntimeException("Unexpected message: " + message);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/VersionBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/VersionBits.java
deleted file mode 100644
index 6f4a8174..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/VersionBits.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.ruoyi.aihuman.protocol;
-
-import lombok.Getter;
-
-@Getter
-public enum VersionBits {
- Version1((byte) 1),
- Version2((byte) 2),
- Version3((byte) 3),
- Version4((byte) 4),
- ;
-
- private final byte value;
-
- VersionBits(byte b) {
- this.value = b;
- }
-
- public static VersionBits fromValue(int value) {
- for (VersionBits type : VersionBits.values()) {
- if (type.value == value) {
- return type;
- }
- }
- throw new IllegalArgumentException("Unknown VersionBits value: " + value);
- }
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanConfigService.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanConfigService.java
deleted file mode 100644
index b70367cb..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanConfigService.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.ruoyi.aihuman.service;
-
-import org.ruoyi.aihuman.domain.bo.AihumanConfigBo;
-import org.ruoyi.aihuman.domain.vo.AihumanConfigVo;
-import org.ruoyi.common.mybatis.core.page.PageQuery;
-import org.ruoyi.common.mybatis.core.page.TableDataInfo;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 交互数字人配置Service接口
- *
- * @author ageerle
- * @date Fri Sep 26 22:27:00 GMT+08:00 2025
- */
-public interface AihumanConfigService {
-
- /**
- * 查询交互数字人配置
- */
- AihumanConfigVo queryById(Integer id);
-
- /**
- * 查询交互数字人配置列表
- */
- TableDataInfo queryPageList(AihumanConfigBo bo, PageQuery pageQuery);
-
- /**
- * 查询交互数字人配置列表
- */
- List queryList(AihumanConfigBo bo);
-
- /**
- * 新增交互数字人配置
- */
- Boolean insertByBo(AihumanConfigBo bo);
-
- /**
- * 修改交互数字人配置
- */
- Boolean updateByBo(AihumanConfigBo bo);
-
- /**
- * 校验并批量删除交互数字人配置信息
- */
- Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanRealConfigService.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanRealConfigService.java
deleted file mode 100644
index 56398190..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanRealConfigService.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.ruoyi.aihuman.service;
-
-import org.ruoyi.aihuman.domain.bo.AihumanRealConfigBo;
-import org.ruoyi.aihuman.domain.vo.AihumanRealConfigVo;
-import org.ruoyi.common.mybatis.core.page.PageQuery;
-import org.ruoyi.common.mybatis.core.page.TableDataInfo;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 真人交互数字人配置Service接口
- *
- * @author ageerle
- * @date Tue Oct 21 11:46:52 GMT+08:00 2025
- */
-public interface AihumanRealConfigService {
-
- /**
- * 查询真人交互数字人配置
- */
- AihumanRealConfigVo queryById(Integer id);
-
- /**
- * 查询真人交互数字人配置列表
- */
- TableDataInfo queryPageList(AihumanRealConfigBo bo, PageQuery pageQuery);
-
- /**
- * 查询真人交互数字人配置列表
- */
- List queryList(AihumanRealConfigBo bo);
-
- /**
- * 新增真人交互数字人配置
- */
- Boolean insertByBo(AihumanRealConfigBo bo);
-
- /**
- * 修改真人交互数字人配置
- */
- Boolean updateByBo(AihumanRealConfigBo bo);
-
- /**
- * 执行真人交互数字人配置
- */
- Boolean runByBo(AihumanRealConfigBo bo);
-
- /**
- * 校验并批量删除真人交互数字人配置信息
- */
- Boolean deleteWithValidByIds(Collection ids, Boolean isValid);
-
- // 在AihumanRealConfigService接口中添加
- Boolean stopByBo(AihumanRealConfigBo bo);
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanVolcengineService.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanVolcengineService.java
deleted file mode 100644
index 6c99f013..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/AihumanVolcengineService.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package org.ruoyi.aihuman.service;
-
-public interface AihumanVolcengineService {
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/IAihumanInfoService.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/IAihumanInfoService.java
deleted file mode 100644
index a07001d6..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/IAihumanInfoService.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.ruoyi.aihuman.service;
-
-import org.ruoyi.aihuman.domain.AihumanInfo;
-import org.ruoyi.aihuman.domain.vo.AihumanInfoVo;
-import org.ruoyi.common.mybatis.core.page.PageQuery;
-import org.ruoyi.common.mybatis.core.page.TableDataInfo;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * AI人类交互信息Service接口
- *
- * @author QingYunAI
- */
-public interface IAihumanInfoService {
-
- /**
- * 查询AI人类交互信息
- */
- AihumanInfoVo queryById(Long id);
-
- /**
- * 查询AI人类交互信息列表
- */
- TableDataInfo queryPageList(AihumanInfo record, PageQuery pageQuery);
-
- /**
- * 查询AI人类交互信息列表
- */
- List queryList(AihumanInfo record);
-
- /**
- * 新增AI人类交互信息
- */
- int insert(AihumanInfo record);
-
- /**
- * 修改AI人类交互信息
- */
- int update(AihumanInfo record);
-
- /**
- * 批量删除AI人类交互信息
- */
- int deleteWithValidByIds(Collection ids, Boolean isValid);
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanConfigServiceImpl.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanConfigServiceImpl.java
deleted file mode 100644
index 6031d692..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanConfigServiceImpl.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.ruoyi.aihuman.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import lombok.RequiredArgsConstructor;
-import org.ruoyi.aihuman.domain.AihumanConfig;
-import org.ruoyi.aihuman.domain.bo.AihumanConfigBo;
-import org.ruoyi.aihuman.domain.vo.AihumanConfigVo;
-import org.ruoyi.aihuman.mapper.AihumanConfigMapper;
-import org.ruoyi.aihuman.service.AihumanConfigService;
-import org.ruoyi.common.core.utils.MapstructUtils;
-import org.ruoyi.common.core.utils.StringUtils;
-import org.ruoyi.common.mybatis.core.page.PageQuery;
-import org.ruoyi.common.mybatis.core.page.TableDataInfo;
-import org.springframework.stereotype.Service;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 交互数字人配置Service业务层处理
- *
- * @author ageerle
- * @date Fri Sep 26 22:27:00 GMT+08:00 2025
- */
-@RequiredArgsConstructor
-@Service
-public class AihumanConfigServiceImpl implements AihumanConfigService {
-
- private final AihumanConfigMapper baseMapper;
-
- /**
- * 查询交互数字人配置
- */
- @Override
- public AihumanConfigVo queryById(Integer id) {
- return baseMapper.selectVoById(id);
- }
-
- /**
- * 查询交互数字人配置列表
- */
- @Override
- public TableDataInfo queryPageList(AihumanConfigBo bo, PageQuery pageQuery) {
- LambdaQueryWrapper lqw = buildQueryWrapper(bo);
- Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
- return TableDataInfo.build(result);
- }
-
- /**
- * 查询交互数字人配置列表
- */
- @Override
- public List queryList(AihumanConfigBo bo) {
- LambdaQueryWrapper lqw = buildQueryWrapper(bo);
- return baseMapper.selectVoList(lqw);
- }
-
- private LambdaQueryWrapper buildQueryWrapper(AihumanConfigBo bo) {
- LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
- lqw.eq(StringUtils.isNotBlank(bo.getName()), AihumanConfig::getName, bo.getName());
- lqw.eq(StringUtils.isNotBlank(bo.getModelName()), AihumanConfig::getModelName, bo.getModelName());
- lqw.eq(StringUtils.isNotBlank(bo.getModelPath()), AihumanConfig::getModelPath, bo.getModelPath());
- lqw.eq(StringUtils.isNotBlank(bo.getModelParams()), AihumanConfig::getModelParams, bo.getModelParams());
- lqw.eq(StringUtils.isNotBlank(bo.getAgentParams()), AihumanConfig::getAgentParams, bo.getAgentParams());
- lqw.eq(bo.getCreateTime() != null, AihumanConfig::getCreateTime, bo.getCreateTime());
- lqw.eq(bo.getUpdateTime() != null, AihumanConfig::getUpdateTime, bo.getUpdateTime());
- lqw.eq(bo.getStatus() != null, AihumanConfig::getStatus, bo.getStatus());
- lqw.eq(bo.getPublish() != null, AihumanConfig::getPublish, bo.getPublish());
- return lqw;
- }
-
- /**
- * 新增交互数字人配置
- */
- @Override
- public Boolean insertByBo(AihumanConfigBo bo) {
- AihumanConfig add = MapstructUtils.convert(bo, AihumanConfig.class);
- validEntityBeforeSave(add);
- boolean flag = baseMapper.insert(add) > 0;
- if (flag) {
- bo.setId(add.getId());
- }
- return flag;
- }
-
- /**
- * 修改交互数字人配置
- */
- @Override
- public Boolean updateByBo(AihumanConfigBo bo) {
- AihumanConfig update = MapstructUtils.convert(bo, AihumanConfig.class);
- validEntityBeforeSave(update);
- return baseMapper.updateById(update) > 0;
- }
-
- /**
- * 保存前的数据校验
- */
- private void validEntityBeforeSave(AihumanConfig entity) {
- //TODO 做一些数据校验,如唯一约束
- }
-
- /**
- * 批量删除交互数字人配置
- */
- @Override
- public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
- if (isValid) {
- //TODO 做一些业务上的校验,判断是否需要校验
- }
- return baseMapper.deleteBatchIds(ids) > 0;
- }
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanInfoServiceImpl.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanInfoServiceImpl.java
deleted file mode 100644
index dd5e8a9c..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanInfoServiceImpl.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.ruoyi.aihuman.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import lombok.RequiredArgsConstructor;
-import org.ruoyi.aihuman.domain.AihumanInfo;
-import org.ruoyi.aihuman.domain.vo.AihumanInfoVo;
-import org.ruoyi.aihuman.mapper.AihumanInfoMapper;
-import org.ruoyi.aihuman.service.IAihumanInfoService;
-import org.ruoyi.common.core.utils.StringUtils;
-import org.ruoyi.common.mybatis.core.page.PageQuery;
-import org.ruoyi.common.mybatis.core.page.TableDataInfo;
-import org.springframework.stereotype.Service;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * AI人类交互信息Service业务层处理
- *
- * @author QingYunAI
- */
-@RequiredArgsConstructor
-@Service
-public class AihumanInfoServiceImpl implements IAihumanInfoService {
-
- private final AihumanInfoMapper baseMapper;
-
- /**
- * 查询AI人类交互信息
- */
- @Override
- public AihumanInfoVo queryById(Long id) {
- return baseMapper.selectVoById(id);
- }
-
- /**
- * 查询AI人类交互信息列表
- */
- @Override
- public TableDataInfo queryPageList(AihumanInfo record, PageQuery pageQuery) {
- LambdaQueryWrapper lqw = buildQueryWrapper(record);
- Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
- return TableDataInfo.build(result);
- }
-
- /**
- * 查询AI人类交互信息列表
- */
- @Override
- public List queryList(AihumanInfo record) {
- LambdaQueryWrapper lqw = buildQueryWrapper(record);
- return baseMapper.selectVoList(lqw);
- }
-
- /**
- * 构建查询条件
- */
- private LambdaQueryWrapper buildQueryWrapper(AihumanInfo record) {
- LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
- lqw.eq(record.getId() != null, AihumanInfo::getId, record.getId());
- lqw.like(StringUtils.isNotBlank(record.getName()), AihumanInfo::getName, record.getName());
- lqw.like(StringUtils.isNotBlank(record.getContent()), AihumanInfo::getContent, record.getContent());
- lqw.orderByDesc(AihumanInfo::getCreateTime);
- return lqw;
- }
-
- /**
- * 新增AI人类交互信息
- */
- @Override
- public int insert(AihumanInfo record) {
- return baseMapper.insert(record);
- }
-
- /**
- * 修改AI人类交互信息
- */
- @Override
- public int update(AihumanInfo record) {
- return baseMapper.updateById(record);
- }
-
- /**
- * 批量删除AI人类交互信息
- */
- @Override
- public int deleteWithValidByIds(Collection ids, Boolean isValid) {
- if (isValid) {
- // 如果需要逻辑删除,MyBatis-Plus会自动处理
- // 这里的@TableLogic注解已经在实体类中配置
- }
- return baseMapper.deleteBatchIds(ids);
- }
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanRealConfigServiceImpl.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanRealConfigServiceImpl.java
deleted file mode 100644
index 2b162e1c..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanRealConfigServiceImpl.java
+++ /dev/null
@@ -1,534 +0,0 @@
-package org.ruoyi.aihuman.service.impl;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.sun.jna.Library;
-import com.sun.jna.Native;
-import com.sun.jna.Pointer;
-import com.sun.jna.platform.win32.WinNT;
-import jakarta.annotation.PreDestroy;
-import lombok.RequiredArgsConstructor;
-import org.ruoyi.aihuman.domain.AihumanRealConfig;
-import org.ruoyi.aihuman.domain.bo.AihumanRealConfigBo;
-import org.ruoyi.aihuman.domain.vo.AihumanRealConfigVo;
-import org.ruoyi.aihuman.mapper.AihumanRealConfigMapper;
-import org.ruoyi.aihuman.service.AihumanRealConfigService;
-import org.ruoyi.common.core.utils.MapstructUtils;
-import org.ruoyi.common.core.utils.StringUtils;
-import org.ruoyi.common.mybatis.core.page.PageQuery;
-import org.ruoyi.common.mybatis.core.page.TableDataInfo;
-import org.ruoyi.common.redis.utils.RedisUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Service;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.lang.reflect.Field;
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 真人交互数字人配置Service业务层处理
- *
- * @author ageerle
- * @date Tue Oct 21 11:46:52 GMT+08:00 2025
- */
-@RequiredArgsConstructor
-@Service
-public class AihumanRealConfigServiceImpl implements AihumanRealConfigService {
-
- private static final Logger log = LoggerFactory.getLogger(AihumanRealConfigServiceImpl.class);
- private final AihumanRealConfigMapper baseMapper;
- // 存储当前运行的进程,用于停止操作
- private volatile Process runningProcess = null;
-
- /**
- * 查询真人交互数字人配置
- */
- @Override
- public AihumanRealConfigVo queryById(Integer id) {
- return baseMapper.selectVoById(id);
- }
-
- /**
- * 查询真人交互数字人配置列表
- */
- @Override
- public TableDataInfo queryPageList(AihumanRealConfigBo bo, PageQuery pageQuery) {
- LambdaQueryWrapper lqw = buildQueryWrapper(bo);
- Page result = baseMapper.selectVoPage(pageQuery.build(), lqw);
- return TableDataInfo.build(result);
- }
-
- /**
- * 查询真人交互数字人配置列表
- */
- @Override
- public List queryList(AihumanRealConfigBo bo) {
- LambdaQueryWrapper lqw = buildQueryWrapper(bo);
- return baseMapper.selectVoList(lqw);
- }
-
- private LambdaQueryWrapper buildQueryWrapper(AihumanRealConfigBo bo) {
- LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
- lqw.like(StringUtils.isNotBlank(bo.getName()), AihumanRealConfig::getName, bo.getName());
- lqw.like(StringUtils.isNotBlank(bo.getAvatars()), AihumanRealConfig::getAvatars, bo.getAvatars());
- lqw.like(StringUtils.isNotBlank(bo.getModels()), AihumanRealConfig::getModels, bo.getModels());
- lqw.eq(StringUtils.isNotBlank(bo.getAvatarsParams()), AihumanRealConfig::getAvatarsParams, bo.getAvatarsParams());
- lqw.eq(StringUtils.isNotBlank(bo.getModelsParams()), AihumanRealConfig::getModelsParams, bo.getModelsParams());
- lqw.eq(StringUtils.isNotBlank(bo.getAgentParams()), AihumanRealConfig::getAgentParams, bo.getAgentParams());
- lqw.eq(bo.getCreateTime() != null, AihumanRealConfig::getCreateTime, bo.getCreateTime());
- lqw.eq(bo.getUpdateTime() != null, AihumanRealConfig::getUpdateTime, bo.getUpdateTime());
- lqw.eq(bo.getStatus() != null, AihumanRealConfig::getStatus, bo.getStatus());
- lqw.eq(bo.getPublish() != null, AihumanRealConfig::getPublish, bo.getPublish());
- lqw.eq(StringUtils.isNotBlank(bo.getRunParams()), AihumanRealConfig::getRunParams, bo.getRunParams());
- // 添加runStatus字段的查询条件
- lqw.eq(StringUtils.isNotBlank(bo.getRunStatus()), AihumanRealConfig::getRunStatus, bo.getRunStatus());
- lqw.eq(StringUtils.isNotBlank(bo.getCreateDept()), AihumanRealConfig::getCreateDept, bo.getCreateDept());
- lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), AihumanRealConfig::getCreateBy, bo.getCreateBy());
- lqw.eq(StringUtils.isNotBlank(bo.getUpdateBy()), AihumanRealConfig::getUpdateBy, bo.getUpdateBy());
- return lqw;
- }
-
- /**
- * 新增真人交互数字人配置
- */
- @Override
- public Boolean insertByBo(AihumanRealConfigBo bo) {
- AihumanRealConfig add = MapstructUtils.convert(bo, AihumanRealConfig.class);
- validEntityBeforeSave(add);
- boolean flag = baseMapper.insert(add) > 0;
- if (flag) {
- bo.setId(add.getId());
- }
- return flag;
- }
-
- /**
- * 修改真人交互数字人配置
- */
- @Override
- public Boolean updateByBo(AihumanRealConfigBo bo) {
- AihumanRealConfig update = MapstructUtils.convert(bo, AihumanRealConfig.class);
- validEntityBeforeSave(update);
- return baseMapper.updateById(update) > 0;
- }
-
- /**
- * 保存前的数据校验
- */
- private void validEntityBeforeSave(AihumanRealConfig entity) {
- //TODO 做一些数据校验,如唯一约束
- }
-
- /**
- * 批量删除真人交互数字人配置
- */
- @Override
- public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
- if (isValid) {
- //TODO 做一些业务上的校验,判断是否需要校验
- }
- return baseMapper.deleteBatchIds(ids) > 0;
- }
-
- /**
- * 执行真人交互数字人配置
- * 通过主键获取数据库记录,然后从run_params字段读取命令并执行
- */
- @Override
- public Boolean runByBo(AihumanRealConfigBo bo) {
- try {
- // 1. 通过主键获取数据库记录
- Integer id = bo.getId();
- if (id == null) {
- log.error("执行命令失败:主键ID为空");
- throw new RuntimeException("执行命令失败:主键ID为空");
- }
-
- // 检查是否已经有对应的进程在运行
- String redisKey = "aihuman:process:" + id;
- String existingPid = RedisUtils.getCacheObject(redisKey);
- if (StringUtils.isNotEmpty(existingPid) && isProcessRunning(existingPid)) {
- log.warn("ID为{}的配置已有进程在运行,进程ID: {}", id, existingPid);
- // 刷新run_status状态为运行中
- AihumanRealConfig updateStatus = new AihumanRealConfig();
- updateStatus.setId(id);
- updateStatus.setRunStatus("1"); // 1表示运行中
- baseMapper.updateById(updateStatus);
- return true;
- }
-
- // 查询数据库记录
- AihumanRealConfig config = baseMapper.selectById(id);
- if (config == null) {
- log.error("执行命令失败:未找到ID为{}的配置记录", id);
- throw new RuntimeException("执行命令失败:未找到对应的配置记录");
- }
-
- // 2. 从记录中获取run_params字段
- String runParams = config.getRunParams();
- if (StringUtils.isBlank(runParams)) {
- log.error("执行命令失败:ID为{}的记录中run_params字段为空", id);
- throw new RuntimeException("执行命令失败:run_params字段为空");
- }
-
- // 3. 解析并执行命令
- // 将多行命令合并为一个命令字符串
- String[] commands = runParams.split("\\r?\\n");
- if (commands.length == 0) {
- log.error("执行命令失败:runParams中没有有效的命令");
- throw new RuntimeException("执行命令失败:runParams中没有有效的命令");
- }
-
- // 将所有命令合并到一个命令字符串中,使用&&连接,确保在同一个进程中执行
- StringBuilder mergedCmd = new StringBuilder();
- for (int i = 0; i < commands.length; i++) {
- String command = commands[i].trim();
- if (command.isEmpty()) {
- continue;
- }
-
- if (mergedCmd.length() > 0) {
- mergedCmd.append(" && ");
- }
-
- mergedCmd.append(command);
- }
-
- String cmd = "cmd.exe /c " + mergedCmd.toString();
- log.info("准备执行合并命令:{}", cmd);
-
- // 更新数据库中的运行状态为运行中
- AihumanRealConfig updateStatus = new AihumanRealConfig();
- updateStatus.setId(id);
- updateStatus.setRunStatus("1"); // 1表示运行中
- baseMapper.updateById(updateStatus);
-
- // 使用线程池执行命令并监听输出
- ExecutorService executor = Executors.newSingleThreadExecutor();
- executor.submit(() -> {
- try {
- Process process = Runtime.getRuntime().exec(cmd);
- // 保存进程引用,用于后续停止操作
- runningProcess = process;
-
- // 获取进程ID并保存到Redis
- String pid = getProcessId(process);
- if (!"unknown".equals(pid)) {
- RedisUtils.setCacheObject(redisKey, pid);
- log.info("保存进程ID到Redis:key={}, pid={}", redisKey, pid);
- }
-
- // 读取标准输出
- new Thread(() -> {
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
- String line;
- while ((line = reader.readLine()) != null) {
- log.info("[LiveTalking] {}", line);
- }
- } catch (IOException e) {
- log.error("读取命令输出失败", e);
- }
- }).start();
-
- // 读取debug输出
- new Thread(() -> {
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
- String line;
- while ((line = reader.readLine()) != null) {
- log.debug("[LiveTalking DEBUG] {}", line);
- }
- } catch (IOException e) {
- log.error("读取命令debug输出失败", e);
- }
- }).start();
-
- // 等待进程结束
- int exitCode = process.waitFor();
- log.info("LiveTalking进程结束,退出码: {}", exitCode);
-
- // 进程结束后更新数据库状态为已停止
- AihumanRealConfig endStatus = new AihumanRealConfig();
- endStatus.setId(id);
- endStatus.setRunStatus("0"); // 0表示已停止
- baseMapper.updateById(endStatus);
-
- // 进程结束后从Redis中删除进程ID
- RedisUtils.deleteObject(redisKey);
- log.info("从Redis中删除进程ID:key={}", redisKey);
-
- // 进程结束后清空引用
- runningProcess = null;
- } catch (Exception e) {
- log.error("执行命令失败", e);
- // 发生异常时更新数据库状态为失败
- try {
- AihumanRealConfig errorStatus = new AihumanRealConfig();
- errorStatus.setId(id);
- errorStatus.setRunStatus("2"); // 2表示启动失败
- baseMapper.updateById(errorStatus);
- } catch (Exception ex) {
- log.error("更新状态失败", ex);
- }
- // 发生异常时从Redis中删除进程ID
- RedisUtils.deleteObject(redisKey);
- // 发生异常时清空引用
- runningProcess = null;
- }
- });
-
- executor.shutdown();
- return true;
- } catch (Exception e) {
- log.error("执行命令过程中发生异常", e);
- return false;
- }
- }
-
- /**
- * 检查进程是否正在运行
- *
- * @param pid 进程ID
- * @return 是否正在运行
- */
- private boolean isProcessRunning(String pid) {
- if (StringUtils.isEmpty(pid) || "unknown".equals(pid)) {
- return false;
- }
-
- try {
- boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");
- ProcessBuilder processBuilder;
-
- if (isWindows) {
- processBuilder = new ProcessBuilder("tasklist", "/FI", "PID eq " + pid);
- } else {
- processBuilder = new ProcessBuilder("ps", "-p", pid);
- }
-
- Process process = processBuilder.start();
- int exitCode = process.waitFor();
-
- // 在Windows上,tasklist命令如果找不到进程,退出码也是0,但输出中不会包含PID
- if (isWindows) {
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
- String line;
- while ((line = reader.readLine()) != null) {
- if (line.contains(pid)) {
- return true;
- }
- }
- }
- return false;
- } else {
- // 在Linux/Mac上,ps命令如果找不到进程,退出码不为0
- return exitCode == 0;
- }
- } catch (Exception e) {
- log.error("检查进程是否运行失败, pid={}", pid, e);
- return false;
- }
- }
-
- /**
- * 停止正在运行的真人交互数字人配置任务
- */
- @Override
- public Boolean stopByBo(AihumanRealConfigBo bo) {
- try {
- Integer id = bo.getId();
- String redisKey = "aihuman:process:" + id;
-
- // 首先检查Redis中是否有对应的进程ID
- String pid = RedisUtils.getCacheObject(redisKey);
- if (StringUtils.isNotEmpty(pid)) {
- // 如果Redis中有进程ID,先尝试通过进程ID停止进程
- try {
- // 根据操作系统类型,使用不同的命令终止进程树
- if (System.getProperty("os.name").toLowerCase().contains("win")) {
- // Windows系统使用taskkill命令终止进程树
- log.info("通过Redis中的PID停止进程: taskkill /F /T /PID {}", pid);
- Process killProcess = Runtime.getRuntime().exec("taskkill /F /T /PID " + pid);
- // 等待kill命令执行完成
- killProcess.waitFor(5, TimeUnit.SECONDS);
- } else {
- // Linux/Mac系统使用pkill命令终止进程树
- Runtime.getRuntime().exec("pkill -P " + pid);
- }
- } catch (Exception e) {
- log.error("通过Redis中的PID停止进程失败", e);
- }
- }
-
- // 然后检查本地runningProcess引用
- if (runningProcess != null && runningProcess.isAlive()) {
- log.info("正在停止LiveTalking进程...");
- // 强制销毁进程树,确保完全停止
- destroyProcessTree(runningProcess);
-
- // 更新数据库中的运行状态为已停止
- AihumanRealConfig updateStatus = new AihumanRealConfig();
- updateStatus.setId(id);
- updateStatus.setRunStatus("0"); // 0表示已停止
- baseMapper.updateById(updateStatus);
-
- runningProcess = null;
- log.info("LiveTalking进程已停止");
- } else {
- log.warn("没有正在运行的LiveTalking进程");
- // 确保数据库中的状态也是已停止
- AihumanRealConfig updateStatus = new AihumanRealConfig();
- updateStatus.setId(id);
- updateStatus.setRunStatus("0"); // 0表示已停止
- baseMapper.updateById(updateStatus);
- }
-
- // 无论如何都从Redis中删除进程ID
- RedisUtils.deleteObject(redisKey);
- log.info("从Redis中删除进程ID:key={}", redisKey);
-
- return true;
- } catch (Exception e) {
- log.error("停止进程时发生异常", e);
- // 发生异常时也尝试从Redis中删除进程ID
- try {
- RedisUtils.deleteObject("aihuman:process:" + bo.getId());
- } catch (Exception ex) {
- log.error("从Redis中删除进程ID失败", ex);
- }
- return false;
- }
- }
-
- /**
- * 销毁进程及其子进程(进程树)
- *
- * @param process 要销毁的进程
- */
- private void destroyProcessTree(Process process) {
- try {
- if (process.isAlive()) {
- // 获取进程ID
- String pid = getProcessId(process);
- log.info("获取到进程ID: {}", pid);
-
- // 根据操作系统类型,使用不同的命令终止进程树
- if (System.getProperty("os.name").toLowerCase().contains("win")) {
- // Windows系统使用taskkill命令终止进程树
- log.info("执行taskkill命令终止进程树: taskkill /F /T /PID {}", pid);
- Process killProcess = Runtime.getRuntime().exec("taskkill /F /T /PID " + pid);
- // 等待kill命令执行完成
- killProcess.waitFor(5, TimeUnit.SECONDS);
- } else {
- // Linux/Mac系统使用pkill命令终止进程树
- Runtime.getRuntime().exec("pkill -P " + pid);
- process.destroy();
- }
- }
- } catch (Exception e) {
- log.error("销毁进程树时发生异常", e);
- // 如果出现异常,尝试使用普通销毁方法
- process.destroy();
- try {
- // 强制销毁
- if (process.isAlive()) {
- process.destroyForcibly();
- }
- } catch (Exception ex) {
- log.error("强制销毁进程失败", ex);
- }
- }
- }
-
- /**
- * 获取进程ID
- *
- * @param process 进程对象
- * @return 进程ID
- */
- private String getProcessId(Process process) {
- try {
- // 不同JVM实现可能有所不同,这里尝试通过反射获取
- if (process.getClass().getName().equals("java.lang.Win32Process") ||
- process.getClass().getName().equals("java.lang.ProcessImpl")) {
- Field f = process.getClass().getDeclaredField("handle");
- f.setAccessible(true);
- long handl = f.getLong(process);
- Kernel32 kernel = Kernel32.INSTANCE;
- WinNT.HANDLE handle = new WinNT.HANDLE();
- handle.setPointer(Pointer.createConstant(handl));
- return String.valueOf(kernel.GetProcessId(handle));
- } else if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
- Field f = process.getClass().getDeclaredField("pid");
- f.setAccessible(true);
- return String.valueOf(f.getInt(process));
- }
- } catch (Exception e) {
- log.error("获取进程ID失败", e);
- }
-
- // 如果反射获取失败,尝试通过wmic命令获取
- try {
- // 对于Windows系统,可以尝试使用wmic命令获取进程ID
- if (System.getProperty("os.name").toLowerCase().contains("win")) {
- ProcessHandle.Info info = process.toHandle().info();
- return String.valueOf(process.toHandle().pid());
- }
- } catch (Exception e) {
- log.error("通过ProcessHandle获取进程ID失败", e);
- }
-
- return "unknown";
- }
-
- @PreDestroy
- public void onDestroy() {
- if (runningProcess != null && runningProcess.isAlive()) {
- try {
- log.info("应用关闭,正在停止数字人进程");
- destroyProcessTree(runningProcess);
-
- // 查找所有运行状态为运行中的配置,并更新为已停止
- LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
- lqw.eq(AihumanRealConfig::getRunStatus, "1");
- List runningConfigs = baseMapper.selectList(lqw);
- for (AihumanRealConfig config : runningConfigs) {
- config.setRunStatus("0");
- baseMapper.updateById(config);
-
- // 从Redis中删除对应的进程ID记录
- String redisKey = "aihuman:process:" + config.getId();
- RedisUtils.deleteObject(redisKey);
- log.info("应用关闭,从Redis中删除进程ID:key={}", redisKey);
- }
- } catch (Exception e) {
- log.error("停止数字人进程失败", e);
- // 即使发生异常,也尝试清理Redis中的进程ID记录
- try {
- LambdaQueryWrapper lqw = Wrappers.lambdaQuery();
- lqw.eq(AihumanRealConfig::getRunStatus, "1");
- List runningConfigs = baseMapper.selectList(lqw);
- for (AihumanRealConfig config : runningConfigs) {
- RedisUtils.deleteObject("aihuman:process:" + config.getId());
- }
- } catch (Exception ex) {
- log.error("清理Redis中的进程ID记录失败", ex);
- }
- }
- }
- }
-
- // JNA接口定义,用于Windows系统获取进程ID
- interface Kernel32 extends Library {
- Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
-
- int GetProcessId(WinNT.HANDLE hProcess);
- }
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanVolcengineServiceImpl.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanVolcengineServiceImpl.java
deleted file mode 100644
index aa11aabd..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/service/impl/AihumanVolcengineServiceImpl.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package org.ruoyi.aihuman.service.impl;
-
-public class AihumanVolcengineServiceImpl {
-}
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/volcengine/Bidirection.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/volcengine/Bidirection.java
deleted file mode 100644
index dc8ef8c9..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/volcengine/Bidirection.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package org.ruoyi.aihuman.volcengine;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import lombok.extern.slf4j.Slf4j;
-import org.ruoyi.aihuman.protocol.EventType;
-import org.ruoyi.aihuman.protocol.Message;
-import org.ruoyi.aihuman.protocol.MsgType;
-import org.ruoyi.aihuman.protocol.SpeechWebSocketClient;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.net.URI;
-import java.nio.file.Files;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-@Slf4j
-public class Bidirection {
- private static final String ENDPOINT = "wss://openspeech.bytedance.com/api/v3/tts/bidirection";
- private static final ObjectMapper objectMapper = new ObjectMapper();
-
- /**
- * Get resource ID based on voice type
- *
- * @param voice Voice type string
- * @return Corresponding resource ID
- */
- public static String voiceToResourceId(String voice) {
- // Map different voice types to resource IDs based on actual needs
- if (voice.startsWith("S_")) {
- return "volc.megatts.default";
- }
- return "volc.service_type.10029";
- }
-
- public static void main(String[] args) throws Exception {
- // Configure parameters
- String appId = System.getProperty("appId", "1055299334");
- String accessToken = System.getProperty("accessToken", "fOHuq4R4dirMYiOruCU3Ek9q75zV0KVW");
- String resourceId = System.getProperty("resourceId", "seed-tts-2.0");
- String voice = System.getProperty("voice", "zh_female_vv_uranus_bigtts");
- String text = System.getProperty("text", "你好呀!我是AI合成的语音,很高兴认识你。");
- String encoding = System.getProperty("encoding", "mp3");
-
- if (appId.isEmpty() || accessToken.isEmpty()) {
- throw new IllegalArgumentException("Please set appId and accessToken system properties");
- }
-
- // Set request headers
- Map headers = Map.of(
- "X-Api-App-Key", appId,
- "X-Api-Access-Key", accessToken,
- "X-Api-Resource-Id", resourceId.isEmpty() ? voiceToResourceId(voice) : resourceId,
- "X-Api-Connect-Id", UUID.randomUUID().toString());
-
- // Create WebSocket client
- SpeechWebSocketClient client = new SpeechWebSocketClient(new URI(ENDPOINT), headers);
- try {
- client.connectBlocking();
- Map request = Map.of(
- "user", Map.of("uid", UUID.randomUUID().toString()),
- "namespace", "BidirectionalTTS",
- "req_params", Map.of(
- "speaker", voice,
- "audio_params", Map.of(
- "format", encoding,
- "sample_rate", 24000,
- "enable_timestamp", true),
- // additions requires a JSON string
- "additions", objectMapper.writeValueAsString(Map.of(
- "disable_markdown_filter", false))));
-
- // Start connection
- client.sendStartConnection();
- // Wait for connection started
- client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.CONNECTION_STARTED);
-
- // Process each sentence
- String[] sentences = text.split("。");
- boolean audioReceived = false;
- for (int i = 0; i < sentences.length; i++) {
- if (sentences[i].trim().isEmpty()) {
- continue;
- }
-
- String sessionId = UUID.randomUUID().toString();
- ByteArrayOutputStream audioStream = new ByteArrayOutputStream();
-
- // Start session
- Map startReq = Map.of(
- "user", request.get("user"),
- "namespace", request.get("namespace"),
- "req_params", request.get("req_params"),
- "event", EventType.START_SESSION.getValue());
- client.sendStartSession(objectMapper.writeValueAsBytes(startReq), sessionId);
- // Wait for session started
- client.waitForMessage(MsgType.FULL_SERVER_RESPONSE, EventType.SESSION_STARTED);
-
- // Send text
- for (char c : sentences[i].toCharArray()) {
- // Create new req_params with text
- @SuppressWarnings("unchecked")
- Map currentReqParams = new HashMap<>(
- (Map) request.get("req_params"));
- currentReqParams.put("text", String.valueOf(c));
-
- // Create current request
- Map currentRequest = Map.of(
- "user", request.get("user"),
- "namespace", request.get("namespace"),
- "req_params", currentReqParams,
- "event", EventType.TASK_REQUEST.getValue());
-
- client.sendTaskRequest(objectMapper.writeValueAsBytes(currentRequest), sessionId);
- }
-
- // End session
- client.sendFinishSession(sessionId);
-
- // Receive response
- while (true) {
- Message msg = client.receiveMessage();
- switch (msg.getType()) {
- case FULL_SERVER_RESPONSE:
- break;
- case AUDIO_ONLY_SERVER:
- if (!audioReceived && audioStream.size() > 0) {
- audioReceived = true;
- }
- if (msg.getPayload() != null) {
- audioStream.write(msg.getPayload());
- }
- break;
- default:
- throw new RuntimeException("Unexpected message: " + msg);
- }
- if (msg.getEvent() == EventType.SESSION_FINISHED) {
- break;
- }
- }
-
- if (audioStream.size() > 0) {
- String fileName = String.format("%s_session_%d.%s", voice, i, encoding);
- Files.write(new File(fileName).toPath(), audioStream.toByteArray());
- log.info("Audio saved to file: {}", fileName);
- }
- }
-
- if (!audioReceived) {
- throw new RuntimeException("No audio data received");
- }
-
- // End connection
- client.sendFinishConnection();
- } finally {
- client.closeBlocking();
- }
- }
-}
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/AihumanInfoMapper.xml b/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/AihumanInfoMapper.xml
deleted file mode 100644
index 22bd47aa..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/AihumanInfoMapper.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanConfigMapper.xml b/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanConfigMapper.xml
deleted file mode 100644
index 0cbe9dcb..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanConfigMapper.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanRealConfigMapper.xml b/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanRealConfigMapper.xml
deleted file mode 100644
index 8c7011ca..00000000
--- a/ruoyi-modules/ruoyi-aihuman/src/main/resources/mapper/aihuman/AihumanRealConfigMapper.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-