文字转音频

This commit is contained in:
wuchunlei
2024-12-06 14:37:06 +08:00
parent 62ab9fbbb2
commit 5e232e932a
2 changed files with 178 additions and 17 deletions

View File

@@ -1,25 +1,118 @@
package com.peanut.common.utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.UUID;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.joda.time.DateTime;
public class BaiduVoicesUtils {
// 填写申请百度语音申请的appkey 申请地址百度AI开放平台
//todo private final static String appKey = "aKDun6vXyqPLhWMdoIsv87Ez";
private final static String appKey = "WOKN473V1o1gL8WMsAkfJZIY";
private final static String secretKey = "CpgbKdB9aZu2esnq5lMdqRZG37Jn3a76";
public static String shortText(String content){
try {
String getTokenURL = "https://tsn.baidu.com/text2audio?tok=" + getAccessToken();
getTokenURL += "&cuid=zcc123456&ctp=1&lan=zh";
getTokenURL += "&spd=4";//语速取值0-15默认为5中语速
getTokenURL += "&pit=5";//音调取值0-15默认为5中语调
getTokenURL += "&vol=7";//音量取值0-15默认为5中音量取值为0时为音量最小值并非为无声
getTokenURL += "&per=1";//度小宇=1度小美=0度逍遥基础=3度丫丫=4 度逍遥(精品)=5003度小鹿=5118度博文=106度小童=110度小萌=111度米朵=103度小娇=5
getTokenURL += "&tex=" + ConnUtil.urlEncode(content);
URL url = new URL(getTokenURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
String contentType = conn.getContentType();
if (contentType.contains("mp3")) {
byte[] bytes = ConnUtil.getResponseBytes(conn);
String fileUrl = uploadFile(new ByteArrayInputStream(bytes),UUID.randomUUID().toString()+".mp3");
return fileUrl;
} else {
System.err.println("ERROR: content-type= " + contentType);
String res = ConnUtil.getResponseString(conn);
System.err.println(res);
return "";
}
}catch (Exception e) {
e.printStackTrace();
return "";
}
}
//长文字查询
public void queryVoice(String id) throws Exception {
URL url = new URL("https://aip.baidubce.com/rpc/2.0/tts/v1/query?access_token=" + getAccessToken());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
JSONObject jsonObject = new JSONObject();
jsonObject.put("task_ids", Arrays.asList(id));
writer.write(jsonObject.toString());
writer.flush();
writer.close();
String result = ConnUtil.getResponseString(conn);
JSONArray tasksInfo = (JSONArray)(JSONObject.parseObject(result).get("tasks_info"));
JSONObject i = (JSONObject)tasksInfo.get(0);
String taskStatus = i.get("task_status").toString();
if ("Running".equals(taskStatus)){
queryVoice(id);
}
System.out.println("taskId:" + result);
}
//长文字转换
public String excute(String content) throws Exception {
URL url = new URL("https://aip.baidubce.com/rpc/2.0/tts/v1/create?access_token=" + getAccessToken());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
JSONObject jsonObject = new JSONObject();
jsonObject.put("text",content);
jsonObject.put("voice",1);//基础音库:度小宇=1度小美=0度逍遥基础=3度丫丫=4精品音库度逍遥精品=5003度小鹿=5118度博文=106度小童=110度小萌=111度米朵=103度小娇=5。默认为度小美
jsonObject.put("lang", "zh");//固定值zh。语言选择,目前只有中英文混合模式填写固定值zh
jsonObject.put("speed", 3);//取值0-15默认为5中语速
jsonObject.put("pitch", 5);//取值0-15默认为5中语调
jsonObject.put("volume", 8);//取值0-15默认为5中音量取值为0时为音量最小值并非为无声
jsonObject.put("enable_subtitle", 1);//取值范围0, 1, 2默认为0。0表示不开启字幕1表示开启句级别字幕2表示开启词级别字幕
writer.write(jsonObject.toString());
writer.flush();
writer.close();
String result = ConnUtil.getResponseString(conn);
String taskId = JSONObject.parseObject(result).get("task_id").toString();
System.out.println("taskId result json:" + taskId);
return taskId;
}
public static String getAccessToken() throws Exception {
String getTokenURL = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials" + "&client_id=" + ConnUtil.urlEncode(appKey)
+ "&client_secret=" + ConnUtil.urlEncode(secretKey);
URL url = new URL(getTokenURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
String result = ConnUtil.getResponseString(conn);
String accessToken = JSONObject.parseObject(result).get("access_token").toString();
return accessToken;
}
// private final static String appKey = "eaPPX40oIazH8R4oWsD9U4IT";
private final static String appKey = "xkyZMti9hu6KSQ8PdRDsadqI";
// 填写申请百度语音申请的APP SECRET
// todo private final static String secretKey = "ew9dMb4yGmwF1g4qutxNvogzjd9eP5tb";
// private final static String secretKey = "DTN0ioQywwM23IoT2ZzEBmvfBe63ATEY";
private final static String secretKey = "KQvdrrADpV7hBzptqvakwG56dYuGljeg";
// text 的内容为"欢迎使用百度语音合成"的urlencode,utf-8 编码
private final String text = "百度百科是百度公司推出的一部内容开放、自由的网络百科全书。";
@@ -42,14 +135,6 @@ public class BaiduVoicesUtils {
TokenHolder holder = new TokenHolder(appKey, secretKey, TokenHolder.ASR_SCOPE);
holder.resfresh();
String token = holder.getToken();
String token1 = holder.getToken();
final String s = ConnUtil.urlEncode(content);
String url21 = url +"?tex=" + s;
url21 +="&per="+ per;
url21 +=""+cuid;
url21 +=""+vol;
long expiresAt = holder.getExpiresAt();
// for (String a:list) {
String url2 = url + "?tex=" + ConnUtil.urlEncode(content);
url2 += "&per=" + per;
url2 += "&spd=" + spd;
@@ -80,4 +165,24 @@ public class BaiduVoicesUtils {
// }
}
public static String uploadFile(InputStream inputStream, String fileName) {
String endpoint = ConstantPropertiesUtils.END_POIND;
String accessKeyId = ConstantPropertiesUtils.ACCESS_KEY_ID;
String accessKeySecret = ConstantPropertiesUtils.ACCESS_KEY_SECRET;
String bucketName = ConstantPropertiesUtils.BUCKET_NAME;
try {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
fileName = uuid + fileName;
String datePath = new DateTime().toString("yyyy/MM/dd");
fileName = datePath + "/" + fileName;
ossClient.putObject(bucketName, fileName, inputStream);
ossClient.shutdown();
String url = "https://" + bucketName + "." + endpoint + "/" + fileName;
return url;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@@ -52,6 +52,62 @@ public class BookChapterContentController {
private UserEbookBuyService userEbookBuyService;
@Autowired
private ShopProductBookService shopProductBookService;
//章节内容单句转成音频
@RequestMapping("/contentToVoices")
public R contentToVoices(@RequestBody Map<String,Object> params){
//调用百度语音合成 API
String voices = BaiduVoicesUtils.shortText(params.get("content").toString());
if (StringUtils.isEmpty(voices)) {
return R.error("语音上传失败");
}
return R.ok().put("voices", voices);
}
//书籍全部章节转成音频
@RequestMapping("/bookToVoices")
public R bookToVoices(@RequestBody Map<String,Object> params){
// 1、创建服务创建线程池
ExecutorService service = Executors.newFixedThreadPool(5);
List<BookChapterContentEntity> list = bookChapterContentService.list(new LambdaQueryWrapper<BookChapterContentEntity>()
.eq(BookChapterContentEntity::getBookId,params.get("bookId")));
for (BookChapterContentEntity bcc:list){
if (!bcc.getContent().contains("https")&&!"".equals(bcc.getContent())){
service.execute(new Runnable() {
@Override
public void run() {
//调用百度语音合成 API
String voices = BaiduVoicesUtils.shortText(bcc.getContent());
bcc.setVoices(voices);
bookChapterContentService.updateById(bcc);
}
});
}
}
return R.ok();
}
/**
* 列表