長文本語音合成RESTful API支持HTTPS POST方式請求,將待合成的文本通過HTTPS POST上傳到服務端,服務端返回文本的語音合成結果。
功能介紹
支持如下設置:
合成音頻的格式:.pcm、.wav、.mp3。
合成音頻的采樣率:8000 Hz、16000 Hz。
多種發(fā)音人。
可設置語速、語調、音量。
數據獲取方式:輪詢方式、回調方式。
隨著TTS合成效果不斷提升,算法的復雜度也越來越高,對您而言,可能會遇到合成耗時變長的情況。因此我們建議您使用流式合成機制。本文及SDK示例中有相關流式處理示例代碼可供參考。
新增RESTful語音合成Java示例代碼。
前提條件
已獲取項目Appkey,詳情請參見創(chuàng)建項目。
已獲取Access Token,詳情請參見獲取Token概述。
服務地址
訪問類型 | 說明 | URL | Host |
外網訪問 | 所有服務器均可使用外網訪問URL。 | https://nls-gateway-cn-shanghai.aliyuncs.com/rest/v1/tts/async | nls-gateway-cn-shanghai.aliyuncs.com |
內網訪問 | 使用阿里云上海ECS(即ECS地域為華東2(上海)),可使用內網訪問URL。 | http://nls-gateway-cn-shanghai-internal.aliyuncs.com/rest/v1/tts/async | nls-gateway-cn-shanghai-internal.aliyuncs.com |
以下將以使用外網訪問URL的方式進行介紹。如果您使用阿里云上海ECS,并需要通過內網訪問URL,則使用HTTP協議,并替換外網訪問的URL和Host。以下示例中除了Python,均支持HTTP和HTTPS協議,在使用Python示例時請閱讀其注意事項。
POST方法上傳文本
一個完整的語音合成RESTful API POST請求包含以下要素:
URL
協議
URL
方法
HTTPS
https://nls-gateway-cn-shanghai.aliyuncs.com/rest/v1/tts/async
POST
HTTPS POST請求體
請求體是請求參數組成的JSON格式字符串,因此在POST請求頭部中的
Content-Type
必須設置為”application/json”,示例如下。{ "payload":{ "tts_request":{ "voice":"xiaoyun", "sample_rate":16000, "format":"wav", "text":"今天天氣好晴朗", "enable_subtitle": true }, "enable_notify":false }, "context":{ "device_id":"my_device_id" }, "header":{ "appkey":"yourAppkey", "token":"yourToken" } }
請求響應
發(fā)送請求后,不論是調用成功還是失敗,服務端的響應消息都會通過HTTP的消息體返回給客戶端。使用HTTPS GET方法和使用HTTPS POST方法請求的響應是相同的,響應的結果都包含在HTTPS的Body中。響應結果的成功或失敗通過HTTPS Header的Content-Type
字段來區(qū)分:
成功響應
HTTPS Header的
Content-Type
字段內容為audio/mpeg
,表示合成成功,合成的語音數據在Body中。HTTPS Header的
X-NLS-RequestId
字段內容為請求任務的task_id
。Body內容為合成音頻的二進制數據。
失敗響應
HTTPS Header沒有
Content-Type
字段,或者Content-Type
字段內容為application/json
,表示合成失敗,錯誤信息在Body中。HTTPS Header的
X-NLS-RequestId
字段內容為請求任務的task_id
。Body內容為錯誤信息,以JSON格式的字符串表示。
錯誤信息字段如下表所示。
名稱
類型
描述
task_id
String
32位請求任務ID,請記錄該值,用于排查錯誤。
error_code
Integer
服務狀態(tài)碼。
error_message
String
服務狀態(tài)描述。
發(fā)起請求后的成功響應
{ "status":200, "error_code":20000000, "error_message":"SUCCESS", "request_id":"f0a9e2c49e9049e78730a3bf0b32****", "data":{ "task_id":"35d9f813e00b11e9a2ce9ba0d6a2****" } }
發(fā)起請求后的失敗響應
{ "error_message":"Meta:ACCESS_DENIED:The token 'fdf' is invalid!", "error_code":40000001, "request_id":"0d8c0eea55824aada9a374aec650****", "url":"/rest/v1/tts/async", "status":400 }
獲取合成結果
根據上一步請求成功響應后返回的task_id,再次發(fā)送GET請求或者輪詢獲取,獲取合成文件并下載。
參數 | 示例 |
URL | https://nls-gateway-cn-shanghai.aliyuncs.com/rest/v1/tts/async |
appkey | 您的Appkey。 |
token | 您的Token。 |
task_id | 上一步請求成功響應后返回的task_id。 |
獲取合成結果GET請求示例如下:
https://nls-gateway-cn-shanghai.aliyuncs.com/rest/v1/tts/async?appkey={Appkey}&task_id={task_id}&token={Token}
命令執(zhí)行成功或者輪詢服務端合成狀態(tài)的成功響應返回示例如下,其中audio_address
為合成后語音的下載鏈接。
audio_address
字段對應的HTTP下載地址有期限最多只有7天。
/// 輪詢時服務端返回的中間狀態(tài)。
{
"status":200,
"error_code":20000000,
"error_message":"RUNNING",
"request_id":"a3370c49a29148e78b39978f98ba****",
"data":{
"task_id":"35d9f813e00b11e9a2ce9ba0d6a2****",
"audio_address":null,
"notify_custom":null
}
}
/// 獲取到最終合成結果。
{
"status":200,
"error_code":20000000,
"error_message":"SUCCESS",
"request_id":"c541eae489af48d69dae2d2e203a****",
"data":{
"sentences":[
{
"text":"長文本語音合成接口",
"begin_time":"0",
"end_time":"2239"
},
{
"text":"一次返回所有文本對應的音頻.現在需要增加句級別的時間戳信息",
"begin_time":"2239",
"end_time":"8499"
},
{
"text":"客戶可利用該信息,實現播放控制功能",
"begin_time":"8499",
"end_time":"12058"
}
],
"task_id":"f4e9bf53cb1611eab327b15f61b4****",
"audio_address":"此處為生成的URL地址",
"notify_custom":""
}
}
如果開啟enable_notify/notify_url,回調識別結果為:
{
"data": {
"audio_address": "http://nls-cloud-cn-shanghai.oss-cn-shanghai.aliyuncs.com/******.wav",
"task_id": "e3a06366d**************e1257693b"
},
"request_id": "edc6b5ab4***********223c8ace71",
"status": 20000000,
"error_code": 20000000,
"error_message": "SUCCESS"
}
服務狀態(tài)碼
服務狀態(tài)碼 | 服務狀態(tài)描述 | 解決辦法 |
20000000 | 請求成功 | 無。 |
40000000 | 默認的客戶端錯誤碼 | 檢查對應的錯誤消息。 |
40000001 | 身份認證失敗 | 檢查使用的令牌是否正確,是否過期。 |
40000002 | 無效的消息 | 檢查發(fā)送的消息是否符合要求。 |
40000003 | 無效的參數 | 檢查參數值設置是否合理。 |
40000004 | 空閑超時 | 確認是否長時間沒有發(fā)送數據到服務端。 |
40000005 | 請求數量過多 | 檢查是否超過了并發(fā)連接數或者每秒鐘請求數。 |
40000010 | 試用期已結束,并且未開通商用版、或賬號欠費。 | 請登錄控制臺確認服務開通狀態(tài)以及賬戶余額。 |
50000000 | 默認的服務端錯誤 | 內部服務錯誤,需要客戶端進行重試。 |
50000001 | 內部GRPC調用錯誤 | 內部服務錯誤,需要客戶端進行重試。 |
Java示例
依賴文件內容如下:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.9.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
示例代碼如下:
package com.alibaba.nls.client;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 此示例演示了長文本語音合成的使用方式。
*/
public class SpeechLongSynthesizerRestfulDemo {
private static Logger logger = LoggerFactory.getLogger(SpeechLongSynthesizerRestfulDemo.class);
private String accessToken;
private String appkey;
public SpeechLongSynthesizerRestfulDemo(String appkey, String token) {
this.appkey = appkey;
this.accessToken = token;
}
public void processPOSTRequest(String text, String format, int sampleRate, String voice) {
String url = "https://nls-gateway-cn-shanghai.aliyuncs.com/rest/v1/tts/async";
// 拼接HTTP Post請求的消息體內容。
JSONObject context = new JSONObject();
// device_id設置,可以設置為自定義字符串或者設備信息id。
context.put("device_id", "my_device_id");
JSONObject header = new JSONObject();
// 設置你的appkey。獲取Appkey請前往控制臺:https://nls-portal.console.aliyun.com/applist
header.put("appkey", appkey);
// 設置你的Token。獲取Token具體操作,請參見:http://bestwisewords.com/document_detail/450514.html
header.put("token", accessToken);
// voice 發(fā)音人,可選,默認是xiaoyun。
// volume 音量,范圍是0~100,可選,默認50。
// speech_rate 語速,范圍是-500~500,可選,默認是0。
// pitch_rate 語調,范圍是-500~500,可選,默認是0。
JSONObject tts = new JSONObject();
tts.put("text", text);
// 設置發(fā)音人。
tts.put("voice", voice);
// 設置編碼格式。
tts.put("format", format);
// 設置采樣率。
tts.put("sample_rate", sampleRate);
// 設置聲音大小,可選。
//tts.put("volume", 100);
// 設置語速,可選。
//tts.put("speech_rate", 200);
// 長文本tts restful接口支持句級時間戳,默認為false。
tts.put("enable_subtitle", true);
JSONObject payload = new JSONObject();
// 可選,是否設置回調。如果設置,則服務端在完成長文本語音合成之后回調用戶此處設置的回調接口,將請求狀態(tài)推送給用戶側。
payload.put("enable_notify", false);
payload.put("notify_url", "http://123.com");
payload.put("tts_request", tts);
JSONObject json = new JSONObject();
json.put("context", context);
json.put("header", header);
json.put("payload", payload);
String bodyContent = json.toJSONString();
logger.info("POST Body Content: " + bodyContent);
// 發(fā)起請求
RequestBody reqBody = RequestBody.create(MediaType.parse("application/json"), bodyContent);
Request request = new Request.Builder()
.url(url)
.header("Content-Type", "application/json")
.post(reqBody)
.build();
try {
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String contentType = response.header("Content-Type");
System.out.println("contentType = " + contentType);
// 獲取結果,并根據返回進一步進行處理。
String result = response.body().string();
response.close();
System.out.println("result = " + result);
JSONObject resultJson = JSON.parseObject(result);
if(resultJson.containsKey("error_code") && resultJson.getIntValue("error_code") == 20000000) {
logger.info("Request Success! task_id = " + resultJson.getJSONObject("data").getString("task_id"));
String task_id = resultJson.getJSONObject("data").getString("task_id");
String request_id = resultJson.getString("request_id");
/// 可選:輪詢檢查服務端的合成狀態(tài),該輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
waitLoop4Complete(url, appkey, accessToken, task_id, request_id);
}else {
logger.error("Request Error: status=" + resultJson.getIntValue("status")
+ ", error_code=" + resultJson.getIntValue("error_code")
+ ", error_message=" + resultJson.getString("error_message"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/// 根據特定信息輪詢檢查某個請求在服務端的合成狀態(tài),輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
private void waitLoop4Complete(String url, String appkey, String token, String task_id, String request_id) {
String fullUrl = url + "?appkey=" + appkey + "&task_id=" + task_id + "&token=" + token + "&request_id=" + request_id;
System.out.println("query url = " + fullUrl);
while(true) {
Request request = new Request.Builder().url(fullUrl).get().build();
try {
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String result = response.body().string();
response.close();
System.out.println("waitLoop4Complete = " + result);
JSONObject resultJson = JSON.parseObject(result);
if(resultJson.containsKey("error_code")
&& resultJson.getIntValue("error_code") == 20000000
&& resultJson.containsKey("data")
&& resultJson.getJSONObject("data").getString("audio_address") != null) {
logger.info("Tts Finished! task_id = " + resultJson.getJSONObject("data").getString("task_id"));
logger.info("Tts Finished! audio_address = " + resultJson.getJSONObject("data").getString("audio_address"));
break;
}else {
logger.info("Tts Queuing...");
}
// 每隔10秒鐘輪詢一次狀態(tài)。
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
if (args.length < 2) {
System.err.println("SpeechLongSynthesizerRestfulDemo need params: <token> <app-key>");
System.exit(-1);
}
String token = args[0];
String appkey = args[1];
SpeechLongSynthesizerRestfulDemo demo = new SpeechLongSynthesizerRestfulDemo(appkey, token);
String text = "我家的后面有一個很大的園,相傳叫作百草園?,F在是早已并屋子一起賣給朱文公的子孫了,連那最末次的相見也已經隔了七八年,其中似乎確鑿只有一些野草;但那時卻是我的樂園。";
String format = "wav";
int sampleRate = 16000;
String voice = "siyue";
demo.processPOSTRequest(text, format, sampleRate, voice);
}
}
Python示例
Python 2.x請使用httplib模塊;Python 3.x請使用http.client模塊。
如果使用阿里云上海ECS內網訪問URL,請使用HTTP協議,需要替換如下函數,即將
HTTPSConnection
修改為HTTPConnection
。
Python 3.x
import http.client
import urllib.request
import json
import time
class TtsHeader:
def __init__(self, appkey, token):
self.appkey = appKey
self.token = token
def tojson(self, e):
return {'appkey': e.appkey, 'token': e.token}
class TtsContext:
def __init__(self, device_id):
self.device_id = device_id
# 將序列化函數定義到類中。
def tojson(self, e):
return {'device_id': e.device_id}
class TtsRequest:
def __init__(self, voice, sample_rate, format, enable_subtitle, text):
self.voice = voice
self.sample_rate = sample_rate
self.format = format
self.enable_subtitle = enable_subtitle
self.text = text
def tojson(self, e):
return {'voice': e.voice, 'sample_rate': e.sample_rate, 'format': e.format, 'enable_subtitle': e.enable_subtitle, 'text': e.text}
class TtsPayload:
def __init__(self, enable_notify, notify_url, tts_request):
self.enable_notify = enable_notify
self.notify_url = notify_url
self.tts_request = tts_request
def tojson(self, e):
return {'enable_notify': e.enable_notify, 'notify_url': e.notify_url, 'tts_request': e.tts_request.tojson(e.tts_request)}
class TtsBody:
def __init__(self, tts_header, tts_context, tts_payload):
self.tts_header = tts_header
self.tts_context = tts_context
self.tts_payload = tts_payload
def tojson(self, e):
return {'header': e.tts_header.tojson(e.tts_header), 'context': e.tts_context.tojson(e.tts_context), 'payload': e.tts_payload.tojson(e.tts_payload)}
# 根據特定信息輪詢檢查某個請求在服務端的合成狀態(tài),每隔10秒鐘輪詢一次狀態(tài).輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
def waitLoop4Complete(url, appkey, token, task_id, request_id):
# fullUrl = url + "?appkey=" + appkey + "&task_id=" + task_id + "&token=" + token + "&request_id=" + request_id
fullUrl = url + "?appkey=" + appkey + "&task_id=" + \
task_id + "&token=" + token + "&request_id=" + request_id
print("fullUrl=", fullUrl)
host = {"Host": "nls-gateway-cn-shanghai.aliyuncs.com", "Accept": "*/*",
"Connection": "keep-alive", 'Content-Type': 'application/json'}
while True:
result = urllib.request.urlopen(fullUrl).read()
print("query result = ", result)
jsonData = json.loads(result)
# jsonData["data"]["audio_address"] is None表示還在未合成完成的狀態(tài)...每隔10秒鐘輪詢一次狀態(tài)
if (jsonData["data"]["audio_address"] is None):
print(" Tts Queuing...please wait...")
time.sleep(10)
elif "error_code" in jsonData and jsonData["error_code"] == 20000000 and "data" in jsonData and (jsonData["data"]["audio_address"] != ""):
print("Tts Finished! task_id = " + jsonData["data"]["task_id"])
print("Tts Finished! audio_address = " +
jsonData["data"]["audio_address"])
break
else:
print("Tts Running...")
time.sleep(10)
# 長文本語音合成restful接口,支持post調用,不支持get請求。發(fā)出請求后,可以輪詢狀態(tài)或者等待服務端合成后自動回調(如果設置了回調參數)。
def requestLongTts4Post(tts_body, appkey, token):
host = 'nls-gateway.cn-shanghai.aliyuncs.com'
url = 'https://' + host + '/rest/v1/tts/async'
# 設置HTTP Headers
http_headers = {'Content-Type': 'application/json'}
print('The POST request body content: ' + tts_body)
conn = http.client.HTTPSConnection(host)
#conn = httplib.HTTPConnection(host)
conn.request(method='POST', url=url, body=tts_body, headers=http_headers)
response = conn.getresponse()
print('Response status and response reason:')
print(response.status, response.reason)
contentType = response.getheader('Content-Type')
print(contentType)
body = response.read()
if response.status == 200:
jsonData = json.loads(body)
print('The request succeed : ', jsonData)
print('error_code = ', jsonData['error_code'])
task_id = jsonData['data']['task_id']
request_id = jsonData['request_id']
print('task_id = ', task_id)
print('request_id = ', request_id)
# 說明:輪詢檢查服務端的合成狀態(tài),輪詢操作非必須。如果設置了回調url,則服務端會在合成完成后主動回調。
waitLoop4Complete(url, appkey, token, task_id, request_id)
else:
print('The request failed: ' + str(body))
appKey = 'yourAppkey'
token = 'yourToken'
text = '今天是周一,天氣挺好的。'
# 拼接HTTP Post請求的消息體內容。
th = TtsHeader(appKey, token)
tc = TtsContext("mydevice")
# TtsRequest對象內容為:發(fā)音人、采樣率、語音格式、待合成文本內容。
tr = TtsRequest("xiaoyun", 16000, "wav", False, text)
# 是否設置回調url,回調url地址,TtsRequest對象。
tp = TtsPayload(True, "http://134.com", tr)
tb = TtsBody(th, tc, tp)
body = json.dumps(tb, default=tb.tojson)
requestLongTts4Post(str(body), appKey, token)
Python 2.x
# -*- coding: UTF-8 -*-
# Python 2.x
import httplib
import urllib
import urllib2
import json
import time
class TtsHeader:
def __init__(self, appkey, token):
self.appkey = appKey
self.token = token
def tojson(self, e):
return {'appkey': e.appkey, 'token': e.token}
class TtsContext:
def __init__(self, device_id):
self.device_id = device_id
#將序列化函數定義到類中。
def tojson(self, e):
return {'device_id': e.device_id}
class TtsRequest:
def __init__(self, voice, sample_rate, format, enable_subtitle, text):
self.voice = voice
self.sample_rate = sample_rate
self.format = format
self.enable_subtitle = enable_subtitle
self.text = text
def tojson(self, e):
return {'voice': e.voice, 'sample_rate': e.sample_rate, 'format': e.format, 'enable_subtitle': e.enable_subtitle, 'text': e.text}
class TtsPayload:
def __init__(self, enable_notify, notify_url, tts_request):
self.enable_notify = enable_notify
self.notify_url = notify_url
self.tts_request = tts_request
def tojson(self, e):
return {'enable_notify': e.enable_notify, 'notify_url': e.notify_url, 'tts_request': e.tts_request.tojson(e.tts_request)}
class TtsBody:
def __init__(self, tts_header, tts_context, tts_payload):
self.tts_header = tts_header
self.tts_context = tts_context
self.tts_payload = tts_payload
def tojson(self, e):
return {'header': e.tts_header.tojson(e.tts_header), 'context': e.tts_context.tojson(e.tts_context), 'payload': e.tts_payload.tojson(e.tts_payload)}
# 根據特定信息輪詢檢查某個請求在服務端的合成狀態(tài),每隔10秒鐘輪詢一次狀態(tài).輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
def waitLoop4Complete(url, appkey, token, task_id, request_id):
# fullUrl = url + "?appkey=" + appkey + "&task_id=" + task_id + "&token=" + token + "&request_id=" + request_id
fullUrl = url + "?appkey=" + appkey + "&task_id=" + task_id + "&token=" + token + "&request_id=" + request_id
print("fullUrl=", fullUrl)
host = {"Host":"nls-gateway.cn-shanghai.aliyuncs.com", "Accept":"*/*", "Connection":"keep-alive",'Content-Type': 'application/json'}
while True:
req = urllib2.Request(url=fullUrl)
result = urllib2.urlopen(req).read()
print("query result = ", result)
jsonData = json.loads(result)
# jsonData["data"]["audio_address"] is None表示還在未合成完成的狀態(tài)...每隔10秒鐘輪詢一次狀態(tài)
if (jsonData["data"]["audio_address"] is None):
print(" Tts Queuing...please wait...")
time.sleep(10)
elif jsonData.has_key("error_code") and jsonData["error_code"] == 20000000 and jsonData.has_key("data") and (jsonData["data"]["audio_address"] != ""):
print("Tts Finished! task_id = " + jsonData["data"]["task_id"])
print("Tts Finished! audio_address = " + jsonData["data"]["audio_address"])
break
else:
print("Tts Running...")
time.sleep(10)
# 長文本語音合成restful接口,支持post調用,不支持get請求。發(fā)出請求后,可以輪詢狀態(tài)或者等待服務端合成后自動回調(如果設置了回調參數)。
def requestLongTts4Post(tts_body, appkey, token):
host = 'nls-gateway.cn-shanghai.aliyuncs.com'
url = 'https://' + host + '/rest/v1/tts/async'
# 設置HTTP Headers
http_headers = {'Content-Type': 'application/json'}
print('The POST request body content: ' + tts_body)
conn = httplib.HTTPSConnection(host)
#conn = httplib.HTTPConnection(host)
conn.request(method='POST', url=url, body=tts_body, headers=http_headers)
response = conn.getresponse()
print('Response status and response reason:')
print(response.status ,response.reason)
contentType = response.getheader('Content-Type')
print(contentType)
body = response.read()
if response.status == 200:
jsonData = json.loads(body)
print('The request succeed : ', jsonData)
print('error_code = ', jsonData['error_code'])
task_id = jsonData['data']['task_id']
request_id = jsonData['request_id']
print('task_id = ', task_id)
print('request_id = ', request_id)
# 說明:輪詢檢查服務端的合成狀態(tài),輪詢操作非必須。如果設置了回調url,則服務端會在合成完成后主動回調。
waitLoop4Complete(url, appkey, token, task_id, request_id)
else:
print('The request failed: ' + str(body))
appKey = 'yourAppkey'
token = 'yourToken'
text = '今天是周一,天氣挺好的。'
# 拼接HTTP Post請求的消息體內容。
th = TtsHeader(appKey, token)
tc = TtsContext("mydevice")
# TtsRequest對象內容為:發(fā)音人、采樣率、語音格式、待合成文本內容。
tr = TtsRequest("xiaoyun", 16000, "wav", False, text)
# 是否設置回調url,回調url地址,TtsRequest對象。
tp = TtsPayload(True, "http://134.com", tr)
tb = TtsBody(th, tc, tp)
body = json.dumps(tb, default=tb.tojson)
requestLongTts4Post(str(body), appKey, token)
PHP示例
PHP示例中使用了cURL函數,要求PHP的版本為4.0.2以上,并且確保已安裝cURL擴展。
<?php
// 根據特定信息輪詢檢查某個請求在服務端的合成狀態(tài),每隔10秒鐘輪詢一次狀態(tài).輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
function waitLoop4Complete($url, $appkey, $token, $task_id, $request_id) {
$fullUrl = $url . "?appkey=" . $appkey . "&task_id=" . $task_id . "&token=" . $token . "&request_id=" . $request_id;
print "query url = " . $fullUrl . "\n";
while(true) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_URL, $fullUrl);
curl_setopt($curl, CURLOPT_HEADER, TRUE);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
$response = curl_exec($curl);
if ($response == FALSE) {
print "curl_exec failed!\n";
curl_close($curl);
return ;
}
// 處理服務端返回的響應。
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $headerSize);
$bodyContent = substr($response, $headerSize);
print $bodyContent."\n";
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if($http_code != 200) { // 如果請求失敗,需要檢查調用是否正確。
print "tts request failure, error code = " . $http_code . "\n";
curl_close($curl);
return ;
}
curl_close($curl);
$data = json_decode($bodyContent, true);
//$data["data"]["audio_address"]== null時表示還在合成未完成的狀態(tài),需要等待。。。
if(isset($data["error_code"]) && $data["error_code"] == 20000000
&& isset($data["data"]) && $data["data"]["audio_address"]== null){
print "Tts Queuing...please wait..." . "\n";
}
else if(isset($data["error_code"]) && $data["error_code"] == 20000000
&& isset($data["data"]) && $data["data"]["audio_address"] != "") {
print "Tts Finished! task_id = " . $data["data"]["task_id"] . "\n";
print "Tts Finished! audio_address = " . $data["data"]["audio_address"] . "\n";
break;
}
// 每隔10秒鐘輪詢一次狀態(tài)。
sleep(10);
}
}
// 長文本語音合成restful接口,支持post調用,不支持get請求。發(fā)出請求后,可以輪詢狀態(tài)或者等待服務端合成后自動回調(如果設置了回調參數)。
function requestLongTts4Post($appkey, $token, $text, $voice, $format, $sampleRate) {
$url = "https://nls-gateway-cn-shanghai.aliyuncs.com/rest/v1/tts/async";
// 拼接HTTP Post請求的消息體內容。
$header = array("appkey" => $appkey, "token" => $token);
$context = array("device_id" => "my_device_id");
$tts_request = array("text" => $text, "format" => $format, "voice" => $voice, "sample_rate" => $sampleRate, "enable_subtitle" => false);
$payload = array("enable_notify" => true, "notify_url" => "http://123.com", "tts_request" => $tts_request);
$tts_body = array("context" => $context, "header" => $header, "payload" => $payload);
$body = json_encode($tts_body);
print "The POST request body content: " . $body . "\n";
$httpHeaders = array("Content-Type: application/json");
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_HTTPHEADER, $httpHeaders);
curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
curl_setopt($curl, CURLOPT_HEADER, TRUE);
$response = curl_exec($curl);
if ($response == FALSE) {
print "curl_exec failed!\n";
curl_close($curl);
return ;
}
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $headerSize);
$bodyContent = substr($response, $headerSize);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if($http_code != 200) {
print "tts request failure, error code = " . $http_code . "\n";
print "tts request failure, response = " . $bodyContent . "\n";
return ;
}
curl_close($curl);
print $bodyContent . "\n";
$data = json_decode($bodyContent, true);
if( isset($data["error_code"]) && $data["error_code"] == 20000000) {
$task_id = $data["data"]["task_id"];
$request_id = $data["request_id"];
print "Request Success! task_id = " . $task_id . "\n";
print "Request Success! request_id = " . $request_id . "\n";
///說明:輪詢檢查服務端的合成狀態(tài),輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
waitLoop4Complete($url, $appkey, $token, $task_id, $request_id);
} else {
print "Request Error: status=" . $data["status"] . "; error_code=" . $data["error_code"] . "; error_message=" . $data["error_message"] . "\n";
}
}
$appkey = "yourAppkey";
$token = "yourToken";
$text = "今天是周一,天氣挺好的。";
$format = "wav";
$voice = "xiaogang";
$sampleRate = 16000;
requestLongTts4Post($appkey, $token, $text, $voice, $format, $sampleRate);
?>
Node.js示例
首先安裝request依賴,請在您的示例文件所在目錄執(zhí)行如下命令:
npm install request --save
示例代碼如下:
const request = require('request');
const fs = require('fs');
// 長文本語音合成restful接口,支持post調用,不支持get請求。發(fā)出請求后,可以輪詢狀態(tài)或者等待服務端合成后自動回調(如果設置了回調參數)。
function requestLongTts4Post(textValue, appkeyValue, tokenValue, voiceValue, formatValue, sampleRateValue) {
var url = "https://nls-gateway-cn-shanghai.aliyuncs.com/rest/v1/tts/async"
console.log(url);
// 請求參數,以JSON格式字符串填入HTTPS POST請求的Body中。
var context = {
device_id : "device_id",
};
var header = {
appkey : appkeyValue,
token : tokenValue,
};
var tts_request = {
text : textValue,
voice : voiceValue,
format : formatValue,
"sample_rate" : sampleRateValue,
"enable_subtitle" : false
};
var payload = {
"enable_notify" : false,
"notify_url": "http://123.com",
"tts_request" : tts_request,
};
var tts_body = {
"context" : context,
"header" : header,
"payload" : payload
};
var bodyContent = JSON.stringify(tts_body);
console.log('The POST request body content: ' + bodyContent);
// 設置HTTPS POST請求頭部。
var httpHeaders = {'Content-type' : 'application/json'};
// 設置HTTPS POST請求。
// encoding必須設置為null,HTTPS響應的Body為二進制Buffer類型。
var options = {
url: url,
method: 'POST',
headers: httpHeaders,
body: bodyContent,
encoding: null
};
request(options, function (error, response, body) {
// 處理服務端的響應。
if (error != null) {
console.log(error);
} else {
if(response.statusCode != 200) {
console.log("Http Request Fail: " + response.statusCode + "; " + body.toString());
return;
}
console.log("response result: " + body.toString());
var code = 0;
var task_id = "";
var request_id = "";
var json = JSON.parse(body.toString());
console.info(json);
for(var key in json){
if(key=='error_code'){
code = json[key]
} else if(key=='request_id'){
request_id = json[key]
} else if(key == "data") {
task_id = json[key]["task_id"];
}
}
if(code == 20000000) {
console.info("Request Success! task_id = " + task_id);
console.info("Request Success! request_id = " + request_id);
/// 說明:輪詢檢查服務端的合成狀態(tài),輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
waitLoop4Complete(url, appkey, token, task_id, request_id);
} else {
console.info("Request Error: status=" + $data["status"] + "; error_code=" + $data["error_code"] + "; error_message=" + $data["error_message"]);
}
}
});
}
// 根據特定信息輪詢檢查某個請求在服務端的合成狀態(tài),每隔10秒鐘輪詢一次狀態(tài).輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
function waitLoop4Complete(urlValue, appkeyValue, tokenValue, task_id_value, request_id_value) {
var fullUrl = urlValue + "?appkey=" + appkeyValue + "&task_id=" + task_id_value + "&token=" + tokenValue + "&request_id=" + request_id_value;
console.info("query url = " + fullUrl);
//while(true) {
var timer = setInterval(() => {
var options = {
url: fullUrl,
method: 'GET'
};
console.info("query url = " + fullUrl);
request(options, function (error, response, body) {
// 處理服務端的響應。
if (error != null) {
console.log(error);
} else if(response.statusCode != 200) {
console.log("Http Request Fail: " + response.statusCode + "; " + body.toString());
return;
} else {
console.log("query result: " + body.toString());
var code = 0;
var task_id = "";
var output_url = "";
var json = JSON.parse(body.toString());
console.info(json);
for(var key in json){
if(key=='error_code'){
code = json[key]
} else if(key=='request_id'){
request_id = json[key]
} else if(key == "data" && json["data"] != null) {
task_id = json[key]["task_id"];
audio_address = json[key]["audio_address"];
}
}
if(code == 20000000 && audio_address == null) {
console.info("Tts Queuing...please wait...");
}
else if(code == 20000000 && audio_address != "") {
console.info("Tts Finished! task_id = " + task_id);
console.info("Tts Finished! audio_address = " + audio_address);
// 退出輪詢。
clearInterval(timer);
}
}
}
);
}
, 10000);
}
var appkey = 'yourAppkey';
var token = 'yourToken';
var text = '今天是周一,天氣挺好的。';
var voice = "xiaogang";
var format = 'wav';
var sampleRate = 16000;
requestLongTts4Post(text, appkey, token, voice, format, sampleRate);
GO示例
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"time"
)
// 長文本語音合成restful接口,支持post調用,不支持get請求。發(fā)出請求后,可以輪詢狀態(tài)或者等待服務端合成后自動回調(如果設置了回調參數)。
func requestLongTts4Post(text string, appkey string, token string) {
var url string = "https://nls-gateway-cn-shanghai.aliyuncs.com/rest/v1/tts/async"
// 拼接HTTP Post請求的消息體內容。
context := make(map[string]interface{})
context["device_id"] = "test-device"
header := make(map[string]interface{})
header["appkey"] = appkey
header["token"] = token
tts_request := make(map[string]interface{})
tts_request["text"] = text
tts_request["format"] = "wav"
tts_request["voice"] = "xiaogang"
tts_request["sample_rate"] = 16000
tts_request["enable_subtitle"] = false
payload := make(map[string]interface{})
payload["enable_notify"] = false
payload["notify_url"] = "http://123.com"
payload["tts_request"] = tts_request
ttsBody := make(map[string]interface{})
ttsBody["context"] = context
ttsBody["header"] = header
ttsBody["payload"] = payload
ttsBodyJson, err := json.Marshal(ttsBody)
if err != nil {
panic(nil)
}
fmt.Println(string(ttsBodyJson))
// 發(fā)送HTTPS POST請求,處理服務端的響應。
response, err := http.Post(url, "application/json;charset=utf-8", bytes.NewBuffer([]byte(ttsBodyJson)))
if err != nil {
panic(err)
}
defer response.Body.Close()
contentType := response.Header.Get("Content-Type")
body, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(contentType))
fmt.Println(string(body))
statusCode := response.StatusCode
if statusCode == 200 {
fmt.Println("The POST request succeed!")
var f interface{}
err := json.Unmarshal(body, &f)
if err != nil {
fmt.Println(err)
}
// 從消息體中解析出來task_id(重要)和request_id。
var taskId string = ""
var requestId string = ""
m := f.(map[string]interface{})
for k, v := range m {
if k == "error_code" {
fmt.Println("error_code = ", v)
} else if k == "request_id" {
fmt.Println("request_id = ", v)
requestId = v.(string)
} else if k == "data" {
fmt.Println("data = ", v)
data := v.(map[string]interface{})
fmt.Println(data)
taskId = data["task_id"].(string)
}
}
// 說明:輪詢檢查服務端的合成狀態(tài),輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
waitLoop4Complete(url, appkey, token, taskId, requestId)
} else {
fmt.Println("The POST request failed: " + string(body))
fmt.Println("The HTTP statusCode: " + strconv.Itoa(statusCode))
}
}
// 根據特定信息輪詢檢查某個請求在服務端的合成狀態(tài),每隔10秒鐘輪詢一次狀態(tài).輪詢操作非必須,如果設置了回調url,則服務端會在合成完成后主動回調。
func waitLoop4Complete(url string, appkey string, token string, task_id string, request_id string) {
var fullUrl string = url + "?appkey=" + appkey + "&task_id=" + task_id + "&token=" + token + "&request_id=" + request_id
fmt.Println("fullUrl=" + fullUrl)
for {
response, err := http.Get(fullUrl)
if err != nil {
fmt.Println("The GET request failed!")
panic(err)
}
defer response.Body.Close()
body, _ := ioutil.ReadAll(response.Body)
fmt.Println("waitLoop4Complete = ", string(body))
var f interface{}
json.Unmarshal(body, &f)
if err != nil {
fmt.Println(err)
}
// 從消息體中解析出來task_id(重要)和request_id。
var code float64 = 0
var taskId string = ""
var audioAddress string = ""
m := f.(map[string]interface{})
for k, v := range m {
if k == "error_code" {
code = v.(float64)
} else if k == "request_id" {
} else if k == "data" {
if v != nil {
data := v.(map[string]interface{})
taskId = data["task_id"].(string)
if data["audio_address"] == nil {
fmt.Println("Tts Queuing...,please wait...")
} else {
audioAddress = data["audio_address"].(string)
}
}
}
}
if code == 20000000 && audioAddress != "" {
fmt.Println("Tts Finished! task_id = " + taskId)
fmt.Println("Tts Finished! audio_address = " + audioAddress)
break
} else {
// 每隔10秒鐘輪詢一次狀態(tài)
time.Sleep(time.Duration(10) * time.Second)
}
}
}
func main() {
var appkey string = "yourAppkey"
var token string = "yourToken"
var text string = "今天是周一,天氣挺好的。"
requestLongTts4Post(text, appkey, token)
}