全部产品
云市场

RESTful API 2.0

更新时间:2019-12-06 11:15:38

功能介绍

长文本语音合成RESTful API支持HTTP/HTTPS POST方式的请求,将待合成的文本通过HTTP POST上传到服务端,服务端返回文本的语音合成结果。

  • 支持设置合成音频的格式:pcm,wav,mp3;
  • 支持设置合成音频的采样率:8000Hz、16000Hz;
  • 支持设置多种发音人;
  • 支持设置语速、语调、音量;
  • 支持两种数据获取方式:轮询方式和回调方式;

重要提示

  • 随着TTS合成效果的不断提升,算法的复杂度也越来越高,对用户而言,可能会遇到合成耗时变长的可能。因此我们建议您使用流式合成机制。本文档及SDK附带Demo示例中有相关流式处理示例代码可做参考;

  • 新增RESTful长文本语音合成Java示例代码源码下载地址链接

服务地址

访问类型 说明 URL Host
外网访问 所有服务器均可使用外网访问URL https://nls-gateway.cn-shanghai.aliyuncs.com/rest/v1/tts/async nls-gateway.cn-shanghai.aliyuncs.com
阿里云上海ECS内网访问 您使用阿里云上海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。以下Demo中除了Python,均直接支持HTTP和HTTPS协议,Python Demo请在使用时阅读其注意事项。

交互流程

客户端向服务端发送带有文本内容的HTTPS POST方法的请求,服务端返回对应的处理,此后客户端有两种处理方式:一是主动轮询合成状态,直至合成完成;二是等待服务端完成语音合成全部完成之后主动回调用户设置的回调地址,此时用户端程序可以继续进行后续处理。

需要说明的是,不同于原语音合成的RESTful接口,长文本语音合成RESTful接口并不会把实际的合成数据直接返回给客户端,而是返回了一个http地址的录音合成文件,用户可以通过该http地址下载录音文件或者直接播放。

提示:服务端的错误响应都会在返回信息中包含task_id参数,用于表示本次合成任务的ID,请记录下这个值,如果发生错误,请将task_id和错误信息提交到工单。

请求参数

长文本语音合成需要设置的主要请求参数如下表所示。在请求时需要将这些参数设置到HTTPS/HTTP的请求体(Body)中。

名称 类型 是否必需 描述
appkey String 应用appkey(获取方法请阅读创建项目一节)
token String 服务鉴权Token,获取方法请阅读获取访问令牌一节。
text String 待合成的文本,需要为UTF-8编码。
format String 音频编码格式,支持的格式:pcm、wav、mp3,默认是pcm
sample_rate Integer 音频采样率,支持16000Hz、8000Hz,默认是16000Hz
voice String 发音人,默认是xiaoyun,其他发音人名称请在简介中选择
volume Integer 音量,范围是0~100,默认50
speech_rate Integer 语速,范围是-500~500,默认是0
pitch_rate Integer 语调,范围是-500~500,可选,默认是0
enable_notify Boolean 是否启用回调功能,默认值为false
notify_url String 回调服务的地址,enable_notify=true时,本字段必填,url支持HTTP和HTTPS协议,host不能使用IP地址

POST方法上传文本

一个完整的语音合成RESTful API POST请求包含以下要素:

URL

协议 URL 方法
HTTPS https://nls-gateway.cn-shanghai.aliyuncs.com/rest/v1/tts/async POST

HTTPS POST 请求体

POST请求体传入的是请求参数组成的JSON格式的字符串,因此在POST请求头部中的Content-Type必须设置为”application/json”。示例如下:

  1. {
  2. "payload":{
  3. "tts_request":{
  4. "voice":"xiaoyun",
  5. "sample_rate":16000,
  6. "format":"wav",
  7. "text":"今天天气好晴朗"
  8. },
  9. "enable_notify":false
  10. },
  11. "context":{
  12. "device_id":"my_device_id"
  13. },
  14. "header":{
  15. "appkey":"你的appkey",
  16. "token":"你的token"
  17. }
  18. }

响应结果

发送请求后,不论是调用成功还是失败,服务端的响应消息都会通过HTTP的消息体返回给客户端,请仔细处理返回数据。使用HTTPS GET方法和使用HTTPS POST方法请求的响应是相同的,响应的结果都包含在HTTPS的Body中。响应结果的成功或失败通过HTTPS Header的Content-Type字段来区分:

  • 成功响应

    • HTTPS Headers的Content-Type字段内容为audio/mpeg,表示合成成功,合成的语音数据在Body中。
    • HTTPS Header的X-NLS-RequestId字段内容为请求任务的task_id,方便调试排查。
    • Body内容为合成音频的二进制数据。
  • 失败响应

    • HTTPS Headers没有Content-Type字段,或者Content-Type字段内容为application/json,表示合成失败,错误信息在Body中。
    • HTTPS Header的X-NLS-RequestId字段内容为请求任务的task_id,方便调试排查。
    • Body内容为错误信息,JSON格式的字符串。如下所示:
  • 发起请求后的成功响应
    1. {
    2. "status":200,
    3. "error_code":20000000,
    4. "error_message":"SUCCESS",
    5. "request_id":"f0a9e2c49e9049e78730a3bf0b32b071",
    6. "data":{
    7. "task_id":"35d9f813e00b11e9a2ce9ba0d6a288dd"
    8. }
    9. }
  • 发起请求后的失败响应
    1. {
    2. "error_message":"Meta:ACCESS_DENIED:The token 'fdf' is invalid!",
    3. "error_code":40000001,
    4. "request_id":"0d8c0eea55824aada9a374aec650b18a",
    5. "url":"/rest/v1/tts/async",
    6. "status":400
    7. }
  • 轮询服务端合成状态的成功响应
  1. /// 轮询时服务端返回的中间状态
  2. {
  3. "status":200,
  4. "error_code":20000000,
  5. "error_message":"RUNNING",
  6. "request_id":"a3370c49a29148e78b39978f98bab284",
  7. "data":{
  8. "task_id":"35d9f813e00b11e9a2ce9ba0d6a288dd",
  9. "audio_address":null,
  10. "notify_custom":null
  11. }
  12. }
  13. /// 获取到最终合成结果
  14. {
  15. "status":200,
  16. "error_code":20000000,
  17. "error_message":"SUCCESS",
  18. "request_id":"711db7b6e4b04563a6993daf66bdc878",
  19. "data":{
  20. "task_id":"35d9f813e00b11e9a2ce9ba0d6a288dd",
  21. "audio_address":"http://tts-custom.oss-cn-shanghai.aliyuncs.com/personal/daily/MvRSYf80dv49pMWL/my_device_id/35d9f813e00b11e9a2ce9ba0d6a288dd.wav?Expires=1570072241&OSSAccessKeyId=LTAINfQ1jtEEAbFd&Signature=tGuD%2BathysLcpqSfu0G%2FjW%2Ftsvs%3D",
  22. "notify_custom":""
  23. }
  24. }

提示:audio_address字段对应的http下载地址有期限最多只有3天。

响应字段

失败响应时的错误信息字段如下表所示:

名称 类型 描述
task_id String 32位请求任务ID,请记录该值,用于排查错误
error_code Integer 服务状态码
error_message String 服务状态描述

服务状态码

服务状态码 服务状态描述 解决办法
20000000 请求成功
40000000 默认的客户端错误码 查看错误消息或提交工单
40000001 身份认证失败 检查使用的令牌是否正确,是否过期
40000002 无效的消息 检查发送的消息是否符合要求
40000003 无效的参数 检查参数值设置是否合理
40000004 空闲超时 确认是否长时间没有发送数据掉服务端
40000005 请求数量过多 检查是否超过了并发连接数或者每秒钟请求数
50000000 默认的服务端错误 如果偶现可以忽略,重复出现请提交工单
50000001 内部GRPC调用错误 如果偶现可以忽略,重复出现请提交工单

Java Demo

添加依赖:

  1. <dependency>
  2. <groupId>com.squareup.okhttp3</groupId>
  3. <artifactId>okhttp</artifactId>
  4. <version>3.9.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.alibaba</groupId>
  8. <artifactId>fastjson</artifactId>
  9. <version>1.2.49</version>
  10. </dependency>
  1. package com.alibaba.nls.client;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import okhttp3.MediaType;
  5. import okhttp3.OkHttpClient;
  6. import okhttp3.Request;
  7. import okhttp3.RequestBody;
  8. import okhttp3.Response;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11. /**
  12. * 此示例演示了长文本语音合成的使用方式
  13. */
  14. public class SpeechLongSynthesizerRestfulDemo {
  15. private static Logger logger = LoggerFactory.getLogger(SpeechLongSynthesizerRestfulDemo.class);
  16. private String accessToken;
  17. private String appkey;
  18. public SpeechLongSynthesizerRestfulDemo(String appkey, String token) {
  19. this.appkey = appkey;
  20. this.accessToken = token;
  21. }
  22. public void processPOSTRequest(String text, String format, int sampleRate, String voice) {
  23. String url = "https://nls-gateway.cn-shanghai.aliyuncs.com/rest/v1/tts/async";
  24. // 拼接Http Post请求的消息体内容
  25. JSONObject context = new JSONObject();
  26. // device_id设置,可以设置为自定义字符串或者设备信息id
  27. context.put("device_id", "my_device_id");
  28. JSONObject header = new JSONObject();
  29. // 必选:设置你的appkey
  30. header.put("appkey", appkey);
  31. // 必选:设置你的token
  32. header.put("token", accessToken);
  33. // voice 发音人,可选,默认是xiaoyun
  34. // volume 音量,范围是0~100,可选,默认50
  35. // speech_rate 语速,范围是-500~500,可选,默认是0
  36. // pitch_rate 语调,范围是-500~500,可选,默认是0
  37. JSONObject tts = new JSONObject();
  38. tts.put("text", text);
  39. // 设置发音人
  40. tts.put("voice", voice);
  41. // 设置编码格式
  42. tts.put("format", format);
  43. // 设置采样率
  44. tts.put("sample_rate", sampleRate);
  45. // 设置声音大小,可选
  46. //tts.put("volume", 100);
  47. // 设置语速,可选
  48. //tts.put("speech_rate", 200);
  49. JSONObject payload = new JSONObject();
  50. // 可选,是否设置回调,如果设置,则服务端在完成长文本语音合成之后回调用用户此处设置的回调接口,将请求状态推送给用户侧
  51. payload.put("enable_notify", false);
  52. payload.put("notify_url", "http://123.com");
  53. payload.put("tts_request", tts);
  54. JSONObject json = new JSONObject();
  55. json.put("context", context);
  56. json.put("header", header);
  57. json.put("payload", payload);
  58. String bodyContent = json.toJSONString();
  59. logger.info("POST Body Content: " + bodyContent);
  60. // 发起请求
  61. RequestBody reqBody = RequestBody.create(MediaType.parse("application/json"), bodyContent);
  62. Request request = new Request.Builder()
  63. .url(url)
  64. .header("Content-Type", "application/json")
  65. .post(reqBody)
  66. .build();
  67. try {
  68. OkHttpClient client = new OkHttpClient();
  69. Response response = client.newCall(request).execute();
  70. String contentType = response.header("Content-Type");
  71. System.out.println("contentType = " + contentType);
  72. // 获取结果,并根据返回进一步进行处理
  73. String result = response.body().string();
  74. response.close();
  75. System.out.println("result = " + result);
  76. JSONObject resultJson = JSON.parseObject(result);
  77. if(resultJson.containsKey("error_code") && resultJson.getIntValue("error_code") == 20000000) {
  78. logger.info("Request Success! task_id = " + resultJson.getJSONObject("data").getString("task_id"));
  79. String task_id = resultJson.getJSONObject("data").getString("task_id");
  80. String request_id = resultJson.getString("request_id");
  81. /// 可选:轮询检查服务端的合成状态,该轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  82. waitLoop4Complete(url, appkey, accessToken, task_id, request_id);
  83. }else {
  84. logger.error("Request Error: status=" + resultJson.getIntValue("status")
  85. + ", error_code=" + resultJson.getIntValue("error_code")
  86. + ", error_message=" + resultJson.getString("error_message"));
  87. }
  88. } catch (Exception e) {
  89. e.printStackTrace();
  90. }
  91. }
  92. /// 根据特定信息轮询检查某个请求在服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  93. private void waitLoop4Complete(String url, String appkey, String token, String task_id, String request_id) {
  94. String fullUrl = url + "?appkey=" + appkey + "&task_id=" + task_id + "&token=" + token + "&request_id=" + request_id;
  95. System.out.println("query url = " + fullUrl);
  96. while(true) {
  97. Request request = new Request.Builder().url(fullUrl).get().build();
  98. try {
  99. OkHttpClient client = new OkHttpClient();
  100. Response response = client.newCall(request).execute();
  101. String result = response.body().string();
  102. response.close();
  103. System.out.println("waitLoop4Complete = " + result);
  104. JSONObject resultJson = JSON.parseObject(result);
  105. if(resultJson.containsKey("error_code")
  106. && resultJson.getIntValue("error_code") == 20000000
  107. && resultJson.containsKey("data")
  108. && resultJson.getJSONObject("data").getString("audio_address") != null) {
  109. logger.info("Tts Finished! task_id = " + resultJson.getJSONObject("data").getString("task_id"));
  110. logger.info("Tts Finished! audio_address = " + resultJson.getJSONObject("data").getString("audio_address"));
  111. break;
  112. }else {
  113. logger.info("Tts Queuing...");
  114. }
  115. // 每隔3秒钟轮询一次状态
  116. Thread.sleep(3000);
  117. } catch (Exception e) {
  118. e.printStackTrace();
  119. }
  120. }
  121. }
  122. public static void main(String[] args) {
  123. if (args.length < 2) {
  124. System.err.println("SpeechLongSynthesizerRestfulDemo need params: <token> <app-key>");
  125. System.exit(-1);
  126. }
  127. String token = args[0];
  128. String appkey = args[1];
  129. SpeechLongSynthesizerRestfulDemo demo = new SpeechLongSynthesizerRestfulDemo(appkey, token);
  130. String text = "我家的后面有一个很大的园,相传叫作百草园。现在是早已并屋子一起卖给朱文公的子孙了,连那最末次的相见也已经隔了七八年,其中似乎确凿只有一些野草;但那时却是我的乐园。";
  131. String format = "wav";
  132. int sampleRate = 16000;
  133. String voice = "siyue";
  134. demo.processPOSTRequest(text, format, sampleRate, voice);
  135. }
  136. }

Python Demo

注意:

  • Python 2.x请使用httplib模块;Python 3.x请使用http.client模块。
  • 如果使用阿里云上海ECS内网访问URL,使用HTTP协议,需要替换如下函数,即将HTTPSConnection修改为HTTPConnection :
  1. # -*- coding: UTF-8 -*-
  2. # Python 2.x
  3. import httplib
  4. import urllib
  5. import urllib2
  6. import json
  7. import time
  8. class TtsHeader:
  9. def __init__(self, appkey, token):
  10. self.appkey = appKey
  11. self.token = token
  12. def tojson(self, e):
  13. return {'appkey': e.appkey, 'token': e.token}
  14. class TtsContext:
  15. def __init__(self, device_id):
  16. self.device_id = device_id
  17. #将序列化函数定义到类中
  18. def tojson(self, e):
  19. return {'device_id': e.device_id}
  20. class TtsRequest:
  21. def __init__(self, voice, sample_rate, format, enable_subtitle, text):
  22. self.voice = voice
  23. self.sample_rate = sample_rate
  24. self.format = format
  25. self.enable_subtitle = enable_subtitle
  26. self.text = text
  27. def tojson(self, e):
  28. return {'voice': e.voice, 'sample_rate': e.sample_rate, 'format': e.format, 'enable_subtitle': e.enable_subtitle, 'text': e.text}
  29. class TtsPayload:
  30. def __init__(self, enable_notify, notify_url, tts_request):
  31. self.enable_notify = enable_notify
  32. self.notify_url = notify_url
  33. self.tts_request = tts_request
  34. def tojson(self, e):
  35. return {'enable_notify': e.enable_notify, 'notify_url': e.notify_url, 'tts_request': e.tts_request.tojson(e.tts_request)}
  36. class TtsBody:
  37. def __init__(self, tts_header, tts_context, tts_payload):
  38. self.tts_header = tts_header
  39. self.tts_context = tts_context
  40. self.tts_payload = tts_payload
  41. def tojson(self, e):
  42. 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)}
  43. # 根据特定信息轮询检查某个请求在服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  44. def waitLoop4Complete(url, appkey, token, task_id, request_id):
  45. fullUrl = url + "?appkey=" + appkey + "&task_id=" + task_id + "&token=" + token + "&request_id=" + request_id
  46. print "fullUrl=", fullUrl
  47. host = {"Host":"nls-gateway.cn-shanghai.aliyuncs.com", "Accept":"*/*", "Connection":"keep-alive",'Content-Type': 'application/json'}
  48. while True:
  49. req = urllib2.Request(url=fullUrl)
  50. result = urllib2.urlopen(req).read()
  51. print "query result = ", result
  52. jsonData = json.loads(result)
  53. if jsonData.has_key("error_code") and jsonData["error_code"] == 20000000 and jsonData.has_key("data") and (jsonData["data"]["audio_address"] != ""):
  54. print "Tts Finished! task_id = " + jsonData["data"]["task_id"]
  55. print "Tts Finished! audio_address = " + jsonData["data"]["audio_address"]
  56. break
  57. else:
  58. print "Tts Running..."
  59. time.sleep(3)
  60. # 长文本语音合成restful接口,支持post调用,不支持get请求,发出请求后,可以轮询状态或者等待服务端合成后自动回调(如果设置了回调参数)
  61. def requestLongTts4Post(tts_body, appkey, token):
  62. host = 'nls-gateway.cn-shanghai.aliyuncs.com'
  63. url = 'https://' + host + '/rest/v1/tts/async'
  64. # 设置HTTP Headers
  65. http_headers = {'Content-Type': 'application/json'}
  66. print('The POST request body content: ' + tts_body)
  67. conn = httplib.HTTPSConnection(host)
  68. #conn = httplib.HTTPConnection(host)
  69. conn.request(method='POST', url=url, body=tts_body, headers=http_headers)
  70. response = conn.getresponse()
  71. print('Response status and response reason:')
  72. print(response.status ,response.reason)
  73. contentType = response.getheader('Content-Type')
  74. print(contentType)
  75. body = response.read()
  76. if response.status == 200:
  77. jsonData = json.loads(body)
  78. print 'The request succeed : ', jsonData
  79. print 'error_code = ', jsonData['error_code']
  80. task_id = jsonData['data']['task_id']
  81. request_id = jsonData['request_id']
  82. print 'task_id = ', task_id
  83. print 'request_id = ', request_id
  84. # 说明:轮询检查服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  85. waitLoop4Complete(url, appkey, token, task_id, request_id)
  86. else:
  87. print('The request failed: ' + str(body))
  88. appKey = '填写你的appkey'
  89. token = '填写你的token'
  90. text = '今天是周一,天气挺好的。'
  91. # 拼接Http Post请求的消息体内容
  92. th = TtsHeader(appKey, token)
  93. tc = TtsContext("mydevice")
  94. # 发音人, 采样率, 语音格式, 待合成文本内容
  95. tr = TtsRequest("xiaoyun", 16000, "wav", False, text)
  96. # 是否设置回调url, 回调url地址,TtsRequest对象
  97. tp = TtsPayload(True, "http://134.com", tr)
  98. tb = TtsBody(th, tc, tp)
  99. body = json.dumps(tb, default=tb.tojson)
  100. requestLongTts4Post(str(body), appKey, token)

PHP Demo

说明:PHP Demo中使用了cURL函数,要求PHP的版本在4.0.2以上,并且确保安装了cURL扩展。

  1. <?php
  2. // 根据特定信息轮询检查某个请求在服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  3. function waitLoop4Complete($url, $appkey, $token, $task_id, $request_id) {
  4. $fullUrl = $url . "?appkey=" . $appkey . "&task_id=" . $task_id . "&token=" . $token . "&request_id=" . $request_id;
  5. print "query url = " . $fullUrl . "\n";
  6. while(true) {
  7. $curl = curl_init();
  8. curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
  9. curl_setopt($curl, CURLOPT_URL, $fullUrl);
  10. curl_setopt($curl, CURLOPT_HEADER, TRUE);
  11. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
  12. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
  13. $response = curl_exec($curl);
  14. if ($response == FALSE) {
  15. print "curl_exec failed!\n";
  16. curl_close($curl);
  17. return ;
  18. }
  19. // 处理服务端返回的响应
  20. $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
  21. $headers = substr($response, 0, $headerSize);
  22. $bodyContent = substr($response, $headerSize);
  23. print $bodyContent."\n";
  24. $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
  25. if($http_code != 200) { // 如果请求失败,需要检查调用是否正确
  26. print "tts request failure, error code = " . $http_code . "\n";
  27. curl_close($curl);
  28. return ;
  29. }
  30. curl_close($curl);
  31. $data = json_decode($bodyContent, true);
  32. if(isset($data["error_code"]) && $data["error_code"] == 20000000
  33. && isset($data["data"]) && $data["data"]["audio_address"] != "") {
  34. print "Tts Finished! task_id = " . $data["data"]["task_id"] . "\n";
  35. print "Tts Finished! audio_address = " . $data["data"]["audio_address"] . "\n";
  36. break;
  37. } else {
  38. print "Tts Queuing..." . "\n";
  39. }
  40. // 每隔3秒钟轮询一次状态
  41. sleep(3);
  42. }
  43. }
  44. // 长文本语音合成restful接口,支持post调用,不支持get请求,发出请求后,可以轮询状态或者等待服务端合成后自动回调(如果设置了回调参数)
  45. function requestLongTts4Post($appkey, $token, $text, $voice, $format, $sampleRate) {
  46. $url = "https://nls-gateway.cn-shanghai.aliyuncs.com/rest/v1/tts/async";
  47. // 拼接Http Post请求的消息体内容
  48. $header = array("appkey" => $appkey, "token" => $token);
  49. $context = array("device_id" => "my_device_id");
  50. $tts_request = array("text" => $text, "format" => $format, "voice" => $voice, "sample_rate" => $sampleRate, "enable_subtitle" => false);
  51. $payload = array("enable_notify" => true, "notify_url" => "http://123.com", "tts_request" => $tts_request);
  52. $tts_body = array("context" => $context, "header" => $header, "payload" => $payload);
  53. $body = json_encode($tts_body);
  54. print "The POST request body content: " . $body . "\n";
  55. $httpHeaders = array("Content-Type: application/json");
  56. $curl = curl_init();
  57. curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
  58. curl_setopt($curl, CURLOPT_URL, $url);
  59. curl_setopt($curl, CURLOPT_POST, TRUE);
  60. curl_setopt($curl, CURLOPT_HTTPHEADER, $httpHeaders);
  61. curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
  62. curl_setopt($curl, CURLOPT_HEADER, TRUE);
  63. $response = curl_exec($curl);
  64. if ($response == FALSE) {
  65. print "curl_exec failed!\n";
  66. curl_close($curl);
  67. return ;
  68. }
  69. $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
  70. $headers = substr($response, 0, $headerSize);
  71. $bodyContent = substr($response, $headerSize);
  72. $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
  73. if($http_code != 200) {
  74. print "tts request failure, error code = " . $http_code . "\n";
  75. print "tts request failure, response = " . $bodyContent . "\n";
  76. return ;
  77. }
  78. curl_close($curl);
  79. print $bodyContent . "\n";
  80. $data = json_decode($bodyContent, true);
  81. if( isset($data["error_code"]) && $data["error_code"] == 20000000) {
  82. $task_id = $data["data"]["task_id"];
  83. $request_id = $data["request_id"];
  84. print "Request Success! task_id = " . $task_id . "\n";
  85. print "Request Success! request_id = " . $request_id . "\n";
  86. /// 说明:轮询检查服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  87. waitLoop4Complete($url, $appkey, $token, $task_id, $request_id);
  88. } else {
  89. print "Request Error: status=" . $data["status"] . "; error_code=" . $data["error_code"] . "; error_message=" . $data["error_message"] . "\n";
  90. }
  91. }
  92. $appkey = "填写你的appkey";
  93. $token = "填写你的token";
  94. $text = "今天是周一,天气挺好的。";
  95. $format = "wav";
  96. $voice = "xiaogang";
  97. $sampleRate = 16000;
  98. requestLongTts4Post($appkey, $token, $text, $voice, $format, $sampleRate);
  99. ?>

Node.js Demo

说明:request依赖安装,请在您的Demo文件所在目录执行如下命令:

  1. npm install request --save

示例代码:

  1. const request = require('request');
  2. const fs = require('fs');
  3. // 长文本语音合成restful接口,支持post调用,不支持get请求,发出请求后,可以轮询状态或者等待服务端合成后自动回调(如果设置了回调参数)
  4. function requestLongTts4Post(textValue, appkeyValue, tokenValue, voiceValue, formatValue, sampleRateValue) {
  5. var url = "https://nls-gateway.cn-shanghai.aliyuncs.com/rest/v1/tts/async"
  6. console.log(url);
  7. // 请求参数,以JSON格式字符串填入HTTPS POST 请求的Body中
  8. var context = {
  9. device_id : "device_id",
  10. };
  11. var header = {
  12. appkey : appkeyValue,
  13. token : tokenValue,
  14. };
  15. var tts_request = {
  16. text : textValue,
  17. voice : voiceValue,
  18. format : formatValue,
  19. "sample_rate" : sampleRateValue,
  20. "enable_subtitle" : false
  21. };
  22. var payload = {
  23. "enable_notify" : false,
  24. "notify_url": "http://123.com",
  25. "tts_request" : tts_request,
  26. };
  27. var tts_body = {
  28. "context" : context,
  29. "header" : header,
  30. "payload" : payload
  31. };
  32. var bodyContent = JSON.stringify(tts_body);
  33. console.log('The POST request body content: ' + bodyContent);
  34. // 设置HTTPS POST请求头部
  35. var httpHeaders = {'Content-type' : 'application/json'};
  36. // 设置HTTPS POST请求
  37. // encoding必须设置为null,HTTPS响应的Body为二进制Buffer类型
  38. var options = {
  39. url: url,
  40. method: 'POST',
  41. headers: httpHeaders,
  42. body: bodyContent,
  43. encoding: null
  44. };
  45. request(options, function (error, response, body) {
  46. // 处理服务端的响应
  47. if (error != null) {
  48. console.log(error);
  49. } else {
  50. if(response.statusCode != 200) {
  51. console.log("Http Request Fail: " + response.statusCode + "; " + body.toString());
  52. return;
  53. }
  54. console.log("response result: " + body.toString());
  55. var code = 0;
  56. var task_id = "";
  57. var request_id = "";
  58. var json = JSON.parse(body.toString());
  59. console.info(json);
  60. for(var key in json){
  61. if(key=='error_code'){
  62. code = json[key]
  63. } else if(key=='request_id'){
  64. request_id = json[key]
  65. } else if(key == "data") {
  66. task_id = json[key]["task_id"];
  67. }
  68. }
  69. if(code == 20000000) {
  70. console.info("Request Success! task_id = " + task_id);
  71. console.info("Request Success! request_id = " + request_id);
  72. /// 说明:轮询检查服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  73. waitLoop4Complete(url, appkey, token, task_id, request_id);
  74. } else {
  75. console.info("Request Error: status=" + $data["status"] + "; error_code=" + $data["error_code"] + "; error_message=" + $data["error_message"]);
  76. }
  77. }
  78. });
  79. }
  80. // 根据特定信息轮询检查某个请求在服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  81. function waitLoop4Complete(urlValue, appkeyValue, tokenValue, task_id_value, request_id_value) {
  82. var fullUrl = urlValue + "?appkey=" + appkeyValue + "&task_id=" + task_id_value + "&token=" + tokenValue + "&request_id=" + request_id_value;
  83. console.info("query url = " + fullUrl);
  84. //while(true) {
  85. var timer = setInterval(() => {
  86. var options = {
  87. url: fullUrl,
  88. method: 'GET'
  89. };
  90. console.info("query url = " + fullUrl);
  91. request(options, function (error, response, body) {
  92. // 处理服务端的响应
  93. if (error != null) {
  94. console.log(error);
  95. } else if(response.statusCode != 200) {
  96. console.log("Http Request Fail: " + response.statusCode + "; " + body.toString());
  97. return;
  98. } else {
  99. console.log("query result: " + body.toString());
  100. var code = 0;
  101. var task_id = "";
  102. var output_url = "";
  103. var json = JSON.parse(body.toString());
  104. console.info(json);
  105. for(var key in json){
  106. if(key=='error_code'){
  107. code = json[key]
  108. } else if(key=='request_id'){
  109. request_id = json[key]
  110. } else if(key == "data" && json["data"] != null) {
  111. task_id = json[key]["task_id"];
  112. audio_address = json[key]["audio_address"];
  113. }
  114. }
  115. if(code == 20000000 && audio_address != "") {
  116. console.info("Tts Finished! task_id = " + task_id);
  117. console.info("Tts Finished! audio_address = " + audio_address);
  118. // 退出轮询
  119. clearInterval(timer);
  120. } else {
  121. console.info("Tts Queuing...");
  122. }
  123. }
  124. }
  125. );
  126. }
  127. , 3000);
  128. }
  129. var appkey = '填写你的appkey';
  130. var token = '填写你的token';
  131. var text = '今天是周一,天气挺好的。';
  132. var voice = "xiaogang";
  133. var format = 'wav';
  134. var sampleRate = 16000;
  135. requestLongTts4Post(text, appkey, token, voice, format, sampleRate);

Go Demo

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. "io/ioutil"
  6. "encoding/json"
  7. "strconv"
  8. "bytes"
  9. "time"
  10. )
  11. // 长文本语音合成restful接口,支持post调用,不支持get请求,发出请求后,可以轮询状态或者等待服务端合成后自动回调(如果设置了回调参数)
  12. func requestLongTts4Post(text string, appkey string, token string) {
  13. // var url string= "http://pre-nls-gateway.aliyuncs.com:80/rest/v1/tts/async"
  14. var url string= "https://nls-gateway.cn-shanghai.aliyuncs.com/rest/v1/tts/async"
  15. // 拼接Http Post请求的消息体内容
  16. context := make(map[string]interface{})
  17. context["device_id"] = "test-device"
  18. header := make(map[string]interface{})
  19. header["appkey"] = appkey
  20. header["token"] = token
  21. tts_request := make(map[string]interface{})
  22. tts_request["text"] = text
  23. tts_request["format"] = "wav"
  24. tts_request["voice"] = "xiaogang"
  25. tts_request["sample_rate"] = 16000
  26. tts_request["enable_subtitle"] = false
  27. payload := make(map[string]interface{})
  28. payload["enable_notify"] = false
  29. payload["notify_url"] = "http://123.com"
  30. payload["tts_request"] = tts_request
  31. ttsBody := make(map[string]interface{})
  32. ttsBody["context"] = context
  33. ttsBody["header"] = header
  34. ttsBody["payload"] = payload
  35. ttsBodyJson, err := json.Marshal(ttsBody)
  36. if err != nil {
  37. panic(nil)
  38. }
  39. fmt.Println(string(ttsBodyJson))
  40. // 发送HTTPS POST请求,处理服务端的响应
  41. response, err := http.Post(url, "application/json;charset=utf-8", bytes.NewBuffer([]byte(ttsBodyJson)))
  42. if err != nil {
  43. panic(err)
  44. }
  45. defer response.Body.Close()
  46. contentType := response.Header.Get("Content-Type")
  47. body, _ := ioutil.ReadAll(response.Body)
  48. fmt.Println(string(contentType))
  49. fmt.Println(string(body))
  50. statusCode := response.StatusCode
  51. if(statusCode == 200) {
  52. fmt.Println("The POST request succeed!")
  53. var f interface{}
  54. err := json.Unmarshal(body, &f)
  55. if err != nil {
  56. fmt.Println(err)
  57. }
  58. // 从消息体中解析出来task_id(重要)和request_id
  59. var taskId string = ""
  60. var requestId string = ""
  61. m := f.(map[string]interface{})
  62. for k, v := range m {
  63. if(k == "error_code") {
  64. fmt.Println("error_code = ", v)
  65. } else if(k == "request_id") {
  66. fmt.Println("request_id = ", v)
  67. requestId = v.(string)
  68. } else if(k == "data") {
  69. fmt.Println("data = ", v)
  70. data := v.(map[string]interface{})
  71. fmt.Println(data)
  72. taskId = data["task_id"].(string)
  73. }
  74. }
  75. // 说明:轮询检查服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  76. waitLoop4Complete(url, appkey, token, taskId, requestId)
  77. } else {
  78. fmt.Println("The POST request failed: " + string(body))
  79. fmt.Println("The HTTP statusCode: " + strconv.Itoa(statusCode))
  80. }
  81. }
  82. // 根据特定信息轮询检查某个请求在服务端的合成状态,轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
  83. func waitLoop4Complete(url string, appkey string, token string, task_id string, request_id string) {
  84. var fullUrl string = url + "?appkey=" + appkey + "&task_id=" + task_id + "&token=" + token + "&request_id=" + request_id
  85. fmt.Println("fullUrl=" + fullUrl)
  86. for {
  87. response, err := http.Get(fullUrl)
  88. if err != nil {
  89. fmt.Println("The GET request failed!")
  90. panic(err)
  91. }
  92. defer response.Body.Close()
  93. body, _ := ioutil.ReadAll(response.Body)
  94. fmt.Println("waitLoop4Complete = ", string(body))
  95. var f interface{}
  96. json.Unmarshal(body, &f)
  97. if err != nil {
  98. fmt.Println(err)
  99. }
  100. // 从消息体中解析出来task_id(重要)和request_id
  101. var code float64 = 0
  102. var taskId string = ""
  103. var audioAddress string = ""
  104. m := f.(map[string]interface{})
  105. for k, v := range m {
  106. if(k == "error_code") {
  107. code = v.(float64)
  108. } else if(k == "request_id") {
  109. } else if(k == "data") {
  110. if (v != nil) {
  111. data := v.(map[string]interface{})
  112. taskId = data["task_id"].(string)
  113. audioAddress = data["audio_address"].(string)
  114. }
  115. }
  116. }
  117. if (code == 20000000 && audioAddress != "") {
  118. fmt.Println("Tts Finished! task_id = " + taskId);
  119. fmt.Println("Tts Finished! audio_address = " + audioAddress);
  120. break
  121. } else {
  122. time.Sleep(time.Duration(3)*time.Second)
  123. }
  124. }
  125. }
  126. func main() {
  127. var appkey string = "填写你的appkey"
  128. var token string = "填写你的token"
  129. var text string = "今天是周一,天气挺好的。"
  130. requestLongTts4Post(text, appkey, token)
  131. }