提交 557248f0 authored 作者: liupengfei's avatar liupengfei

--no commit message

上级 50a65df8
package com.zrqx.resource.bg.controller.ebook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.stream.Collectors;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
......@@ -23,6 +36,8 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.github.pagehelper.PageHelper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.zrqx.core.client.sysuser.bg.SysuserClient;
import com.zrqx.core.client.vo.ImportLabelVo;
import com.zrqx.core.commons.redis.Redis;
......@@ -81,12 +96,21 @@ import com.zrqx.resource.commons.model.qrcode.QrCode;
import com.zrqx.resource.commons.model.resourcerelation.RelationAuthor;
import com.zrqx.resource.commons.solr.SolrManage;
import com.zrqx.resource.commons.util.WebTTSWSUtil;
import com.zrqx.resource.commons.util.WebTTSWSUtil.Data;
import com.zrqx.resource.commons.util.WebTTSWSUtil.ResponseData;
import com.zrqx.resource.commons.vo.bg.EpubVo;
import com.zrqx.resource.commons.vo.bg.ebook.EbookListVO;
import com.zrqx.resource.commons.vo.bg.ebook.EbookVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
import tk.mybatis.mapper.entity.Example;
......@@ -151,6 +175,11 @@ public class EbookController {
private QrCodeService qrCodeService;
@Value("${qrcode-upload-path}")
private String qrCodeUploadPath;
private static final String hostUrl = "https://tts-api.xfyun.cn/v2/tts"; //http url 不支持解析 ws/wss schema
private static final String appid = "5f800e7f";//到控制台-语音合成页面获取
private static final String apiSecret = "fcf21aa34ac9b1c89a5ae080e86f406c";//到控制台-语音合成页面获取
private static final String apiKey = "793094b3d3f8dd4c4f57193499d6cc5a";//到控制台-语音合成页面获取
public static final Gson json = new Gson();
@ApiOperation("保存电子书")
@PostMapping("/save")
......@@ -588,7 +617,7 @@ public class EbookController {
for(int i = 0 ; i < textList.size() ; i++) {
try {
String fileName = i+1+"";
String articlePath = WebTTSWSUtil.testToAudio(textList.get(i),article.getId(),fileName);
String articlePath = testToAudio(textList.get(i),article.getId(),fileName);
ArticleToAudio articleToAudio = new ArticleToAudio();
articleToAudio.setArticleId(article.getId());
articleToAudio.setUploadTime(new Date());
......@@ -719,7 +748,7 @@ public class EbookController {
for(int i = 0 ; i < textList.size() ; i++) {
try {
String fileName = i+1+"";
String articlePath = WebTTSWSUtil.testToAudio(textList.get(i),article.getId(),fileName);
String articlePath = testToAudio(textList.get(i),article.getId(),fileName);
ArticleToAudio articleToAudio = new ArticleToAudio();
articleToAudio.setArticleId(article.getId());
articleToAudio.setUploadTime(new Date());
......@@ -795,6 +824,176 @@ public class EbookController {
* @param length 指定长度
* @return
*/
public static String testToAudio(String text,String filePath,String fileName) throws Exception {
// 构建鉴权url
String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
OkHttpClient client = new OkHttpClient.Builder().build();
//将url中的 schema http://和https://分别替换为ws:// 和 wss://
String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
Request request = new Request.Builder().url(url).build();
// 存放音频的文件
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
File file = new File("/opt/upload/hxwza/audio/" + filePath);
if(!file.exists()) {
file.mkdirs();
}
File f = new File("/opt/upload/hxwza/audio/" + filePath + "/" + fileName + ".mp3");
String path = "/audio/" + filePath + "/" + fileName + ".mp3";
if (!f.exists()) {
f.createNewFile();
}
FileOutputStream os = new FileOutputStream(f);
WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
//发送数据
JsonObject frame = new JsonObject();
JsonObject business = new JsonObject();
JsonObject common = new JsonObject();
JsonObject data = new JsonObject();
// 填充common
common.addProperty("app_id", appid);
//填充business
business.addProperty("aue", "lame");
business.addProperty("sfl", 1);
business.addProperty("tte", "UTF8");//小语种必须使用UNICODE编码
business.addProperty("vcn", "xiaoyan");//到控制台-我的应用-语音合成-添加试用或购买发音人,添加后即显示该发音人参数值,若试用未添加的发音人会报错11200
business.addProperty("pitch", 50);
business.addProperty("speed", 50);
//填充data
data.addProperty("status", 2);//固定位2
try {
data.addProperty("text", Base64.getEncoder().encodeToString(text.getBytes("utf8")));
//使用小语种须使用下面的代码,此处的unicode指的是 utf16小端的编码方式,即"UTF-16LE"”
//data.addProperty("text", Base64.getEncoder().encodeToString(text.getBytes("UTF-16LE")));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//填充frame
frame.add("common", common);
frame.add("business", business);
frame.add("data", data);
webSocket.send(frame.toString());
}
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
//处理返回数据
System.out.println("receive=>" + text);
ResponseData resp = null;
try {
resp = json.fromJson(text, ResponseData.class);
} catch (Exception e) {
e.printStackTrace();
}
if (resp != null) {
if (resp.getCode() != 0) {
System.out.println("error=>" + resp.getMessage() + " sid=" + resp.getSid());
return;
}
if (resp.getData() != null) {
String result = resp.getData().audio;
byte[] audio = Base64.getDecoder().decode(result);
try {
os.write(audio);
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
if (resp.getData().status == 2) {
// todo resp.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源
System.out.println("session end ");
System.out.println("合成的音频文件保存在:" + f.getPath());
webSocket.close(1000, "");
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
@Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes);
}
@Override
public void onClosing(WebSocket webSocket, int code, String reason) {
super.onClosing(webSocket, code, reason);
System.out.println("socket closing");
}
@Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
System.out.println("socket closed");
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
System.out.println("connection failed");
}
});
return path;
}
public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
URL url = new URL(hostUrl);
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = format.format(new Date());
StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").//
append("date: ").append(date).append("\n").//
append("GET ").append(url.getPath()).append(" HTTP/1.1");
Charset charset = Charset.forName("UTF-8");
Mac mac = Mac.getInstance("hmacsha256");
SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256");
mac.init(spec);
byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
String sha = Base64.getEncoder().encodeToString(hexDigits);
String authorization = String.format("hmac username=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(charset))).//
addQueryParameter("date", date).//
addQueryParameter("host", url.getHost()).//
build();
return httpUrl.toString();
}
public static class ResponseData {
private int code;
private String message;
private String sid;
private Data data;
public int getCode() {
return code;
}
public String getMessage() {
return this.message;
}
public String getSid() {
return sid;
}
public Data getData() {
return data;
}
}
public static class Data {
private int status; //标志音频是否返回结束 status=1,表示后续还有音频返回,status=2表示所有的音频已经返回
private String audio; //返回的音频,base64 编码
private String ced; // 合成进度
}
/**
* 把原始字符串分割成指定长度的字符串列表
* @param inputString 原始字符串
* @param length 指定长度
* @return
*/
public static List<String> getStrList(String inputString, int length) {
int size = inputString.length() / length;
if (inputString.length() % length != 0) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论