百度语音合成通过 REST API 的方式给开发者提供一个通用的 HTTP 接口,基于该接口,开发者可以轻松的获取语音合成能力,本文档描述了使用语音合成服务 REST API 的方法。
对本文中将提到的名词约定如下:
语音合成:也被称为文本转换技术(TTS),它是将计算机自己产生的、或外部输入的文字信息转变为可以听得懂的、流利的口语输出的技术。
应用程序:在开发中调用了 API、具有语音合成功能的产品线产品。
功能介绍
REST API 支持对一段文本的合成,其中对于文本格式以及参数有一定的要求。请按照文档中描述进行相应请求操作。
具体参考:http://yuyin.baidu.com/docs/tts/135
从管理控制台进入创建的应用,如下图所示,API Key(client_id)和 Secret Key(client_secret)即显示于其中, ID 即为应用 id(appid)。
根据百度 OAuth 的 Client Credentials 授权方式获取 access_token。百度 OAuth 的 Client Credentials 和其他授权方式的说明见百度 OAuth 介绍的 "百度支持的 OAuth 授权" 部分。
其中,grant_type 的值固定为 client_credentials,client_id 即为(3)中截图所示的 API Key 的值,client_secret 即为截图所示的 Secret Key 的值。更为详细的介绍请参见 Client Credentials 授权说明。响应如下所示,其中 access_token 字段即为请求 REST API 所需的令牌, access_token 有效期一般为一个月,开发者需要对 access_token,进行有效性判断,过期需重新申请 access_token。请求成功返回的 JSON 数据格式为:
- {
- "access_token": "24.ec37046714941b2a78af9b3e1ef06580.2592000.1492874149.282335-9434283",
- "session_key": "9mzdXqbP+NaF3yTrfmDrvxb4fpvsAdo5lXl+HstDj5C2IXfPJnq2M/0oEmhxRFEuaEYH5y5fYmnJbT5GPWPqtm1zgboG",
- "scope": "public audio_voice_assistant_get audio_tts_post wise_adapt lebo_resource_base lightservice_public hetu_basic lightcms_map_poi kaidian_kaidian wangrantest_test wangrantest_test1 bnstest_test1 bnstest_test2 ApsMisTest_Test67439650 vis-classify_flower",
- "refresh_token": "25.8a27c3ddb074c21e6cefa86d1927845f.315360000.1805642149.282335-9434283",
- "session_secret": "909d30289c56e58e0d7f4f53fb189a26",
- "expires_in": 2592000
- }
获得响应值对应的 "access_token" 对应的值 "24.ec37046714941b2a78af9b3e1ef06580.2592000.1492874149.282335-9434283",
以下是实现请求 accessToken 的核心代码:
- public static String queryAccessToken(){
- String requestUrl = null;
- StringBuffer temp = new StringBuffer();
- temp.append("https://openapi.baidu.com/oauth/2.0/token"+ "?grant_type=client_credentials");
- temp.append("&client_id={client_id}");
- temp.append("&client_secret={client_secret}");
- requestUrl = temp.toString().replace("{client_id}", API_Key).replace("{client_secret}", SecretKey);
- String accessTokenRstStr =httpRequest(requestUrl);
- JSONObject resultJsonObject = (JSONObject) JSONObject.parse(accessTokenRstStr);
- String accessToken = resultJsonObject.getString("access_token");
- return accessToken;
- }
1)文本上传模式
以下是上传参数说明。
将所有的参数都填写到 URL 地址中,可以通过发送 GET 请百度语音合成。
- http: //tsn.baidu.com/text2audio?tex=***&lan=zh&cuid=***&ctp=1&tok=***
也可以将文本以及其他参数写入到 body 里面,利用表单的方式将参数传递到服务端。调用地址为 , 所有的参数都在 body 中。以下是通过 GET 方式来获取百度语音合成服务。
注意:
不论是将参数放到 URL 地址中,还是利用表单的方式放入到 http body 中,参数都需要经过两次 URLENCODE 操作。如果是直接在浏览器地址栏输入则不需要。核心代码如下:
- String inputStr = URLEncoder.encode(URLEncoder.encode("核心管理层更新带来的直接结果是百度内部领域、资源、利益的重新划分,结果就是利益相关人的出局","UTF-8"),"UTF-8");
错误实例为:
- {
- "err_no": 500,
- "err_msg": "notsupport.",
- "sn": "abcdefgh",
- "idx": 1
- }
错误码解释
错误码 | 含义 |
---|---|
500 | 不支持输入 |
501 | 输入参数不正确 |
502 | token 验证失败 |
503 | 合成后端错误 |
保存百度合成语音代码如下:
- public static String httpBaiduVoiceRequest(String requestUrl) {
- System.setProperty("sun.net.client.defaultConnectTimeout", 10 * 60 * 1000 + "");
- System.setProperty("sun.net.client.defaultReadTimeout", 10 * 60 * 1000 + "");
- StringBuffer buffer = new StringBuffer();
- try {
- URL url = new URL(requestUrl);
- HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
- httpUrlConn.setDoInput(true);
- httpUrlConn.setRequestMethod("GET");
- httpUrlConn.setConnectTimeout(10 * 60 * 1000);
- httpUrlConn.setReadTimeout(10 * 60 * 1000);
- httpUrlConn.connect();
- InputStream inputStream = httpUrlConn.getInputStream();
- FileOutputStream fos = new FileOutputStream("d:/testBaidu.mp3");
- byte[] b = new byte[1024];
- while((inputStream.read(b)) != -1){
- fos.write(b);
- }
- inputStream.close();
- fos.close();
- httpUrlConn.disconnect();
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return buffer.toString();
- }
注意:调用成功返回的是连接的输入流,需要把输入流保存到本地音频文件 (比如 d:/testBaidu.mp3) 中, 调用失败返回的是一个 JSON 格式的字符串,实验做到这里,想问问百度语音团队,为什么不是在调用失败时,抛出错误异常信息,在错误异常信息里保存错误实例呢?此处在以后的开发中应当注意,开发的 restful api 借口,要尽可能的复合程序猿的思维,为开发人员考虑,并且完整的调用 api 文档说明。
完整的调用代码如下:
- package test;
- import java.io.BufferedReader;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.net.HttpURLConnection;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.net.URLEncoder;
- import org.apache.log4j.Logger;
- import com.alibaba.fastjson.JSONObject;
- public class HttpUtill
- {
- private static final Logger logger = Logger.getLogger(HttpUtill.class);
- /**
- * 发送Http请求
- *
- * @param requestUrl
- * 请求地址
- */
- public static String httpRequest(String requestUrl) {
- System.setProperty("sun.net.client.defaultConnectTimeout", 10 * 60 * 1000 + "");
- System.setProperty("sun.net.client.defaultReadTimeout", 10 * 60 * 1000 + "");
- StringBuffer buffer = new StringBuffer();
- try {
- URL url = new URL(requestUrl);
- HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
- httpUrlConn.setDoInput(true);
- httpUrlConn.setRequestMethod("GET");
- httpUrlConn.setConnectTimeout(10 * 60 * 1000);
- httpUrlConn.setReadTimeout(10 * 60 * 1000);
- httpUrlConn.connect();
- // 将返回的输入流转换成字符串
- InputStream inputStream = httpUrlConn.getInputStream();
- InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
- String str = null;
- while ((str = bufferedReader.readLine()) != null) {
- buffer.append(str);
- }
- // 释放资源
- bufferedReader.close();
- inputStreamReader.close();
- inputStream.close();
- inputStream = null;
- httpUrlConn.disconnect();
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return buffer.toString();
- }
- public static String httpBaiduVoiceRequest(String requestUrl) {
- System.setProperty("sun.net.client.defaultConnectTimeout", 10 * 60 * 1000 + "");
- System.setProperty("sun.net.client.defaultReadTimeout", 10 * 60 * 1000 + "");
- StringBuffer buffer = new StringBuffer();
- try {
- URL url = new URL(requestUrl);
- HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
- httpUrlConn.setDoInput(true);
- httpUrlConn.setRequestMethod("GET");
- httpUrlConn.setConnectTimeout(10 * 60 * 1000);
- httpUrlConn.setReadTimeout(10 * 60 * 1000);
- httpUrlConn.connect();
- InputStream inputStream = httpUrlConn.getInputStream();
- FileOutputStream fos = new FileOutputStream("d:/testBaidu.mp3");
- byte[] b = new byte[1024];
- while((inputStream.read(b)) != -1){
- fos.write(b);
- }
- inputStream.close();
- fos.close();
- httpUrlConn.disconnect();
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return buffer.toString();
- }
- private static final String ID = "9434283";
- private static final String API_Key = "uS5L3CU0pNGEVeaFYS9pxGDO";
- private static final String SecretKey = "84b4c5f8b4a89da0a84a0046e6edcff0";
- public static String queryAccessToken(){
- String requestUrl = null;
- StringBuffer temp = new StringBuffer();
- temp.append("https://openapi.baidu.com/oauth/2.0/token"+ "?grant_type=client_credentials");
- temp.append("&client_id={client_id}");
- temp.append("&client_secret={client_secret}");
- requestUrl = temp.toString().replace("{client_id}", API_Key).replace("{client_secret}", SecretKey);
- String accessTokenRstStr =httpRequest(requestUrl);
- System.out.println(accessTokenRstStr);
- JSONObject resultJsonObject = (JSONObject) JSONObject.parse(accessTokenRstStr);
- String accessToken = resultJsonObject.getString("access_token");
- return accessToken;
- }
- public static void method1(String token) throws Exception {
- String requestUrl = null;
- StringBuffer temp = new StringBuffer();
- temp.append("http://tsn.baidu.com/text2audio?");
- temp.append("tex={tex}");
- temp.append("&lan=zh");
- temp.append("&tok="+token);
- temp.append("&ctp=1");
- temp.append("&cuid="+ID);
- temp.append("&per=3");
- String inputStr = URLEncoder.encode(URLEncoder.encode("你好,欢迎访问信平的小屋。","UTF-8"),"UTF-8");
- requestUrl = temp.toString().replace("{tex}", inputStr);
- logger.info("*** method1 requestUrl="+requestUrl);
- String result = httpBaiduVoiceRequest(requestUrl);
- logger.info(result);
- }
- public static String printResponse(HttpURLConnection conn) throws Exception {
- if (conn.getResponseCode() != 200) {
- // request error
- return "";
- }
- InputStream is = conn.getInputStream();
- BufferedReader rd = new BufferedReader(new InputStreamReader(is));
- String line;
- StringBuffer response = new StringBuffer();
- while ((line = rd.readLine()) != null) {
- response.append(line);
- response.append('\r');
- }
- rd.close();
- System.out.println("*** step2 response="+response.toString());
- System.out.println(JSONObject.parse(response.toString()));
- return response.toString();
- }
- public static void main(String[] args)
- {
- HttpUtill test = new HttpUtill();
- String accessToken = test.queryAccessToken();
- System.out.println("*** step1 accessToekn=" + accessToken );
- try
- {
- test.method1(accessToken);
- } catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
如果读者没有开发基础,可以参考百度官方的语音合成产品的 demo .
- http: //yuyin.baidu.com/#try
最后,还是希望百度语音团队能够开发更多语音合成参数,比如输入更多的人声训练文本,让读者可以自由上传自己喜欢的明星的语音素材,随意输入文本然后通过程序合成语音,用明星的语气来说出来,那将会更有乐趣。
资料参考:
百度语音合成官方文档
http://yuyin.baidu.com/docs/tts/135
来源: http://www.cnblogs.com/wangshuo1/p/6607921.html