diff --git a/ruoyi-modules/ruoyi-aihuman/pom.xml b/ruoyi-modules/ruoyi-aihuman/pom.xml index b86f7de5..65327e0e 100644 --- a/ruoyi-modules/ruoyi-aihuman/pom.xml +++ b/ruoyi-modules/ruoyi-aihuman/pom.xml @@ -19,6 +19,7 @@ 3.2.1 5.13.0 + 1.5.5 @@ -84,5 +85,11 @@ ${jna.version} + + org.java-websocket + Java-WebSocket + ${java-websocket.version} + + \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/config/WebConfig.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/config/WebConfig.java index 5efe553b..5ccaf134 100644 --- a/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/config/WebConfig.java +++ b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/config/WebConfig.java @@ -1,4 +1,16 @@ package org.ruoyi.aihuman.config; -public class WebConfig { -} +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // 映射/voice/**路径到classpath:/voice/目录 + registry.addResourceHandler("/voice/**") + .addResourceLocations("classpath:/voice/") + .setCachePeriod(3600); + } +} \ No newline at end of file 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 index 601e8a6e..c396ba0a 100644 --- 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 @@ -1,4 +1,508 @@ package org.ruoyi.aihuman.controller; +import cn.dev33.satoken.annotation.SaIgnore; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.core.io.ResourceLoader; +import org.springframework.beans.factory.annotation.Autowired; +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 com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.HashMap; +import java.util.UUID; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +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.util.concurrent.TimeUnit; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 火山引擎相关接口 + * + * @author ruoyi + */ +// 临时免登录 +@SaIgnore + +@Validated +@RequiredArgsConstructor +@Slf4j +@RestController +@RequestMapping("/aihuman/volcengine") public class AihumanVolcengineController { + + @Autowired + private ResourceLoader resourceLoader; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + private static final Logger logger = LoggerFactory.getLogger(AihumanVolcengineController.class); + + + @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/VoiceRequest.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/domain/VoiceRequest.java index 4be027e6..a0ce0c65 100644 --- 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 @@ -1,4 +1,21 @@ 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/protocol/CompressionBits.java b/ruoyi-modules/ruoyi-aihuman/src/main/java/org/ruoyi/aihuman/protocol/CompressionBits.java index 55442fef..78794aa4 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.Getter; 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 index 5d043dde..ece69af3 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.Getter; 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 index 86daf375..6c09a20d 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.Getter; 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 index bc44fc73..d3605edc 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.Data; import lombok.extern.slf4j.Slf4j; 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 index 9d782b36..965f40e8 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.Getter; 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 index d155a562..393a24dc 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.Getter; 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 index c822ecc8..01e8f102 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.Getter; 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 index 63c20366..c41e57b3 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.extern.slf4j.Slf4j; import org.java_websocket.client.WebSocketClient; 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 index 1e3542fc..6f4a8174 100644 --- 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 @@ -1,4 +1,4 @@ -package com.speech.protocol; +package org.ruoyi.aihuman.protocol; import lombok.Getter; 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 index 749b5bf7..f4dd19e3 100644 --- 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 @@ -1,10 +1,10 @@ -package com.speech.volcengine; +package org.ruoyi.aihuman.volcengine; import com.fasterxml.jackson.databind.ObjectMapper; -import com.speech.protocol.EventType; -import com.speech.protocol.Message; -import com.speech.protocol.MsgType; -import com.speech.protocol.SpeechWebSocketClient; +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 lombok.extern.slf4j.Slf4j; import java.io.ByteArrayOutputStream; @@ -40,7 +40,7 @@ public class Bidirection { 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", "你好呀!如果你有关于老婆相关的问题,比如怎么让她开心、怎么照顾她等,都可以跟我说哦,我会根据【马斯克·陈】提供的关爱老婆百事通里的信息给你分析和建议哒。"); + String text = System.getProperty("text", "你好呀!我是AI合成的语音,很高兴认识你。"); String encoding = System.getProperty("encoding", "mp3"); if (appId.isEmpty() || accessToken.isEmpty()) { diff --git a/ruoyi-modules/ruoyi-generator/src/main/resources/generator.yml b/ruoyi-modules/ruoyi-generator/src/main/resources/generator.yml new file mode 100644 index 00000000..7f5955fb --- /dev/null +++ b/ruoyi-modules/ruoyi-generator/src/main/resources/generator.yml @@ -0,0 +1,10 @@ +# 代码生成 +gen: + # 作者 + author: ageerle + # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool + packageName: org.ruoyi.aihuman + # 自动去除表前缀,默认是false + autoRemovePre: false + # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) + tablePrefix: aihuman_