RESTful API

更新时间:
复制 MD 格式

语音合成 RESTful API 通过 HTTPS GET 或 POST 请求接收文本,并在响应体中返回合成音频。支持设置音频格式、采样率、发音人、语速、语调和音量。

功能说明

支持 PCM、WAV 和 MP3 音频格式,以及多种发音人。音频格式和采样率等配置见请求参数。

重要
  • 单次请求的文本不超过 300 个字符,超过的字符会被截断。更长的文本需要分段合成,再拼接音频。

  • 合成耗时受文本和模型影响。建议采用流式接收,收到音频数据后即可处理,不必等待全部音频返回。在响应读取完成前,保持连接不中断。

前提条件

服务地址

使用与服务地域对应的 AppKey 和 Token。以下示例使用公网 HTTPS 地址。

地域

请求 URL

华东 2(上海)

https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts

示例代码

将示例中的 AppKey 和 Token 占位值替换为有效凭证。不要在日志中记录 Token、携带 Token 的完整 URL 或请求体。各语言示例演示 GET 和 POST 请求;Java 还提供流式接收示例。

Java

依赖

将以下依赖加入 Maven 项目的 pom.xml:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.9.1</version>
</dependency>
<!-- http://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>
<dependency>
    <groupId>org.asynchttpclient</groupId>
    <artifactId>async-http-client</artifactId>
    <version>2.5.4</version>
</dependency>

普通请求

import java.io.File;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import com.alibaba.fastjson.JSONObject;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class SpeechSynthesizerRestfulDemo {
    private String accessToken;
    private String appkey;
    public SpeechSynthesizerRestfulDemo(String appkey, String token) {
        this.appkey = appkey;
        this.accessToken = token;
    }
    /**
     * HTTPS GET请求
     */
    public void processGETRequet(String text, String audioSaveFile, String format, int sampleRate, String voice) {
        /**
         * 设置HTTPS GET请求:
         * 1.使用HTTPS协议
         * 2.语音合成服务域名:nls-gateway-cn-shanghai.aliyuncs.com
         * 3.语音合成接口请求路径:/stream/v1/tts
         * 4.设置本示例使用的请求参数:appkey、token、text、format、sample_rate
         * 5.设置可选请求参数:voice、volume、speech_rate、pitch_rate
         */
        String url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
        url = url + "?appkey=" + appkey;
        url = url + "&token=" + accessToken;
        url = url + "&text=" + text;
        url = url + "&format=" + format;
        url = url + "&voice=" + voice;
        url = url + "&sample_rate=" + String.valueOf(sampleRate);
        // voice 发音人,可选,默认是xiaoyun。
        // url = url + "&voice=" + "xiaoyun";
        // volume 音量,范围是0~100,可选,默认50。
        // url = url + "&volume=" + String.valueOf(50);
        // speech_rate 语速,范围是-500~500,可选,默认是0。
        // url = url + "&speech_rate=" + String.valueOf(0);
        // pitch_rate 语调,范围是-500~500,可选,默认是0。
        // url = url + "&pitch_rate=" + String.valueOf(0);
        /**
         * 发送HTTPS GET请求,处理服务端的响应。
         */
        Request request = new Request.Builder().url(url).get().build();
        try {
            long start = System.currentTimeMillis();
            OkHttpClient client = new OkHttpClient();
            Response response = client.newCall(request).execute();
            System.out.println("total latency :" + (System.currentTimeMillis() - start) + " ms");
            System.out.println(response.headers().toString());
            String contentType = response.header("Content-Type");
            if ("audio/mpeg".equals(contentType)) {
                File f = new File(audioSaveFile);
                FileOutputStream fout = new FileOutputStream(f);
                fout.write(response.body().bytes());
                fout.close();
                System.out.println("The GET request succeed!");
            }
            else {
                // ContentType 为 null 或者为 "application/json"
                String errorMessage = response.body().string();
                System.out.println("The GET request failed: " + errorMessage);
            }
            response.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * HTTPS POST请求
     */
    public void processPOSTRequest(String text, String audioSaveFile, String format, int sampleRate, String voice) {
        /**
         * 设置HTTPS POST请求:
         * 1.使用HTTPS协议
         * 2.语音合成服务域名:nls-gateway-cn-shanghai.aliyuncs.com
         * 3.语音合成接口请求路径:/stream/v1/tts
         * 4.设置本示例使用的请求参数:appkey、token、text、format、sample_rate
         * 5.设置可选请求参数:voice、volume、speech_rate、pitch_rate
         */
        String url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
        JSONObject taskObject = new JSONObject();
        taskObject.put("appkey", appkey);
        taskObject.put("token", accessToken);
        taskObject.put("text", text);
        taskObject.put("format", format);
        taskObject.put("voice", voice);
        taskObject.put("sample_rate", sampleRate);
        // voice 发音人,可选,默认是xiaoyun。
        // taskObject.put("voice", "xiaoyun");
        // volume 音量,范围是0~100,可选,默认50。
        // taskObject.put("volume", 50);
        // speech_rate 语速,范围是-500~500,可选,默认是0。
        // taskObject.put("speech_rate", 0);
        // pitch_rate 语调,范围是-500~500,可选,默认是0。
        // taskObject.put("pitch_rate", 0);
        String bodyContent = taskObject.toJSONString();
        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");
            if ("audio/mpeg".equals(contentType)) {
                File f = new File(audioSaveFile);
                FileOutputStream fout = new FileOutputStream(f);
                fout.write(response.body().bytes());
                fout.close();
                System.out.println("The POST request succeed!");
            }
            else {
                // ContentType 为 null 或者为 "application/json"
                String errorMessage = response.body().string();
                System.out.println("The POST request failed: " + errorMessage);
            }
            response.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        if (args.length < 2) {
            System.err.println("SpeechSynthesizerRestfulDemo need params: <token> <app-key>");
            System.exit(-1);
        }
        String token = args[0];
        String appkey = args[1];
        SpeechSynthesizerRestfulDemo demo = new SpeechSynthesizerRestfulDemo(appkey, token);
        String text = "今天是周一,天气挺好的。";
        // 采用RFC 3986规范进行urlencode编码。
        String textUrlEncode = text;
        try {
            textUrlEncode = URLEncoder.encode(textUrlEncode, "UTF-8")
                .replace("+", "%20")
                .replace("*", "%2A")
                .replace("%7E", "~");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(textUrlEncode);
        String audioSaveFile = "syAudio.wav";
        String format = "wav";
        int sampleRate = 16000;
        demo.processGETRequet(textUrlEncode, audioSaveFile, format, sampleRate, "siyue");
        //demo.processPOSTRequest(text, audioSaveFile, format, sampleRate, "siyue");
        System.out.println("### Game Over ###");
    }
}

流式接收

通过响应回调分段接收音频。不要在回调中执行耗时操作;需要播放或进一步处理时,可将音频数据交给其他线程。

import java.io.File;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.concurrent.CountDownLatch;
import io.netty.handler.codec.http.HttpHeaders;
import org.asynchttpclient.AsyncHandler;
import org.asynchttpclient.AsyncHttpClient;
import org.asynchttpclient.AsyncHttpClientConfig;
import org.asynchttpclient.DefaultAsyncHttpClient;
import org.asynchttpclient.DefaultAsyncHttpClientConfig;
import org.asynchttpclient.HttpResponseBodyPart;
import org.asynchttpclient.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 此示例演示了
 * 1. TTS的RESTFul接口调用。
 * 2. 启用HTTP chunked机制的处理方式(流式返回)。
 */
public class SpeechSynthesizerRestfulChunkedDemo {
    private static Logger logger = LoggerFactory.getLogger(SpeechSynthesizerRestfulChunkedDemo.class);
    private String accessToken;
    private String appkey;
    public SpeechSynthesizerRestfulChunkedDemo(String appkey, String token) {
        this.appkey = appkey;
        this.accessToken = token;
    }
    public void processGETRequet(String text, String audioSaveFile, String format, int sampleRate, String voice, boolean chunked) {
        /**
         * 设置HTTPS GET请求:
         * 1.使用HTTPS协议
         * 2.语音合成服务域名:nls-gateway-cn-shanghai.aliyuncs.com
         * 3.语音合成接口请求路径:/stream/v1/tts
         * 4.设置本示例使用的请求参数:appkey、token、text、format、sample_rate
         * 5.设置可选请求参数:voice、volume、speech_rate、pitch_rate
         * 6.设置参数chunk,启用http流式返回
         */
        String url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
        url = url + "?appkey=" + appkey;
        url = url + "&token=" + accessToken;
        url = url + "&text=" + text;
        url = url + "&format=" + format;
        url = url + "&voice=" + voice;
        url = url + "&sample_rate=" + String.valueOf(sampleRate);
        url = url + "&chunk=" + String.valueOf(chunked);
        try {
            AsyncHttpClientConfig config = new DefaultAsyncHttpClientConfig.Builder()
                .setConnectTimeout(3000)
                .setKeepAlive(true)
                .setReadTimeout(10000)
                .setRequestTimeout(50000)
                .setMaxConnections(1000)
                .setMaxConnectionsPerHost(200)
                .setPooledConnectionIdleTimeout(-1)
                .build();
            AsyncHttpClient httpClient = new DefaultAsyncHttpClient(config);
            CountDownLatch latch = new CountDownLatch(1);
            AsyncHandler<org.asynchttpclient.Response> handler = new AsyncHandler<org.asynchttpclient.Response>() {
                FileOutputStream outs;
                boolean firstRecvBinary = true;
                long startTime = System.currentTimeMillis();
                int httpCode = 200;
                @Override
                public State onStatusReceived(HttpResponseStatus httpResponseStatus) throws Exception {
                    logger.info("onStatusReceived status {}", httpResponseStatus);
                    httpCode = httpResponseStatus.getStatusCode();
                    if (httpResponseStatus.getStatusCode() != 200) {
                        logger.error("request error " +  httpResponseStatus.toString());
                    }
                    return State.CONTINUE;
                }
                @Override
                public State onHeadersReceived(HttpHeaders httpHeaders) throws Exception {
                    if (httpCode != 200 || !"audio/mpeg".equals(httpHeaders.get("Content-Type"))) {
                        throw new java.io.IOException("Unexpected synthesis response: HTTP " + httpCode);
                    }
                    outs = new FileOutputStream(new File(audioSaveFile));
                    return State.CONTINUE;
                }
                @Override
                public State onBodyPartReceived(HttpResponseBodyPart httpResponseBodyPart) throws Exception {
                    // 注意:此处一旦接收到数据流,即可向用户播放或者用于其他处理,以提升响应速度。
                    // 注意:请不要在此回调接口中执行耗时操作,可以以异步或者队列形式将二进制TTS语音流推送到另一线程中。
                    logger.info("onBodyPartReceived " + httpResponseBodyPart.getBodyPartBytes().toString());
                    if(httpCode != 200) {
                        System.err.write(httpResponseBodyPart.getBodyPartBytes());
                    }
                    if (firstRecvBinary) {
                        firstRecvBinary = false;
                        // 统计第一包数据的接收延迟。实际上接收到第一包数据后就可以进行业务处理了,比如播放或者发送给调用方。注意:这里的首包延迟也包括了网络建立链接的时间。
                        logger.info("tts first latency " + (System.currentTimeMillis() - startTime) + " ms");
                    }
                    // 此处以将语音流保存到文件为例。
                    outs.write(httpResponseBodyPart.getBodyPartBytes());
                    return State.CONTINUE;
                }
                @Override
                public void onThrowable(Throwable throwable) {
                    logger.error("Synthesis request failed: {}", throwable.getClass().getSimpleName());
                    if (outs != null) {
                        try { outs.close(); } catch (java.io.IOException ignored) { }
                    }
                    latch.countDown();
                }
                @Override
                public org.asynchttpclient.Response onCompleted() throws Exception {
                    logger.info("completed");
                    logger.info("tts total latency " + (System.currentTimeMillis() - startTime) + " ms");
                    outs.close();
                    latch.countDown();
                    return null;
                }
            };
            httpClient.prepareGet(url).execute(handler);
            // 等待合成完成
            latch.await();
            httpClient.close();
        }catch (Exception e) {
        }
    }
    public static void main(String[] args) {
        if (args.length < 2) {
            System.err.println("SpeechSynthesizerRestfulDemo need params: <token> <app-key>");
            System.exit(-1);
        }
        String token = args[0];
        String appkey = args[1];
        SpeechSynthesizerRestfulChunkedDemo demo = new SpeechSynthesizerRestfulChunkedDemo(appkey, token);
        String text = "今天是周一,天气挺好的。";
        // 采用RFC 3986规范进行urlencode编码。
        String textUrlEncode = text;
        try {
            textUrlEncode = URLEncoder.encode(textUrlEncode, "UTF-8")
                .replace("+", "%20")
                .replace("*", "%2A")
                .replace("%7E", "~");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(textUrlEncode);
        String audioSaveFile = "syAudio.wav";
        String format = "wav";
        int sampleRate = 16000;
        // 最后一个参数为true表示使用http chunked机制。
        demo.processGETRequet(textUrlEncode, audioSaveFile, format, sampleRate, "aixia", true);
        System.out.println("### Game Over ###");
    }
}

分段合成长文本的完整示例可下载 nls-restful-java-demo.zip。

C++

说明
  • 下载C++示例。

    C++示例使用第三方函数库curl处理HTTPS的请求和响应,使用jsoncpp处理POST请求体的JSON字符串。

  • Linux环境下,运行环境最低要求:Glibc 2.5及以上, GCC 4或GCC 5。

  • Windows下需解压lib目录下的windows.zip库编译使用。

示例目录说明如下:

  • CMakeLists.txt:示例工程的CMakeList文件。

  • demo:示例文件。

    文件名

    描述

    restfulTtsDemo.cpp

    语音合成RESTful API示例。

  • include

    目录名

    描述

    curl

    curl库头文件目录。

    json

    jsoncpp库头文件目录。

  • lib:包含curl、jsoncpp动态库。

    根据平台不同,使用如下版本软件加载库文件:

    • linux(Glibc:2.5及以上,GCC 4或GCC 5)

    • windows(VS2013、VS2015)

  • readme.txt:说明文件。

  • release.log:更新记录。

  • version:版本号。

  • build.sh:示例编译脚本。

编译运行操作步骤:

假设示例文件已解压至path/to路径下,在Linux终端依次执行如下命令编译运行程序。

  • 支持Cmake:

    1. 确认本地系统已安装Cmake 2.4及以上版本。

    2. cd path/to/sdk/lib。

    3. tar -zxvpf linux.tar.gz。

    4. cd path/to/sdk。

    5. ./build.sh。

    6. cd path/to/sdk/demo。

    7. ./restfulTtsDemo <your-token> <your-appkey>。

  • 不支持Cmake:

    1. cd path/to/sdk/lib。

    2. tar -zxvpf linux.tar.gz。

    3. cd path/to/sdk/demo。

    4. g++ -o restfulTtsDemo restfulTtsDemo.cpp -I path/to/sdk/include -L path/to/sdk/lib/linux -ljsoncpp -lssl -lcrypto -lcurl -D_GLIBCXX_USE_CXX11_ABI=0。

    5. export LD_LIBRARY_PATH=path/to/sdk/lib/linux/。

    6. ./restfulTtsDemo <your-token> <your-appkey>。

示例代码如下:

#ifdef _WIN32
#include <Windows.h>
#endif
#include <iostream>
#include <string>
#include <map>
#include <fstream>
#include <sstream>
#include "curl/curl.h"
#include "json/json.h"
using namespace std;
#ifdef _WIN32
string GBKToUTF8(const string &strGBK) {
    string strOutUTF8 = "";
    WCHAR * str1;
    int n = MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, NULL, 0);
    str1 = new WCHAR[n];
    MultiByteToWideChar(CP_ACP, 0, strGBK.c_str(), -1, str1, n);
    n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);
    char * str2 = new char[n];
    WideCharToMultiByte(CP_UTF8, 0, str1, -1, str2, n, NULL, NULL);
    strOutUTF8 = str2;
    delete[] str1;
    str1 = NULL;
    delete[] str2;
    str2 = NULL;
    return strOutUTF8;
}
#endif
void stringReplace(string& src, const string& s1, const string& s2) {
    string::size_type pos = 0;
    while ((pos = src.find(s1, pos)) != string::npos) {
        src.replace(pos, s1.length(), s2);
        pos += s2.length();
    }
}
string urlEncode(const string& src) {
    CURL* curl = curl_easy_init();
    char* output = curl_easy_escape(curl, src.c_str(), src.size());
    string result(output);
    curl_free(output);
    curl_easy_cleanup(curl);
    return result;
}
size_t responseHeadersCallback(void* ptr, size_t size, size_t nmemb, void* userdata)
{
    map<string, string> *headers = (map<string, string>*)userdata;
    string line((char*)ptr, size * nmemb);
    string::size_type pos = line.find(':');
    if (pos != line.npos)
    {
        string name = line.substr(0, pos);
        string value = line.substr(pos + 2);
        size_t p = 0;
        if ((p = value.rfind('\r')) != value.npos) {
            value = value.substr(0, p);
        }
        headers->insert(make_pair(name, value));
    }
    return size * nmemb;
}
size_t responseBodyCallback(void* ptr, size_t size, size_t nmemb, void* userData) {
    size_t len = size * nmemb;
    char* pBuf = (char*)ptr;
    string* bodyContent = (string*)userData;
    (*bodyContent).append(string(pBuf, pBuf + len));
    return len;
}
int processGETRequest(string appKey, string token, string text, 
                      string audioSaveFile, string format, int sampleRate) {
    CURL* curl = NULL;
    CURLcode res;
    curl = curl_easy_init();
    if (curl == NULL) {
        return -1;
    }
    string url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
    /**
     * 设置HTTPS URL请求参数
     */
    ostringstream oss;
    oss << url;
    oss << "?appkey=" << appKey;
    oss << "&token=" << token;
    oss << "&text=" << text;
    oss << "&format=" << format;
    oss << "&sample_rate=" << sampleRate;
    // voice 发音人,可选,默认是xiaoyun。
    // oss << "&voice=" << "xiaoyun";
    // volume 音量,范围是0~100,可选,默认50。
    // oss << "&volume=" << 50;
    // speech_rate 语速,范围是-500~500,可选,默认是0。
    // oss << "&speech_rate=" << 0;
    // pitch_rate 语调,范围是-500~500,可选,默认是0。
    // oss << "&pitch_rate=" << 0;
    string request = oss.str();
    curl_easy_setopt(curl, CURLOPT_URL, request.c_str());
    /**
     * 设置获取响应的HTTPS Headers回调函数
     */
    map<string, string> responseHeaders;
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, responseHeadersCallback);
    curl_easy_setopt(curl, CURLOPT_HEADERDATA, &responseHeaders);
    /**
     * 设置获取响应的HTTPS Body回调函数
     */
    string bodyContent = "";
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, responseBodyCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &bodyContent);
    /**
     * 发送HTTPS GET请求
     */
    res = curl_easy_perform(curl);
    /**
     * 释放资源
     */
    curl_easy_cleanup(curl);
    if (res != CURLE_OK) {
        cerr << "curl_easy_perform failed: " << curl_easy_strerror(res) << endl;
        return -1;
    }
    /**
     * 处理服务端返回的响应
     */
    map<string, string>::iterator it = responseHeaders.find("Content-Type");
    if (it != responseHeaders.end() && it->second.compare("audio/mpeg") == 0) {
        ofstream fs;
        fs.open(audioSaveFile.c_str(), ios::out | ios::binary);
        if (!fs.is_open()) {
            cout << "The audio save file can not open!";
            return -1;
        }
        fs.write(bodyContent.c_str(), bodyContent.size());
        fs.close();
        cout << "The GET request succeed!" << endl;
    }
    else {
        cout << "The GET request failed: " + bodyContent << endl;
        return -1;
    }
    return 0;
}
int processPOSTRequest(string appKey, string token, string text,
                       string audioSaveFile, string format, int sampleRate) {
    CURL* curl = NULL;
    CURLcode res;
    curl = curl_easy_init();
    if (curl == NULL) {
        return -1;
    }
    string url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
    /**
     * 设置HTTPS POST URL
     */
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    /**
     * 设置HTTPS POST请求头部
     */
    struct curl_slist* headers = NULL;
    // Content-Type
    headers = curl_slist_append(headers, "Content-Type:application/json");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    /**
     * 设置HTTPS POST请求体
     */
    Json::Value root;
    Json::FastWriter writer;
    root["appkey"] = appKey;
    root["token"] = token;
    root["text"] = text;
    root["format"] = format;
    root["sample_rate"] = sampleRate;
    // voice 发音人,可选,默认是xiaoyun。
    // root["voice"] = "xiaoyun";
    // volume 音量,范围是0~100,可选,默认50。
    // root["volume"] = 50;
    // speech_rate 语速,范围是-500~500,可选,默认是0。
    // root["speech_rate"] = 0;
    // pitch_rate 语调,范围是-500~500,可选,默认是0。
    // root["pitch_rate"] = 0;
    string task = writer.write(root);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, task.c_str());
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, task.length());
    /**
     * 设置获取响应的HTTPS Headers回调函数
     */
    map<string, string> responseHeaders;
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, responseHeadersCallback);
    curl_easy_setopt(curl, CURLOPT_HEADERDATA, &responseHeaders);
    /**
     * 设置获取响应的HTTPS Body回调函数
     */
    string bodyContent = "";
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, responseBodyCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &bodyContent);
    /**
     * 发送HTTPS POST请求
     */
    res = curl_easy_perform(curl);
    /**
     * 释放资源
     */
    curl_slist_free_all(headers);
    curl_easy_cleanup(curl);
    if (res != CURLE_OK) {
        cerr << "curl_easy_perform failed: " << curl_easy_strerror(res) << endl;
        return -1;
    }
    /**
     * 处理服务端返回的响应
     */
    map<string, string>::iterator it = responseHeaders.find("Content-Type");
    if (it != responseHeaders.end() && it->second.compare("audio/mpeg") == 0) {
        ofstream fs;
        fs.open(audioSaveFile.c_str(), ios::out | ios::binary);
        if (!fs.is_open()) {
            cout << "The audio save file can not open!";
            return -1;
        }
        fs.write(bodyContent.c_str(), bodyContent.size());
        fs.close();
        cout << "The POST request succeed!" << endl;
    }
    else {
        cout << "The POST request failed: " + bodyContent << endl;
        return -1;
    }
    return 0;
}
int main(int argc, char* argv[]) {
    if (argc < 3) {
        cerr << "params is not valid. Usage: ./demo your_token your_appkey" << endl;
        return -1;
    }
    string token = argv[1];
    string appKey = argv[2];
    string text = "今天是周一,天气挺好的。";
#ifdef _WIN32
    text = GBKToUTF8(text);
#endif
    string textUrlEncode = urlEncode(text);
    stringReplace(textUrlEncode, "+", "%20");
    stringReplace(textUrlEncode, "*", "%2A");
    stringReplace(textUrlEncode, "%7E", "~");
    string audioSaveFile = "syAudio.wav";
    string format = "wav";
    int sampleRate = 16000;
    // 全局只初始化一次。
    curl_global_init(CURL_GLOBAL_ALL);
    processGETRequest(appKey, token, textUrlEncode, audioSaveFile, format, sampleRate);
    //processPOSTRequest(appKey, token, text, audioSaveFile, format, sampleRate);
    curl_global_cleanup();
    return 0;
}

Python

Python 3 使用 http.client 和 urllib.parse。Python 2 对应使用 httplib 和 urllib,替换方式见代码注释。

# -*- coding: UTF-8 -*-
# Python 2.x引入httplib模块。
# import httplib
# Python 3.x引入http.client模块。
import http.client
# Python 2.x引入urllib模块。
# import urllib
# Python 3.x引入urllib.parse模块。
import urllib.parse
import json
def processGETRequest(appKey, token, text, audioSaveFile, format, sampleRate) :
    host = 'nls-gateway-cn-shanghai.aliyuncs.com'
    url = 'https://' + host + '/stream/v1/tts'
    # 设置URL请求参数
    url = url + '?appkey=' + appKey
    url = url + '&token=' + token
    url = url + '&text=' + text
    url = url + '&format=' + format
    url = url + '&sample_rate=' + str(sampleRate)
    # voice 发音人,可选,默认是xiaoyun。
    # url = url + '&voice=' + 'xiaoyun'
    # volume 音量,范围是0~100,可选,默认50。
    # url = url + '&volume=' + str(50)
    # speech_rate 语速,范围是-500~500,可选,默认是0。
    # url = url + '&speech_rate=' + str(0)
    # pitch_rate 语调,范围是-500~500,可选,默认是0。
    # url = url + '&pitch_rate=' + str(0)
    # Python 2.x请使用httplib。
    # conn = httplib.HTTPSConnection(host)
    # Python 3.x请使用http.client。
    conn = http.client.HTTPSConnection(host)
    conn.request(method='GET', url=url)
    # 处理服务端返回的响应。
    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 'audio/mpeg' == contentType :
        with open(audioSaveFile, mode='wb') as f:
            f.write(body)
        print('The GET request succeed!')
    else :
        print('The GET request failed: ' + str(body))
    conn.close()
def processPOSTRequest(appKey, token, text, audioSaveFile, format, sampleRate) :
    host = 'nls-gateway-cn-shanghai.aliyuncs.com'
    url = 'https://' + host + '/stream/v1/tts'
    # 设置HTTPS Headers。
    httpHeaders = {
        'Content-Type': 'application/json'
        }
    # 设置HTTPS Body。
    body = {'appkey': appKey, 'token': token, 'text': text, 'format': format, 'sample_rate': sampleRate}
    body = json.dumps(body)
    # Python 2.x请使用httplib。
    # conn = httplib.HTTPSConnection(host)
    # Python 3.x请使用http.client。
    conn = http.client.HTTPSConnection(host)
    conn.request(method='POST', url=url, body=body, headers=httpHeaders)
    # 处理服务端返回的响应。
    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 'audio/mpeg' == contentType :
        with open(audioSaveFile, mode='wb') as f:
            f.write(body)
        print('The POST request succeed!')
    else :
        print('The POST request failed: ' + str(body))
    conn.close()
appKey = '<appkey>'
token = '<token>'
text = '今天是周一,天气挺好的。'
# 采用RFC 3986规范进行urlencode编码。
textUrlencode = text
# Python 2.x请使用urllib.quote。
# textUrlencode = urllib.quote(textUrlencode, '')
# Python 3.x请使用urllib.parse.quote_plus。
textUrlencode = urllib.parse.quote_plus(textUrlencode)
textUrlencode = textUrlencode.replace("+", "%20")
textUrlencode = textUrlencode.replace("*", "%2A")
textUrlencode = textUrlencode.replace("%7E", "~")
print('text: ' + textUrlencode)
audioSaveFile = 'syAudio.wav'
format = 'wav'
sampleRate = 16000
# GET请求方式
processGETRequest(appKey, token, textUrlencode, audioSaveFile, format, sampleRate)
# POST请求方式
# processPOSTRequest(appKey, token, text, audioSaveFile, format, sampleRate)

PHP

需要支持 json_encode 的 PHP 环境,并安装 cURL 扩展。使用 HTTPS 时保留证书校验。

<?php
function processGETRequest($appkey, $token, $text, $audioSaveFile, $format, $sampleRate) {
    $url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
    $url = $url . "?appkey=" . $appkey;
    $url = $url . "&token=" . $token;
    $url = $url . "&text=" . $text;
    $url = $url . "&format=" . $format;
    $url = $url . "&sample_rate=" . strval($sampleRate);
    // voice 发音人,可选,默认是xiaoyun。
    // $url = $url . "&voice=" . "xiaoyun";
    // volume 音量,范围是0~100,可选,默认50。
    // $url = $url . "&volume=" . strval(50);
    // speech_rate 语速,范围是-500~500,可选,默认是0。
    // $url = $url . "&speech_rate=" . strval(0);
    // pitch_rate 语调,范围是-500~500,可选,默认是0。
    // $url = $url . "&pitch_rate=" . strval(0);
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
    /**
     * 设置HTTPS GET URL。
     */
    curl_setopt($curl, CURLOPT_URL, $url);
    /**
     * 设置返回的响应包含HTTPS头部信息。
     */
    curl_setopt($curl, CURLOPT_HEADER, TRUE);
    /**
     * 发送HTTPS GET请求。
     */
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, TRUE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
    $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);
    curl_close($curl);
    if (stripos($headers, "Content-Type: audio/mpeg") != FALSE || stripos($headers, "Content-Type:audio/mpeg") != FALSE) {
        file_put_contents($audioSaveFile, $bodyContent);
        print "The GET request succeed!\n";
    }
    else {
        print "The GET request failed: " . $bodyContent . "\n";
    }
}
function processPOSTRequest($appkey, $token, $text, $audioSaveFile, $format, $sampleRate) {
    $url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
    /**
     * 请求参数,以JSON格式字符串填入HTTPS POST请求的Body中。
     */
    $taskArr = array(
        "appkey" => $appkey,
        "token" => $token,
        "text" => $text,
        "format" => $format,
        "sample_rate" => $sampleRate
        // voice 发音人,可选,默认是xiaoyun。
        // "voice" => "xiaoyun",
        // volume 音量,范围是0~100,可选,默认50。
        // "volume" => 50,
        // speech_rate 语速,范围是-500~500,可选,默认是0。
        // "speech_rate" => 0,
        // pitch_rate 语调,范围是-500~500,可选,默认是0。
        // "pitch_rate" => 0
    );
    $body = json_encode($taskArr);
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
    /**
     * 设置HTTPS POST URL。
     */
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, TRUE);
    /**
     * 设置HTTPS POST请求头部。
     * */
    $httpHeaders = array(
        "Content-Type: application/json"
    );
    curl_setopt($curl, CURLOPT_HTTPHEADER, $httpHeaders);
    /**
     * 设置HTTPS POST请求体。
     */
    curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
    /**
     * 设置返回的响应包含HTTPS头部信息。
     */
    curl_setopt($curl, CURLOPT_HEADER, TRUE);
    /**
     * 发送HTTPS POST请求。
     */
    $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);
    curl_close($curl);
    if (stripos($headers, "Content-Type: audio/mpeg") != FALSE || stripos($headers, "Content-Type:audio/mpeg") != FALSE) {
        file_put_contents($audioSaveFile, $bodyContent);
        print "The POST request succeed!\n";
    }
    else {
        print "The POST request failed: " . $bodyContent . "\n";
    }
}
$appkey = "<appkey>";
$token = "<token>";
$text = "今天是周一,天气挺好的。";
$textUrlEncode = urlencode($text);
$textUrlEncode = preg_replace('/\+/', '%20', $textUrlEncode);
$textUrlEncode = preg_replace('/\*/', '%2A', $textUrlEncode);
$textUrlEncode = preg_replace('/%7E/', '~', $textUrlEncode);
$audioSaveFile = "syAudio.wav";
$format = "wav";
$sampleRate = 16000;
processGETRequest($appkey, $token, $textUrlEncode, $audioSaveFile, $format, $sampleRate);
// processPOSTRequest($appkey, $token, $text, $audioSaveFile, $format, $sampleRate);
?>

Node.js

在示例文件所在目录安装依赖:

npm install request --save
const request = require('request');
const fs = require('fs');
function processGETRequest(appkey, token, text, audioSaveFile, format, sampleRate) {
    var url = 'https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts';
    /**
     * 设置URL请求参数。
     */
    url = url + '?appkey=' + appkey;
    url = url + '&token=' + token;
    url = url + '&text=' + text;
    url = url + '&format=' + format;
    url = url + '&sample_rate=' + sampleRate;
    // voice 发音人,可选,默认是xiaoyun。
    // url = url + "&voice=" + "xiaoyun";
    // volume 音量,范围是0~100,可选,默认50。
    // url = url + "&volume=" + 50;
    // speech_rate 语速,范围是-500~500,可选,默认是0。
    // url = url + "&speech_rate=" + 0;
    // pitch_rate 语调,范围是-500~500,可选,默认是0。
    // url = url + "&pitch_rate=" + 0;
    /**
     * 设置HTTPS GET请求。
     * encoding必须设置为null,HTTPS响应的Body为二进制Buffer类型。
     */
    var options = {
        url: url,
        method: 'GET',
        encoding: null
    };
    request(options, function (error, response, body) {
        /**
         * 处理服务端的响应。
         */
        if (error != null) {
            console.log(error);
        }
        else {
            var contentType = response.headers['content-type'];
            if (contentType === undefined || contentType != 'audio/mpeg') {
                console.log('The GET request failed!');
            }
            else {
                fs.writeFileSync(audioSaveFile, body);
                console.log('The GET request is succeed!');
            }
        }
    });
}
function processPOSTRequest(appkeyValue, tokenValue, textValue, audioSaveFile, formatValue, sampleRateValue) {
    var url = 'https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts';
    /**
     * 请求参数,以JSON格式字符串填入HTTPS POST请求的Body中。
    */
    var task = {
        appkey : appkeyValue,
        token : tokenValue,
        text : textValue,
        format : formatValue,
        sample_rate : sampleRateValue
        // voice 发音人,可选,默认是xiaoyun。
        // voice : 'xiaoyun',
        // volume 音量,范围是0~100,可选,默认50。
        // volume : 50,
        // speech_rate 语速,范围是-500~500,可选,默认是0。
        // speech_rate : 0,
        // pitch_rate 语调,范围是-500~500,可选,默认是0。
        // pitch_rate : 0
    };
    var bodyContent = JSON.stringify(task);
    /**
     * 设置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 {
            var contentType = response.headers['content-type'];
            if (contentType === undefined || contentType != 'audio/mpeg') {
                console.log('The POST request failed!');
            }
            else {
                fs.writeFileSync(audioSaveFile, body);
                console.log('The POST request is succeed!');
            }
        }
    });
}
var appkey = '<appkey>';
var token = '<token>';
var text = '今天是周一,天气挺好的。';
var textUrlEncode = encodeURIComponent(text)
                    .replace(/[!'()*]/g, function(c) {
                        return '%' + c.charCodeAt(0).toString(16);
                    });
console.log(textUrlEncode);
var audioSaveFile = 'syAudio.wav';
var format = 'wav';
var sampleRate = 16000;
processGETRequest(appkey, token, textUrlEncode, audioSaveFile, format, sampleRate);
// processPOSTRequest(appkey, token, text, audioSaveFile, format, sampleRate);

.NET

示例依赖 System.Net.Http、System.Web 和 Newtonsoft.Json.Linq。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net.Http;
using System.Web;
using Newtonsoft.Json.Linq;
namespace RESTfulAPI
{
    class SpeechSynthesizerRESTfulDemo
    {
        private string appkey;
        private string token;
        public SpeechSynthesizerRESTfulDemo(string appkey, string token)
        {
            this.appkey = appkey;
            this.token = token;
        }
        public void processGETRequest(string text, string audioSaveFile, string format, int sampleRate)
        {
            /**
             * 设置HTTPS GET请求:
             * 1.使用HTTPS协议
             * 2.语音合成服务域名:nls-gateway-cn-shanghai.aliyuncs.com
             * 3.语音合成接口请求路径:/stream/v1/tts
             * 4.设置本示例使用的请求参数:appkey、token、text、format、sample_rate
             * 5.设置可选请求参数:voice、volume、speech_rate、pitch_rate
             */
            string url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
            url = url + "?appkey=" + appkey;
            url = url + "&token=" + token;
            url = url + "&text=" + text;
            url = url + "&format=" + format;
            url = url + "&sample_rate=" + sampleRate.ToString();
            // voice 发音人,可选,默认是xiaoyun。
            // url = url + "&voice=" + "xiaoyun";
            // volume 音量,范围是0~100,可选,默认50。
            // url = url + "&volume=" + 50;
            // speech_rate 语速,范围是-500~500,可选,默认是0。
            // url = url + "&speech_rate=" + 0;
            // pitch_rate 语调,范围是-500~500,可选,默认是0。
            // url = url + "&pitch_rate=" + 0;
            /**
             * 发送HTTPS GET请求,处理服务端的响应。
             */
            HttpClient client = new HttpClient();
            HttpResponseMessage response = null;
            response = client.GetAsync(url).Result;
            string contentType = null;
            if (response.IsSuccessStatusCode)
            {
                string[] typesArray = response.Content.Headers.GetValues("Content-Type").ToArray();
                if (typesArray.Length > 0)
                {
                    contentType = typesArray.First();
                }
            }
            if ("audio/mpeg".Equals(contentType))
            {
                byte[] audioBuff = response.Content.ReadAsByteArrayAsync().Result;
                FileStream fs = new FileStream(audioSaveFile, FileMode.Create);
                fs.Write(audioBuff, 0, audioBuff.Length);
                fs.Flush();
                fs.Close();
                System.Console.WriteLine("The GET request succeed!");
            }
            else
            {
                // ContentType 为 null 或者为 "application/json"
                System.Console.WriteLine("Response status code and reason phrase: " +
                    response.StatusCode + " " + response.ReasonPhrase);
                string responseBodyAsText = response.Content.ReadAsStringAsync().Result;
                System.Console.WriteLine("The GET request failed: " + responseBodyAsText);
            }
        }
        public void processPOSTRequest(string text, string audioSaveFile, string format, int sampleRate)
        {
            /**
             * 设置HTTPS POST请求:
             * 1.使用HTTPS协议
             * 2.语音合成服务域名:nls-gateway-cn-shanghai.aliyuncs.com
             * 3.语音合成接口请求路径:/stream/v1/tts
             * 4.设置本示例使用的请求参数:appkey、token、text、format、sample_rate
             * 5.设置可选请求参数:voice、volume、speech_rate、pitch_rate
             */
            string url = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts";
            JObject obj = new JObject();
            obj["appkey"] = appkey;
            obj["token"] = token;
            obj["text"] = text;
            obj["format"] = format;
            obj["sample_rate"] = sampleRate;
            // voice 发音人,可选,默认是xiaoyun。
            // obj["voice"] = "xiaoyun";
            // volume 音量,范围是0~100,可选,默认50。
            // obj["volume"] = 50;
            // speech_rate 语速,范围是-500~500,可选,默认是0。
            // obj["speech_rate"] = 0;
            // pitch_rate 语调,范围是-500~500,可选,默认是0。
            // obj["pitch_rate"] = 0;
            String bodyContent = obj.ToString();
            StringContent content = new StringContent(bodyContent, Encoding.UTF8, "application/json");
            /**
             * 发送HTTPS POST请求,处理服务端的响应。
             */
            HttpClient client = new HttpClient();
            HttpResponseMessage response = client.PostAsync(url, content).Result;
            string contentType = null;
            if (response.IsSuccessStatusCode)
            {
                string[] typesArray = response.Content.Headers.GetValues("Content-Type").ToArray();
                if (typesArray.Length > 0)
                {
                    contentType = typesArray.First();
                }
            }
            if ("audio/mpeg".Equals(contentType))
            {
                byte[] audioBuff = response.Content.ReadAsByteArrayAsync().Result;
                FileStream fs = new FileStream(audioSaveFile, FileMode.Create);
                fs.Write(audioBuff, 0, audioBuff.Length);
                fs.Flush();
                fs.Close();
                System.Console.WriteLine("The POST request succeed!");
            }
            else
            {
                System.Console.WriteLine("Response status code and reason phrase: " +
                    response.StatusCode + " " + response.ReasonPhrase);
                string responseBodyAsText = response.Content.ReadAsStringAsync().Result;
                System.Console.WriteLine("The POST request failed: " + responseBodyAsText);
            }
        }
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                System.Console.WriteLine("SpeechSynthesizerRESTfulDemo need params: <token> <app-key>");
                return;
            }
            string token = args[0];
            string appkey = args[1];
            SpeechSynthesizerRESTfulDemo demo = new SpeechSynthesizerRESTfulDemo(appkey, token);
            string text = "今天是周一,天气挺好的。";
            // 采用RFC 3986规范进行urlencode编码。
            string textUrlEncode = text;
            textUrlEncode = HttpUtility.UrlEncode(textUrlEncode, Encoding.UTF8)
                .Replace("+", "%20")
                .Replace("*", "%2A")
                .Replace("%7E", "~");
            System.Console.WriteLine(textUrlEncode);
            string audioSaveFile = "syAudio.wav";
            string format = "wav";
            int sampleRate = 16000;
            demo.processGETRequest(textUrlEncode, audioSaveFile, format, sampleRate);
            //demo.processPOSTRequest(text, audioSaveFile, format, sampleRate);
        }
    }
}

Go

package main
import (
    "fmt"
    "net/url"
    "net/http"
    "io/ioutil"
    "encoding/json"
    "strconv"
    "os"
    "bytes"
    "strings"
)
func processGETRequest(appkey string, token string, text string, audioSaveFile string, format string, sampleRate int) {
    /**
     * 设置HTTPS GET请求:
     * 1.使用HTTPS协议
     * 2.语音合成服务域名:nls-gateway-cn-shanghai.aliyuncs.com
     * 3.语音合成接口请求路径:/stream/v1/tts
     * 4.设置本示例使用的请求参数:appkey、token、text、format、sample_rate
     * 5.设置可选请求参数:voice、volume、speech_rate、pitch_rate
     */
    var url string = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts"
    url = url + "?appkey=" + appkey
    url = url + "&token=" + token
    url = url + "&text=" + text
    url = url + "&format=" + format
    url = url + "&sample_rate=" + strconv.Itoa(sampleRate)
    // voice 发音人,可选,默认是xiaoyun。
    // url = url + "&voice=" + "xiaoyun"
    // volume 音量,范围是0~100,可选,默认50。
    // url = url + "&volume=" + strconv.Itoa(50)
    // speech_rate 语速,范围是-500~500,可选,默认是0。
    // url = url + "&speech_rate=" + strconv.Itoa(0)
    // pitch_rate 语调,范围是-500~500,可选,默认是0。
    // url = url + "&pitch_rate=" + strconv.Itoa(0)
    /**
     * 发送HTTPS GET请求,处理服务端的响应。
     */
    response, err := http.Get(url)
    if err != nil {
        fmt.Println("The GET request failed!")
        panic(err)
    }
    defer response.Body.Close()    
    contentType := response.Header.Get("Content-Type")
    body, _ := ioutil.ReadAll(response.Body)
    if ("audio/mpeg" == contentType) {
        file, _ := os.Create(audioSaveFile)
        defer file.Close()
        file.Write([]byte(body))
        fmt.Println("The GET request succeed!")
    } else {
        // ContentType 为 null 或者为 "application/json"
        statusCode := response.StatusCode
        fmt.Println("The HTTP statusCode: " + strconv.Itoa(statusCode))
        fmt.Println("The GET request failed: " + string(body))
    }
}
func processPOSTRequest(appkey string, token string, text string, audioSaveFile string, format string, sampleRate int) {
    /**
     * 设置HTTPS POST请求:
     * 1.使用HTTPS协议
     * 2.语音合成服务域名:nls-gateway-cn-shanghai.aliyuncs.com
     * 3.语音合成接口请求路径:/stream/v1/tts
     * 4.设置本示例使用的请求参数:appkey、token、text、format、sample_rate
     * 5.设置可选请求参数:voice、volume、speech_rate、pitch_rate
     */
    var url string = "https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts"
    bodyContent := make(map[string]interface{})
    bodyContent["appkey"] = appkey
    bodyContent["text"] = text
    bodyContent["token"] = token
    bodyContent["format"] = format
    bodyContent["sample_rate"] = sampleRate
    // voice 发音人,可选,默认是xiaoyun。
    // bodyContent["voice"] = "xiaoyun"
    // volume 音量,范围是0~100,可选,默认50。
    // bodyContent["volume"] = 50
    // speech_rate 语速,范围是-500~500,可选,默认是0。
    // bodyContent["speech_rate"] = 0
    // pitch_rate 语调,范围是-500~500,可选,默认是0。
    // bodyContent["pitch_rate"] = 0
    bodyJson, err := json.Marshal(bodyContent)
    if err != nil {
        panic(nil)
    }
    /**
     * 发送HTTPS POST请求,处理服务端的响应。
     */
    response, err := http.Post(url, "application/json;charset=utf-8", bytes.NewBuffer([]byte(bodyJson)))
    if err != nil {
        panic(err)
    }
    defer response.Body.Close()
    contentType := response.Header.Get("Content-Type")
    body, _ := ioutil.ReadAll(response.Body)
    if ("audio/mpeg" == contentType) {
        file, _ := os.Create(audioSaveFile)
        defer file.Close()
        file.Write([]byte(body))
        fmt.Println("The POST request succeed!")
    } else {
        // ContentType 为 null 或者为 "application/json"
        statusCode := response.StatusCode
        fmt.Println("The HTTP statusCode: " + strconv.Itoa(statusCode))
        fmt.Println("The POST request failed: " + string(body))
    }    
}
func main() {
    var appkey string = "<appkey>"
    var token  string = "<token>"
    var text string = "今天是周一,天气挺好的。"
    var textUrlEncode = text
    textUrlEncode = url.QueryEscape(textUrlEncode)
    textUrlEncode = strings.Replace(textUrlEncode, "+", "%20", -1)
    textUrlEncode = strings.Replace(textUrlEncode, "*", "%2A", -1)
    textUrlEncode = strings.Replace(textUrlEncode, "%7E", "~", -1)
    fmt.Println(textUrlEncode)
    var audioSaveFile string = "syAudio.wav"
    var format string = "wav"
    var sampleRate int = 16000
    processGETRequest(appkey, token, textUrlEncode, audioSaveFile, format, sampleRate)
    // processPOSTRequest(appkey, token, text, audioSaveFile, format, sampleRate)
}

交互流程

客户端发送包含文本的 GET 或 POST 请求,服务端在 HTTP 响应体中返回音频。流式客户端应持续读取响应体,直到本次响应结束。

image

请求参数

GET 请求将参数放在 URL 查询串中;POST 请求将参数放在 JSON 请求体中。Token 也可以通过 X-NLS-Token 请求头传入。

参数

类型

必选

说明

appkey

String

是

项目 AppKey。

text

String

是

待合成的文本,使用 UTF-8 编码。GET 请求还需要按 RFC 3986 进行 URL 编码;POST 请求不需要 URL 编码。

token

String

否

Access Token。不设置此参数时,必须通过 X-NLS-Token 请求头传入。

format

String

否

音频格式,取值为小写 pcm、wav 或 mp3。默认值:pcm。

sample_rate

Integer

否

音频采样率,单位为 Hz。支持 8000、16000,默认值:16000。默认发音人 xiaoyun 还支持 24000;其他发音人的支持范围以对应说明为准。

voice

String

否

发音人。默认值:xiaoyun。发音人列表和支持范围请参见接口说明。

volume

Integer

否

音量。取值范围:0~100。默认值:50。

speech_rate

Integer

否

语速。取值范围:-500~500。默认值:0。

pitch_rate

Integer

否

语调。取值范围:-500~500。默认值:0。

chunk

Boolean

否

GET 流式示例设置为 true,使用 HTTP Chunked 方式接收音频。客户端仍需分段读取响应;不设置此参数时,响应也可能使用分块传输。

GET 请求

将 text 进行 UTF-8 编码后,再进行 URL 编码。例如,+ 编码为 %2B,* 编码为 %2A,~ 保持不变。请求示例如下,<appkey> 和 <token> 为占位值:

https://nls-gateway-cn-shanghai.aliyuncs.com/stream/v1/tts?appkey=<appkey>&token=<token>&text=%E4%BB%8A%E5%A4%A9%E6%98%AF%E5%91%A8%E4%B8%80%EF%BC%8C%E5%A4%A9%E6%B0%94%E6%8C%BA%E5%A5%BD%E7%9A%84%E3%80%82&format=wav&sample_rate=16000

也可以省略查询串中的 token,改用请求头:

请求头

类型

必选

说明

X-NLS-Token

String

条件必选

查询串中未设置 token 时必选。

POST 请求

使用 UTF-8 编码的 JSON 请求体,text 不进行 URL 编码。

请求头

类型

必选

说明

Content-Type

String

是

设置为 application/json。

X-NLS-Token

String

条件必选

请求体中未设置 token 时必选。

Content-Length

Long

否

请求体字节数,通常由 HTTP 客户端自动设置。

请求体示例:

{
  "appkey": "<appkey>",
  "text": "今天是周一,天气挺好的。",
  "token": "<token>",
  "format": "wav",
  "sample_rate": 16000
}

响应结果

GET 和 POST 使用相同的响应格式。结合 HTTP 状态码和 Content-Type 判断结果,不要把错误响应保存为音频。

成功响应

Content-Type 为 audio/mpeg,响应体为音频二进制数据。该响应头不表示请求的音频格式一定是 MP3;实际音频格式由 format 决定。

成功响应返回 X-NLS-RequestId 时,记录其值作为本次请求的任务 ID,用于排查问题。

失败响应

Content-Type 为 application/json 时,响应体包含 JSON 错误信息。Content-Type 缺失或不是预期的音频类型时,也应按异常响应处理。

{
    "task_id":"8f95d0b9b6e948bc98e8d0ce64b0****",
    "result":"",
    "status":40000000,
    "message":"Gateway:CLIENT_ERROR:in post data, json format illegal"
}

字段

类型

说明

task_id

String

请求任务 ID,通常为 32 位字符串。

result

String

服务结果。

status

Integer

服务状态码。

message

String

错误信息。

记录响应中的 X-NLS-RequestId 或 task_id、HTTP 状态码和错误信息。需要技术支持时,提供这些信息,不要提供 Token。

服务状态码

status 是 JSON 响应中的服务状态码,与 HTTP 状态码不同。

服务状态码

含义

处理建议

20000000

请求成功

无。

40000000

客户端错误

检查错误信息,必要时联系技术支持。

40000001

身份认证失败

检查 Token 是否正确、是否过期。

40000002

无效的消息

检查请求消息格式。

40000003

无效的参数

检查参数取值。

40000004

空闲超时

检查是否长时间未发送数据。

40000005

请求数量过多

检查并发连接数和每秒请求数。

41020001

语音合成客户端错误

根据 message 检查合成参数。例如,音频格式使用小写 pcm、wav 或 mp3。

50000000

服务端错误

记录错误信息;重复出现时联系技术支持。

50000001

内部 GRPC 调用错误

记录错误信息;重复出现时联系技术支持。