xf 维语转语音
This commit is contained in:
@@ -3,6 +3,7 @@ package com.newyetai.ai.resume.controller;
|
||||
import com.newyetai.ai.resume.dto.AiResumeReqDTO;
|
||||
import com.newyetai.ai.resume.service.AiResumeService;
|
||||
import com.newyetai.common.AlitaResult;
|
||||
import com.newyetai.sdk.xf.dto.TtsReqDTO;
|
||||
import com.newyetai.sdk.xf.util.XfUtils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -48,8 +49,8 @@ public class AiResumeController {
|
||||
|
||||
@PostMapping("/tts")
|
||||
@ApiOperation("ai简历-语音合成")
|
||||
public AlitaResult<String> tts(@RequestParam("text") String text) {
|
||||
return AlitaResult.success(XfUtils.tts(text));
|
||||
public AlitaResult<String> tts(@RequestBody @Validated TtsReqDTO ttsReq) {
|
||||
return AlitaResult.success(XfUtils.tts(ttsReq));
|
||||
}
|
||||
|
||||
@PostMapping("/analyseResume")
|
||||
|
||||
@@ -16,6 +16,10 @@ public class RtasrReqDTO implements Serializable {
|
||||
|
||||
@NotBlank(message = "语音文件不能为空")
|
||||
private String fileCode;
|
||||
/**
|
||||
* 中文:cn
|
||||
* 维语:cn_uyghur
|
||||
*/
|
||||
@Default
|
||||
private String from = "cn_uyghur";
|
||||
|
||||
|
||||
40
src/main/java/com/newyetai/sdk/xf/dto/TtsReqDTO.java
Normal file
40
src/main/java/com/newyetai/sdk/xf/dto/TtsReqDTO.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package com.newyetai.sdk.xf.dto;
|
||||
|
||||
import com.newyetai.sdk.xf.util.WebTtsWS;
|
||||
import java.io.Serializable;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Builder.Default;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class TtsReqDTO implements Serializable {
|
||||
|
||||
@NotBlank(message = "合成文本不能为空")
|
||||
private String text;
|
||||
|
||||
/**
|
||||
* 发音人
|
||||
* x4_yezi(中文)/x2_ugsp_dilare(维语)
|
||||
*/
|
||||
@Default
|
||||
private String vcn = "xiaoyan";
|
||||
|
||||
/**
|
||||
* 文本编码格式
|
||||
* GB2312
|
||||
* GBK
|
||||
* BIG5
|
||||
* UNICODE(小语种)
|
||||
* GB18030
|
||||
* UTF8(小语种推荐使用UTF8编码)
|
||||
* */
|
||||
@Default
|
||||
private String tte = WebTtsWS.TTL_UTF8;
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -22,6 +23,7 @@ import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream;
|
||||
import com.google.gson.Gson;
|
||||
import com.newyetai.common.AlitaResult;
|
||||
import com.newyetai.sdk.xf.config.XfProperties;
|
||||
import com.newyetai.sdk.xf.dto.TtsReqDTO;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.HttpUrl;
|
||||
@@ -44,6 +46,9 @@ public class WebTtsWS extends WebSocketListener {
|
||||
public static final int StatusFirstFrame = 0;
|
||||
public static final int StatusContinueFrame = 1;
|
||||
public static final int StatusLastFrame = 2;
|
||||
public static final String TTL_UTF8 = "UTF8";
|
||||
public static final String TTL_UNICODE = "UNICODE";
|
||||
|
||||
public static final Gson json = new Gson();
|
||||
// mp3格式
|
||||
private String encoding = "lame";
|
||||
@@ -52,14 +57,16 @@ public class WebTtsWS extends WebSocketListener {
|
||||
private String text;
|
||||
private String appId;
|
||||
OutputStream outputStream;
|
||||
// 合成文本编码格式
|
||||
public static final String TTE = "UTF8"; // 小语种必须使用UNICODE编码作为值
|
||||
// 小语种必须使用UNICODE编码作为值
|
||||
private String tte;
|
||||
// 发音人参数。到控制台-我的应用-语音合成-添加试用或购买发音人,添加后即显示该发音人参数值,若试用未添加的发音人会报错11200
|
||||
public static final String VCN = "xiaoyan";
|
||||
private String vcn;
|
||||
|
||||
WebTtsWS(String text, String appId, OutputStream outputStream){
|
||||
WebTtsWS(String text, String appId, String vcn, String tte, OutputStream outputStream){
|
||||
this.text = text;
|
||||
this.appId = appId;
|
||||
this.vcn = vcn;
|
||||
this.tte = tte;
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
@@ -73,6 +80,16 @@ public class WebTtsWS extends WebSocketListener {
|
||||
super.onOpen(webSocket, response);
|
||||
log.info("ws建立连接成功...");
|
||||
String requestJson;//请求参数json串
|
||||
String encodedText ;
|
||||
if (WebTtsWS.TTL_UNICODE.equals(tte)) {
|
||||
try {
|
||||
encodedText = Base64.getEncoder().encodeToString(text.getBytes("UTF-16LE"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
encodedText = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
requestJson = "{\n" +
|
||||
" \"common\": {\n" +
|
||||
" \"app_id\": \"" + appId + "\"\n" +
|
||||
@@ -80,21 +97,19 @@ public class WebTtsWS extends WebSocketListener {
|
||||
" \"business\": {\n" +
|
||||
" \"aue\": \"lame\",\n" +
|
||||
" \"sfl\": 1,\n" +
|
||||
" \"tte\": \"" + TTE + "\",\n" +
|
||||
" \"tte\": \"" + tte + "\",\n" +
|
||||
" \"ent\": \"intp65\",\n" +
|
||||
" \"vcn\": \"" + VCN + "\",\n" +
|
||||
" \"vcn\": \"" + vcn + "\",\n" +
|
||||
" \"pitch\": 50,\n" +
|
||||
" \"speed\": 50\n" +
|
||||
" },\n" +
|
||||
" \"data\": {\n" +
|
||||
" \"status\": 2,\n" +
|
||||
" \"text\": \""
|
||||
+ Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8)) + "\"\n" +
|
||||
//" \"text\": \"" + Base64.getEncoder().encodeToString(TEXT.getBytes("UTF-16LE")) + "\"\n" +
|
||||
+ encodedText + "\"\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
webSocket.send(requestJson);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,7 +160,7 @@ public class WebTtsWS extends WebSocketListener {
|
||||
}
|
||||
}
|
||||
|
||||
public static AlitaResult<Void> execute(String text, XfProperties xfProperties, OutputStream outputStream) {
|
||||
public static AlitaResult<Void> execute(TtsReqDTO ttsReq, XfProperties xfProperties, OutputStream outputStream) {
|
||||
try {
|
||||
// 构建鉴权url
|
||||
String authUrl = getAuthUrl(xfProperties.getTtsHostUrl(), xfProperties.getApiKey(),
|
||||
@@ -154,7 +169,7 @@ public class WebTtsWS extends WebSocketListener {
|
||||
//将url中的 schema http://和https://分别替换为ws:// 和 wss://
|
||||
String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
WebTtsWS webIATWS = new WebTtsWS(text, xfProperties.getAppId(), outputStream);
|
||||
WebTtsWS webIATWS = new WebTtsWS(ttsReq.getText(), xfProperties.getAppId(), ttsReq.getVcn(), ttsReq.getTte(), outputStream);
|
||||
WebSocket webSocket = client.newWebSocket(request, webIATWS);
|
||||
while (webIATWS.result == null) {
|
||||
// 未拿到结果等待
|
||||
@@ -165,7 +180,6 @@ public class WebTtsWS extends WebSocketListener {
|
||||
log.info("err ", e);
|
||||
return AlitaResult.error("语音合成失败:{}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret)
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.newyetai.component.file.util.FileUtils;
|
||||
import com.newyetai.config.service.ConfigService;
|
||||
import com.newyetai.sdk.xf.config.XfProperties;
|
||||
import com.newyetai.sdk.xf.dto.InterviewContentDTO;
|
||||
import com.newyetai.sdk.xf.dto.TtsReqDTO;
|
||||
import com.newyetai.sdk.xf.model.ChatReq;
|
||||
import com.newyetai.sdk.xf.model.MessageDTO;
|
||||
import com.newyetai.sdk.xf.service.XfSparkProvider;
|
||||
@@ -123,15 +124,14 @@ public class XfUtils {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 语音合成
|
||||
* @return
|
||||
* @author sr on 2025-01-09
|
||||
*/
|
||||
public static String tts(String text) {
|
||||
public static String tts(TtsReqDTO ttsReq) {
|
||||
try(ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){
|
||||
AlitaResult<Void> result = WebTtsWS.execute(text, xfProperties, outputStream);
|
||||
AlitaResult<Void> result = WebTtsWS.execute(ttsReq, xfProperties, outputStream);
|
||||
Assert.isTrue(result.getSuccess(), result.getMsg());
|
||||
FileRecord fileRecord = fileService.upload("语音合成.mp3", outputStream.toByteArray());
|
||||
return fileRecord.getFileCode();
|
||||
|
||||
Reference in New Issue
Block a user