最近有需求,在原有的h5新闻页面顶部添加一个语音播报功能,播放出当前页的文章,要两个方案,一个免费的一个收费的。就开始了解在线语音合成,最后决定免费用百度,收费的用讯飞。这篇将讯飞语音合成api的使用,上一篇讲的百度api
本来的思路是在线请求,然后返回音频播放,然后了解到不论是百度的还是讯飞的一次转换数量都有限,这样的话分割文章会返回多个语音,然后上面的进度条就是一条语音的进度条,这样不行,后来想到先合成多个mp3音频,然后再合并成一个,那样在线合成会很慢。
最后就采用在上传文章时候一并上传合成好的MP3音频,然后一起上传到服务器,也就是一个html文章对应一个mp3,只需给路径就可以。这样就是一个完整的音频,进度条也就正确了。
其实发这个博客也想问问大家,如果在线的话如何解决慢的问题,或者有什么别的办法,还有就是打开文章时候得加载一个MP3文件很慢,如何使用缓存技术,没有弄过。希望弄过的 说一下,或者给出一些相关文章在评论中。谢谢QAQ
第一步:打开讯飞语音合成官网 [语音合成],注册,然后在控制台创建应用,选择在线语音合成,创建好后会有appid和APIKey。后面会用到,然后有一个ip白名单,点击管理,填写你自己的外网ip。
第二步:下载官方demo,官方demo下载选择java语言的。
然后里面会有三个java文件分别是FileUtil.java、HttpUtil.java、WebTTs.java
我们只需要修改WebTTs.java
将你创建应用的appid
和apikey
填写上去就行。
然后在main方法中运行就可以了。
下面是我修改后的WebTTs和控制类,以及jsp
WebTTs.java
/**
* 语音合成 WebAPI 接口调用示例
* 运行方法:直接运行 main() 即可
* 结果: 若合成成功,则音频保存在resouce目录,文件名为 sid; 若合成失败,控制台输出错误信息
* @author iflytek
*
*/
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
/**
* 语音合成 WebAPI 接口调用示例 接口文档(必看):https://doc.xfyun.cn/msc_android/%E8%AF%AD%E9%9F%B3%E5%90%88%E6%88%90.html
* webapi 合成服务参考帖子:http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=38997&extra=
* webapi是单次只支持1000个字节,具体看您的编码格式,计算一下具体支持多少文字
* 合成发音人自动添加获取测试权限使用方法:登陆开放平台https://www.xfyun.cn/后--我的应用(必须为webapi类型应用)--添加在线语音合成(已添加的不用添加)--发音人管理---添加发音人--测试代码里需修改发音人参数
*(Very Important)创建完webapi应用添加合成服务之后一定要设置ip白名单,找到控制台--我的应用--设置ip白名单,如何设置参考:http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=41891
* 错误码链接:https://www.xfyun.cn/document/error-code (code返回错误码时必看)
* @author iflytek
*/
public class WebTTs {
// 合成webapi接口地址
private static final String WEBTTS_URL = "你的";
// 应用APPID(必须为webapi类型应用,并开通语音合成服务,参考帖子如何创建一个webapi应用:http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=36481)
private static final String APPID = "你的";
// 接口密钥(webapi类型应用开通合成服务后,控制台--我的应用---语音合成---相应服务的apikey)
private static final String API_KEY = "0743046eec24dae23e473be4a5396bc3";
// 待合成文本
//private static final String TEXT = "测试音频";
// 音频编码(raw合成的音频格式pcm、wav,lame合成的音频格式MP3)
private static final String AUE = "lame";
// 采样率
private static final String AUF = "audio/L16;rate=16000";
// 语速(取值范围0-100)
private static final String SPEED = "40";
// 音量(取值范围0-100)
private static final String VOLUME = "50";
// 音调(取值范围0-100)
private static final String PITCH = "50";
// 发音人(登陆开放平台https://www.xfyun.cn/后--我的应用(必须为webapi类型应用)--添加在线语音合成(已添加的不用添加)--发音人管理---添加发音人--修改发音人参数)
private static final String VOICE_NAME = "xiaoyan";
// 引擎类型
private static final String ENGINE_TYPE = "aisound";
// 文本类型(webapi是单次只支持1000个字节,具体看您的编码格式,计算一下具体支持多少文字)
private static final String TEXT_TYPE = "text";
/**
* 合成 WebAPI 调用示例程序
*
* @param args
* @throws IOException
*/
public static void get_WebTTs(String txt,int order) throws IOException {
System.out.println("txt="+txt);
Map header = buildHttpHeader();
Map resultMap = HttpUtil.doPost2(WEBTTS_URL, header, "text=" + URLEncoder.encode(txt, "utf-8"));
System.out.println("占用内存大小: "+ URLEncoder.encode(txt, "utf-8").getBytes().length);
if ("audio/mpeg".equals(resultMap.get("Content-Type"))) { // 合成成功
if ("raw".equals(AUE)) {
FileUtil.save("D:/a/", order + ".wav", (byte[]) resultMap.get("body"));
System.out.println("合成 WebAPI 调用成功,音频保存位置:D:/a/" + order + ".wav");
} else {
FileUtil.save("D:/a/", order + ".mp3", (byte[]) resultMap.get("body"));
System.out.println("合成 WebAPI 调用成功,音频保存位置:D:/a/" + order + ".mp3");
}
} else { // 合成失败
System.out.println("合成 WebAPI 调用失败,错误信息:" + resultMap.get("body").toString());//返回code为错误码时,请查询https://www.xfyun.cn/document/error-code解决方案
}
}
/**
* 组装http请求头
*/
public static Map buildHttpHeader() throws UnsupportedEncodingException {
String curTime = System.currentTimeMillis() / 1000L + "";
String param = "{\"auf\":\"" + AUF + "\",\"aue\":\"" + AUE + "\",\"voice_name\":\"" + VOICE_NAME + "\",\"speed\":\"" + SPEED + "\",\"volume\":\"" + VOLUME + "\",\"pitch\":\"" + PITCH + "\",\"engine_type\":\"" + ENGINE_TYPE + "\",\"text_type\":\"" + TEXT_TYPE + "\"}";
String paramBase64 = new String(Base64.encodeBase64(param.getBytes("UTF-8")));
String checkSum = DigestUtils.md5Hex(API_KEY + curTime + paramBase64);
Map header = new HashMap();
header.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
header.put("X-Param", paramBase64);
header.put("X-CurTime", curTime);
header.put("X-CheckSum", checkSum);
header.put("X-Appid", APPID);
return header;
}
}
控制类:里面的分割字符串方法使用的是
分割字符串
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.json.JSONException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.chinaDaily.ttsdemo.DemoException;
import com.chinaDaily.ttsdemo.TtsMain;
import com.chinaDaily.webapi_tts.WebTTs;
import com.google.gson.Gson;
@Controller
public class get_WebTTs {
@RequestMapping("get_baiduWebTTs.action")
@ResponseBody
public String get_baiduWebTTs(HttpServletRequest request) throws DemoException, JSONException {
String txt = request.getParameter("txt");
try {
txt = new String(txt.getBytes("iso-8859-1"),"utf-8");
txt = java.net.URLDecoder.decode(txt,"UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
List strList = getStrList(txt,500);//按500长度分割
try {
for(int i=0;i getStrList(String inputString, int length) {
int size = inputString.length() / length;
if (inputString.length() % length != 0) {
size += 1;
}
return getStrList(inputString, length, size);
}
public static List getStrList(String inputString, int length,
int size) {
List list = new ArrayList();
for (int index = 0; index < size; index++) {
String childStr = substring(inputString, index * length,
(index + 1) * length);
list.add(childStr);
}
return list;
}
public static String substring(String str, int f, int t) {
if (f > str.length())
return null;
if (t > str.length()) {
return str.substring(f, str.length());
} else {
return str.substring(f, t);
}
}
}
jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
Insert title here
输入内容:
应该复制完,jar包齐全,不报错就可以运行,逻辑就是jsp发出请求,将txt传到后台,然后后台按500长度进行分割,循环请求百度的api,然后生成多个文件,再使用合成工具将多个MP3合成一个MP3。