java调用讯飞语音合成api

最近有需求,在原有的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将你创建应用的appidapikey填写上去就行。
然后在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<String, String> header = buildHttpHeader();
		
		Map<String, Object> 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<String, String> 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<String, String> header = new HashMap<String, String>();
		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<String> strList = getStrList(txt,500);//按500长度分割
		try {
			for(int i=0;i<strList.size();i++){
				TtsMain.run(strList.get(i),i+1);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return "2";
	}
	
    public static List<String> 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<String> getStrList(String inputString, int length,
            int size) {
        List<String> list = new ArrayList<String>();
        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"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
输入内容:<textarea rows="25" cols="120" id="txt" ></textarea><br>
<input type="button" id="formBtn" value="语音合成">
</body>
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script  type="text/javascript">
$('#formBtn').click(function () {
var txt=$("#txt").val();
	$.ajax({
		type: "post",
		url: "${pageContext.request.contextPath}/get_baiduWebTTs.action",
		data: {"txt":txt},
		dataType:"json",
		success: function(msg){
			alert("百度语音合成成功");
			}
	})
});
</script>
</html>

应该复制完,jar包齐全,不报错就可以运行,逻辑就是jsp发出请求,将txt传到后台,然后后台按500长度进行分割,循环请求百度的api,然后生成多个文件,再使用合成工具将多个MP3合成一个MP3。

发布了64 篇原创文章 · 获赞 103 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/P_Doraemon/article/details/93217068