feat(读书听书准备): 读书听书准备
This commit is contained in:
parent
2423e27b34
commit
17c571c61d
6
pom.xml
6
pom.xml
|
@ -323,6 +323,12 @@
|
|||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -5,9 +5,12 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
@Slf4j
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.guwan.backend.mapper")
|
||||
@EnableFeignClients
|
||||
public class BackendApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
package com.guwan.backend.client;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
@FeignClient(name = "ttsService", url = "http://127.0.0.1:8534")
|
||||
public interface SimpleTTSClient {
|
||||
|
||||
|
||||
|
||||
|
||||
@PostMapping(value = "/v1/audio/speech")
|
||||
byte[] saveAudio(String jsonInputString);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//public class SimpleAudioSaver {
|
||||
//
|
||||
// public static void main(String[] args) {
|
||||
// String urlString = "http://localhost:8534/v1/audio/speech"; // API URL
|
||||
// String jsonInputString = "{\"input\": \"想听个啥123\", \"voice\": \"zh-CN-XiaoxiaoNeural\", \"style\": \"\", \"rate\": 0, \"pitch\": 0}";
|
||||
//
|
||||
// saveAudio(urlString, jsonInputString);
|
||||
// }
|
||||
//
|
||||
// public static void saveAudio(String urlString, String jsonInputString) {
|
||||
// try {
|
||||
// // 创建 URL 对象
|
||||
// URL url = new URL(urlString);
|
||||
// // 打开连接
|
||||
// HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
// // 设置请求方式为 POST
|
||||
// connection.setRequestMethod("POST");
|
||||
// connection.setDoOutput(true);
|
||||
// connection.setRequestProperty("Content-Type", "application/json");
|
||||
// connection.setRequestProperty("Accept", "audio/mpeg");
|
||||
//
|
||||
// // 发送请求体
|
||||
// connection.getOutputStream().write(jsonInputString.getBytes("UTF-8"));
|
||||
//
|
||||
// // 处理响应
|
||||
// if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
// // 获取输入流
|
||||
// InputStream inputStream = new BufferedInputStream(connection.getInputStream());
|
||||
// // 保存文件
|
||||
// try (FileOutputStream outputStream = new FileOutputStream("output.mp3")) {
|
||||
// byte[] buffer = new byte[1024];
|
||||
// int bytesRead;
|
||||
// while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
// outputStream.write(buffer, 0, bytesRead);
|
||||
// }
|
||||
// }
|
||||
// System.out.println("Audio saved as output.mp3");
|
||||
// } else {
|
||||
// System.err.println("Failed to get audio. Response code: " + connection.getResponseCode());
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
//}
|
|
@ -0,0 +1,19 @@
|
|||
package com.guwan.backend.client;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 语音转文本
|
||||
*/
|
||||
@FeignClient(name = "voiceService", url = "http://127.0.0.1:8532")
|
||||
public interface VoiceServiceClient {
|
||||
|
||||
@PostMapping(value = "/v1/audio/transcriptions", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
JSONObject voiceToText(@RequestPart("file") MultipartFile file,
|
||||
@RequestPart("model") String model);
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
package com.guwan.backend.controller;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.guwan.backend.annotation.OperationLog;
|
||||
import com.guwan.backend.client.SimpleTTSClient;
|
||||
import com.guwan.backend.client.VoiceServiceClient;
|
||||
import com.guwan.backend.common.Result;
|
||||
import com.guwan.backend.pojo.entity.BookContent;
|
||||
import com.guwan.backend.mongodb.EveryReadDetailOfMongodb;
|
||||
|
@ -34,6 +37,11 @@ public class CommonController {
|
|||
|
||||
private final MinioUtil minioUtil;
|
||||
|
||||
private final VoiceServiceClient voiceServiceClient;
|
||||
private final SimpleTTSClient simpleTTSClient;
|
||||
|
||||
|
||||
|
||||
|
||||
private final BookContentService bookContentService;
|
||||
|
||||
|
@ -199,9 +207,11 @@ public class CommonController {
|
|||
@GetMapping("/getBookCommentByPath")
|
||||
public ResponseEntity<Map<String, Object>> getBookCommentByPath(@RequestParam("id") Long id) {
|
||||
// 从数据库中获取评论内容
|
||||
String comments = bookContentService.getById(id).getSectionContent();
|
||||
//String comments = bookContentService.getById(id).getSectionContent();
|
||||
|
||||
BookContent byId = bookContentService.getById(id);
|
||||
BookContent byId = bookContentService.lambdaQuery()
|
||||
.eq(BookContent::getBookName, "大爱仙尊")
|
||||
.eq(BookContent::getSectionId, id).one();
|
||||
|
||||
// 构造返回数据
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
|
@ -252,4 +262,47 @@ public class CommonController {
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* model 默认值 /model/faster-whisper-small/
|
||||
*/
|
||||
@PostMapping("/convertVoiceToText")
|
||||
public Result convertVoiceToText(MultipartFile file, String model) {
|
||||
|
||||
if (model == null){
|
||||
model = "/model/faster-whisper-small/";
|
||||
}
|
||||
|
||||
return Result.success(voiceServiceClient.voiceToText(file, model));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/simpleTTS")
|
||||
public Result simpleTTS(String input, String voiceModel) {
|
||||
|
||||
|
||||
if (voiceModel == null) {
|
||||
voiceModel = "zh-CN-XiaoxiaoNeural";
|
||||
}
|
||||
|
||||
// 使用 JSONObject 构造JSON
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("input", input);
|
||||
jsonObject.put("voice", voiceModel);
|
||||
|
||||
String jsonInputString = jsonObject.toString();
|
||||
System.out.println(jsonInputString);
|
||||
|
||||
|
||||
// jsonInputString = "{\"input\": \"想听个啥123\", \"voice\": \"zh-CN-XiaoxiaoNeural\", \"style\": \"\", \"rate\": 0, \"pitch\": 0}";
|
||||
|
||||
|
||||
String url = minioUtil.getUrl(minioUtil.getFileUrl("temp",
|
||||
minioUtil.uploadByteArray(
|
||||
simpleTTSClient.saveAudio(jsonInputString), "mp3")));
|
||||
|
||||
|
||||
return Result.success(url);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
package com.guwan.backend.pojo.enums;
|
||||
|
||||
public enum VoiceModels {
|
||||
|
||||
ZHHKHIUGAAINEURAL,
|
||||
ZHHKHIUMAANNEURAL,
|
||||
ZHHKWANLUNGNEURAL,
|
||||
ZHCNXIAOXIAONEURAL,
|
||||
/**
|
||||
* 女 晓伊
|
||||
*/
|
||||
ZHCNXIAOYINEURAL
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.guwan.backend.util;
|
||||
|
||||
import io.minio.*;
|
||||
import io.minio.errors.MinioException;
|
||||
import io.minio.http.Method;
|
||||
import io.minio.messages.DeleteError;
|
||||
import io.minio.messages.DeleteObject;
|
||||
|
@ -12,7 +13,10 @@ import org.springframework.stereotype.Component;
|
|||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
@ -160,6 +164,11 @@ public class MinioUtil {
|
|||
return url.substring(0, url.indexOf("?"));
|
||||
}
|
||||
|
||||
public String getUrlByName(String name) {
|
||||
//TODO 加个全局
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成文件名
|
||||
|
@ -185,6 +194,37 @@ public class MinioUtil {
|
|||
|
||||
|
||||
|
||||
public String uploadByteArray(byte[] data, String suffix) {
|
||||
|
||||
String uuid = UUIDUtil.uuid();
|
||||
|
||||
String fileName = uuid + "." +suffix;
|
||||
|
||||
try {
|
||||
// 使用 byte[] 创建 InputStream
|
||||
InputStream byteArrayInputStream = new ByteArrayInputStream(data);
|
||||
|
||||
|
||||
|
||||
// 上传文件
|
||||
minioClient.putObject(
|
||||
PutObjectArgs.builder()
|
||||
.bucket("temp")
|
||||
.object(fileName) // 存储在 MinIO 中的对象名称
|
||||
.stream(byteArrayInputStream, data.length, -1)
|
||||
.contentType("application/octet-stream") // 根据数据类型设置
|
||||
.build()
|
||||
);
|
||||
log.info("File uploaded successfully to MinIO!");
|
||||
return fileName;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 初始化时创建视频桶
|
||||
// @PostConstruct
|
||||
// public void init() {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package com.guwan.backend.util;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class UUIDUtil {
|
||||
public static String uuid(){
|
||||
return UUID.randomUUID().toString().replace("-","");
|
||||
}
|
||||
public static void main(String args[]){
|
||||
String uuid = UUIDUtil.uuid();
|
||||
System.out.println(uuid);
|
||||
}
|
||||
}
|
|
@ -111,7 +111,7 @@
|
|||
// 先清空内容,显示加载状态
|
||||
document.getElementById("comments").innerHTML = "Loading...";
|
||||
|
||||
const response = await fetch(`/common/getBookCommentByPath?id=${bookId}`);
|
||||
const response = await fetch(`/api/common/getBookCommentByPath?id=${bookId}`);
|
||||
const data = await response.json();
|
||||
if (data && data.data) {
|
||||
const volumeTitle = data.data.volume || 'Unknown Volume';
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.guwan.backend;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class CommaToNewline {
|
||||
|
||||
public static void replaceCommasWithNewlines(String filePath) {
|
||||
try {
|
||||
// 读取文件内容到字符串
|
||||
String content = new String(Files.readAllBytes(Paths.get(filePath)));
|
||||
|
||||
// 将逗号替换为换行符
|
||||
content = content.replace(",", "\n");
|
||||
|
||||
// 将修改后的内容写回文件
|
||||
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
|
||||
writer.write(content);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 假设有一个文件路径
|
||||
String filePath = "D:\\00_桌面\\123.txt";
|
||||
replaceCommasWithNewlines(filePath);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue