日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

C++ SDK

本文介紹如何使用阿里云智能語音服務提供的C++ SDK,包括SDK的安裝方法及SDK代碼示例。

前提條件

下載安裝

SDK下載

您可通過以下兩種方法獲取SDK。

  • 方法一:從GitHub獲取最新源碼,詳細編譯和運行方式可見下文,或查看源碼中的readme.md

    git clone --depth 1 https://github.com/aliyun/alibabacloud-nls-cpp-sdk
  • 方法二:直接從下文表中選取需要的SDK包進行下載。其中SDK源碼包為SDK原始代碼,需要通過下文編譯方法生成集成所需的庫文件。其他對應平臺的SDK包內含相關庫文件、頭文件,無需編譯。

    最新SDK包

    平臺

    MD5

    alibabacloud-nls-cpp-sdk3.2.0f-master_dcaf740.zip

    SDK源碼

    054d6f9f3226f689dbc68f8ed970fe3b

    NlsCppSdk_Linux-x86_64_3.2.0f_dcaf740.tar.gz

    Linux x86_64

    1ebb39ec10993583a645c0de8eebf654

    說明

    以上Linux-x86_64版本使用gcc8.4.0 _GLIBCXX_USE_CXX11_ABI=0編譯。可用源碼包根據readme.md說明重新編譯。

    其中:

    • alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip為SDK源碼包。

    • NlsCppSdk_<平臺>_<版本號>_<github commit id>.tar.gz為對應平臺下開發需要的SDK包,詳見內部readme.md。

SDK包文件說明

  • scripts/build_linux.sh:SDK源碼中,以Linux平臺為例的示例編譯腳本。

  • CMakeLists.txt:SDK源碼中,以Linux/Android平臺為例的示例代碼工程CMakeList文件。

  • demo目錄:SDK包中,集成示例代碼,以Linux平臺為例,如下表所示。

    文件名

    描述

    speechRecognizerDemo.cpp

    一句話識別示例。

    speechSynthesizerDemo.cpp

    語音合成示例。

    speechTranscriberDemo.cpp

    實時語音識別示例。

    flowingSynthesizerDemo.cpp

    流式文本語音合成示例。

    fileTransferDemo.cpp

    錄音文件識別示例。

  • resource目錄:SDK源碼中,語音服務范例音頻,可用于功能測試,如下表所示。

    文件名

    描述

    • test0.wav

    • test1.wav

    • test2.wav

    • test3.wav

    測試音頻(16k采樣頻率、16bit采樣位數的音頻文件)。

  • include:SDK源碼中,SDK頭文件,如下表所示。

    文件名

    描述

    nlsClient.h

    SDK實例。

    nlsEvent.h

    回調事件說明。

    nlsGlobal.h

    SDK全局頭文件。

    nlsToken.h

    SDK Access Token實例。

    iNlsRequest.h

    NLS請求基礎頭文件。

    speechRecognizerRequest.h

    一句話識別。

    speechSynthesizerRequest.h

    語音合成、長文本語音合成。

    speechTranscriberRequest.h

    實時音頻流識別。

    flowingSynthesizerRequest.h

    流式文本語音合成。

    FileTrans.h

    錄音文件識別。

  • lib:SDK庫文件。

  • readme.md:SDK說明。

  • release.log:版本更新說明。

  • version:版本號。

編譯運行(Linux平臺編譯)

  1. 安裝工具的最低版本要求如下:

    • CMake 3.0

    • Glibc 2.5

    • Gcc 4.8.5

  2. 在Linux終端運行如下腳本。

    1. 進入SDK源碼的根目錄。

    2. 生成SDK庫文件和可執行程序:srDemo(一句話識別)、stDemo(實時語音識別)、syDemo(語音合成)、daDemo(語音對話)、fsDemo(流式文本語音合成)。

      ./scripts/build_linux.sh
    3. 查看范例使用方式。

      cd build/demo 
      ./fsDemo 

關鍵接口

基礎接口

  • NlsClient:語音處理客戶端,利用該客戶端可以進行一句話識別、實時語音識別和語音合成的語音處理任務。該客戶端為線程安全,建議全局僅創建一個實例。

    接口名

    啟用版本

    功能描述

    getInstance

    2.x

    獲取(創建)NlsClient實例。

    setLogConfig

    2.x

    設置日志文件與存儲路徑。

    setDirectHost

    3.x

    跳過DNS域名解析直接設置服務器IPV4地址,若調用則需要在startWorkThread之前。

    setAddrInFamily

    3.1.12

    設置套接口地址結構的類型,默認為AF_INET僅返回IPV4相關的地址信息,需要在startWorkThread之前調用。

    setUseSysGetAddrInfo

    3.1.13

    libeventDNS無法滿足,無法完成DNS,可調用此接口切換成系統的接口,需要在startWorkThread之前調用。

    calculateUtf8Chars

    3.1.14

    統計文本內容字符數,需要傳入UTF-8編碼的文本內容,其中1個漢字、1個英文字母或1個標點均算作1個字符。

    setSyncCallTimeout

    3.1.17

    設置同步調用模式的超時時間(ms), 0則為關閉同步模式,默認0。此模式start()后收到服務端結果再return出去,stop()后收到close()回調再return出去。

    startWorkThread

    3.x

    啟動工作線程數,默認1即啟動一個線程,若-1則啟動CPU核數的線程數。在高并發的情況下建議選擇-1。可以理解NlsClient實例初始化,必須調用。

    getVersion

    3.x

    獲取SDK版本號。

    releaseInstance

    2.x

    銷毀NlsClient對象實例。

    createFlowingSynthesizerRequest

    3.2

    創建流式文本語音合成對象,線程安全,支持高并發請求。

    releaseFlowingSynthesizerRequest

    3.2

    銷毀流式文本語音合成對象,需要在當前請求的closed事件后調用。

  • NlsToken:創建Token對象,用于申請獲取Token ID。申請新Token時需要先獲取有效時間戳,若超過有效時間則再申請。若在有效時間內多次申請Token會導致Token ID錯誤而無法使用。

    接口名

    功能描述

    setAccessKeyId

    設置阿里云賬號AccessKey ID。

    setKeySecret

    設置阿里云賬號AccessKey Secret。

    setDomain

    設置域名,非必填。

    setServerVersion

    設置API版本,非必填。

    setServerResourcePath

    設置服務路徑,非必填。

    setRegionId

    設置服務的確ID,非必填。

    setAction

    設置功能,非必填。

    applyNlsToken

    申請獲取Token ID。

    getToken

    獲取Token ID。

    getExpireTime

    獲取Token有效期時間戳(秒)。

    getErrorMsg

    獲得錯誤信息

  • NlsEvent:事件對象,您可以從中獲取Request狀態碼、云端返回結果、失敗信息等。

    接口名

    功能描述

    getStatusCode

    獲取狀態碼,正常情況為0或者20000000,失敗時對應失敗的錯誤碼。

    getErrorMessage

    TaskFailed回調中,獲取NlsRequest操作過程中出現失敗時的錯誤信息。

    getTaskId

    獲取任務的TaskId

    getBinaryData

    獲取云端返回的二進制數據。

    getAllResponse

    獲取云端返回的結果。

流式文本合成接口

接口說明以flowingSynthesizerRequest.h內容為準。

接口名

啟用版本

功能描述

setOnSynthesisStarted

3.2

設置流式文本語音合成啟動回調函數。

setOnSynthesisCompleted

3.2

設置語音合成結束回調函數。

setOnChannelClosed

2.x

設置通道關閉回調函數。

setOnTaskFailed

2.x

設置錯誤回調函數。

setOnSentenceBegin

3.2

服務端檢測到了一句話的開始的回調函數。

setOnSentenceEnd

3.2

服務端檢測到了一句話的結束,返回該句的全量時間戳的回調函數。

setOnBinaryDataReceived

2.x

設置語音合成二進制音頻數據接收回調函數。

setOnSentenceSynthesis

3.2

增量返回語音合成的結果,包含最新的音頻和時間戳、句內全量、句間增量的回調函數。

setOnMessage

3.1.16

設置服務端response message回調函數,所有回調從此回調輸出由用戶自行解析。非必填。設置后需setEnableOnMessage啟動。

setAppKey

2.x

設置AppKey。

setToken

2.x

口令認證。所有的請求都必須通過SetToken方法認證通過,才可以使用。

setUrl

2.x

設置服務URL地址。非必填。

sendText

3.2

在同一個流式TTS會話中,單次合成不超過5000字,總計不超過10萬字,其中1個漢字、1個英文字母、1個標點或1個句子中間空格均算作1個字符。

setVoice

2.x

發音人voice設置。

setVolume

2.x

音量volume設置。

setFormat

2.x

設置音頻數據編碼格式(默認是PCM,支持的格式:PCM、WAV、MP3)。

setSampleRate

2.x

音頻采樣率設置。

setSpeechRate

2.x

語速設置。

setPitchRate

2.x

語調設置。

setEnableSubtitle

2.x

是否開啟字幕功能。

setPayloadParam

2.x

參數設置,入參為JSON格式字符串。

setTimeout

2.x

設置鏈接超時時間,默認5000ms。

setContextParam

2.x

設置用戶自定義參數,入參為JSON格式字符串。

AppendHttpHeaderParam

2.x

設置用戶自定義ws階段HTTP header參數。

setSendTimeout

3.1.14

設置發送超時時間,默認5000ms。

setEnableOnMessage

3.1.16

設置開啟服務器返回消息回調。

getTaskId

3.1.17

獲得當前請求的task_id

start

2.x

啟動FlowingSynthesizerRequest

stop

3.2

結束合成任務,后續需要等待合成完畢。

cancel

2.x

不會與服務端確認關閉,直接關閉語音合成過程。

代碼示例

說明
  • 示例中將合成的音頻保存在文件中,如果您需要播放音頻且對實時性要求較高,建議使用流式播放,即邊接收語音數據邊播放,減少延時,而無需等待合成結束后再處理語音流。

  • 完整示例,參見SDK壓縮包中demo目錄的flowingSynthesizerRequest.cpp文件。

  • 調用接口前,需配置環境變量,通過環境變量讀取訪問憑證。智能語音交互的AccessKey IDAccessKey SecretAppKey的環境變量名:NLS_AK_ENVNLS_SK_ENVNLS_APPKEY_ENV

代碼示例

#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ctime>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include "nlsClient.h"
#include "nlsEvent.h"
#include "nlsToken.h"
#include "flowingSynthesizerRequest.h"

#define SAMPLE_RATE_16K 16000
#define DEFAULT_STRING_LEN 512
#define AUDIO_TEXT_LENGTH 2048

/**
 * 全局維護一個服務鑒權token和其對應的有效期時間戳,
 * 每次調用服務之前,首先判斷token是否已經過期,
 * 如果已經過期,則根據AccessKey ID和AccessKey
 * Secret重新生成一個token,并更新這個全局的token和其有效期時間戳。
 *
 * 注意:不要每次調用服務之前都重新生成新token,只需在token即將過期時重新生成即可。所有的服務并發可共用一個token。
 */
// 自定義線程參數
struct ParamStruct {
  char text[AUDIO_TEXT_LENGTH];
  char token[DEFAULT_STRING_LEN];
  char appkey[DEFAULT_STRING_LEN];
  char url[DEFAULT_STRING_LEN];

  pthread_mutex_t mtx;
};

// 自定義事件回調參數
struct ParamCallBack {
 public:
  explicit ParamCallBack(ParamStruct* param) {
    tParam = param;
    pthread_mutex_init(&mtxWord, NULL);
    pthread_cond_init(&cvWord, NULL);
  };
  ~ParamCallBack() {
    tParam = NULL;
    pthread_mutex_destroy(&mtxWord);
    pthread_cond_destroy(&cvWord);
  };

  pthread_mutex_t mtxWord;
  pthread_cond_t cvWord;

  ParamStruct* tParam;
};

std::string g_appkey = "";
std::string g_akId = "";
std::string g_akSecret = "";
std::string g_token = "";
std::string g_url = "";
std::string g_voice = "xiaoyun";
int g_threads = 1;
bool g_save_audio = true;
std::string g_text = "";
std::string g_format = "wav";
long g_expireTime = -1;
static int sample_rate = SAMPLE_RATE_16K;
static bool enableSubtitle = false;

std::vector<std::string> splitString(
    const std::string& str, const std::vector<std::string>& delimiters) {
  std::vector<std::string> result;
  size_t startPos = 0;

  // 查找字符串中的每個分隔符
  while (startPos < str.length()) {
    size_t minPos = std::string::npos;
    size_t delimiterLength = 0;

    for (std::vector<std::string>::const_iterator it = delimiters.begin();
         it != delimiters.end(); ++it) {
      std::size_t position = str.find(*it, startPos);
      // 查找最近的分隔符
      if (position != std::string::npos &&
          (minPos == std::string::npos || position < minPos)) {
        minPos = position;
        delimiterLength = it->size();
      }
    }

    // 如果找到分隔符,則提取前面的字符串
    if (minPos != std::string::npos) {
      result.push_back(str.substr(startPos, minPos - startPos));
      startPos = minPos + delimiterLength;
    } else {
      // 沒有更多分隔符,剩下的全部是一個部分
      result.push_back(str.substr(startPos));
      break;
    }
  }

  return result;
}

/**
 * 根據AccessKey ID和AccessKey Secret重新生成一個token,并獲取其有效期時間戳
 */
int generateToken(std::string akId, std::string akSecret, std::string* token,
                  long* expireTime) {
  AlibabaNlsCommon::NlsToken nlsTokenRequest;
  nlsTokenRequest.setAccessKeyId(akId);
  nlsTokenRequest.setKeySecret(akSecret);

  int retCode = nlsTokenRequest.applyNlsToken();
  /*獲取失敗原因*/
  if (retCode < 0) {
    std::cout << "Failed error code: " << retCode
              << "  error msg: " << nlsTokenRequest.getErrorMsg() << std::endl;
    return retCode;
  }

  *token = nlsTokenRequest.getToken();
  *expireTime = nlsTokenRequest.getExpireTime();

  return 0;
}

void OnSynthesisStarted(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  std::cout << "OnSynthesisStarted:"
            << "  status code: " << cbEvent->getStatusCode()
            << "  task id: " << cbEvent->getTaskId()
            << "  all response:" << cbEvent->getAllResponse() << std::endl;
}

/**
 * @brief sdk在接收到云端返回合成結束消息時, sdk內部線程上報Completed事件
 * @note 上報Completed事件之后,SDK內部會關閉識別連接通道.
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void OnSynthesisCompleted(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  std::cout
      << "OnSynthesisCompleted: "
      << ", status code: "
      << cbEvent
             ->getStatusCode()  // 獲取消息的狀態碼,成功為0或者20000000,失敗時對應失敗的錯誤碼
      << ", task id: "
      << cbEvent->getTaskId()  // 當前任務的task id,方便定位問題,建議輸出
      << std::endl;
  std::cout << "OnSynthesisCompleted: All response:"
            << cbEvent->getAllResponse()
            << std::endl;  // 獲取服務端返回的全部信息
}

/**
 * @brief 合成過程發生異常時, sdk內部線程上報TaskFailed事件
 * @note 上報TaskFailed事件之后,SDK內部會關閉識別連接通道.
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void OnSynthesisTaskFailed(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  FILE* failed_stream = fopen("synthesisTaskFailed.log", "a+");
  if (failed_stream) {
    char outbuf[1024] = {0};
    snprintf(outbuf, sizeof(outbuf),
             "OnSynthesisTaskFailed status code:%d task id:%s error mesg:%s\n",
             cbEvent->getStatusCode(), cbEvent->getTaskId(),
             cbEvent->getErrorMessage());
    std::cout << outbuf << std::endl;
    fwrite(outbuf, strlen(outbuf), 1, failed_stream);
    fclose(failed_stream);
  }
}

/**
 * @brief 識別結束或發生異常時,會關閉連接通道,
 * sdk內部線程上報ChannelCloseed事件
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void OnSynthesisChannelClosed(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = static_cast<ParamCallBack*>(cbParam);
  if (tmpParam) {
    std::cout << "OnSynthesisChannelClosed: "
              << ", All response: " << cbEvent->getAllResponse()
              << std::endl;  // 獲取服務端返回的全部信息
  }
}

/**
 * @brief 文本上報服務端之后, 收到服務端返回的二進制音頻數據,
 * SDK內部線程通過BinaryDataRecved事件上報給用戶
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 * @notice 此處切記不可做block操作,只可做音頻數據轉存. 若在此回調中做過多操作,
 *         會阻塞后續的數據回調和completed事件回調.
 */
void OnBinaryDataRecved(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  std::vector<unsigned char> data =
      cbEvent->getBinaryData();  // getBinaryData() 獲取文本合成的二進制音頻數據
  std::cout
      << "  OnBinaryDataRecved: status code: "
      << cbEvent
             ->getStatusCode()  // 獲取消息的狀態碼,成功為0或者20000000,失敗時對應失敗的錯誤碼
      << ", taskId: "
      << cbEvent->getTaskId()  // 當前任務的task id,方便定位問題,建議輸出
      << ", data size: " << data.size()  // 數據的大小
      << std::endl;

  if (g_save_audio && data.size() > 0) {
    // 以追加形式將二進制音頻數據寫入文件
    std::string dir = "./tts_audio";
    if (access(dir.c_str(), 0) == -1) {
      mkdir(dir.c_str(), S_IRWXU);
    }
    char file_name[256] = {0};
    snprintf(file_name, 256, "%s/%s.%s", dir.c_str(), cbEvent->getTaskId(),
             g_format.c_str());
    FILE* tts_stream = fopen(file_name, "a+");
    if (tts_stream) {
      fwrite((char*)&data[0], data.size(), 1, tts_stream);
      fclose(tts_stream);
    }
  }
}

void OnSentenceBegin(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  std::cout
      << "OnSentenceBegin "
      << "Response: "
      << cbEvent
             ->getAllResponse()  // 獲取消息的狀態碼,成功為0或者20000000,失敗時對應失敗的錯誤碼
      << std::endl;
}

void OnSentenceEnd(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  std::cout
      << "OnSentenceEnd "
      << "Response: "
      << cbEvent
             ->getAllResponse()  // 獲取消息的狀態碼,成功為0或者20000000,失敗時對應失敗的錯誤碼
      << std::endl;
}

/**
 * @brief 返回 tts 文本對應的日志信息,增量返回對應的字幕信息
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void OnSentenceSynthesis(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  std::cout
      << "OnSentenceSynthesis "
      << "Response: "
      << cbEvent
             ->getAllResponse()  // 獲取消息的狀態碼,成功為0或者20000000,失敗時對應失敗的錯誤碼
      << std::endl;
}

/**
 * @brief 服務端返回的所有信息會通過此回調反饋,
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void onMessage(AlibabaNls::NlsEvent* cbEvent, void* cbParam) {
  std::cout << "onMessage: All response:" << cbEvent->getAllResponse()
            << std::endl;
}

/**
 * @brief 短鏈接模式下工作線程
 *        以 createFlowingSynthesizerRequest   <----|
 *                   |                              |
 *           request->start()                       |
 *                   |                              |
 *           request->sendText()                    |
 *                   |                              |
 *           request->stop()                        |
 *                   |                              |
 *           收到OnSynthesisChannelClosed回調        |
 *                   |                              |
 *      releaseFlowingSynthesizerRequest(request) --|
 *        進行循環。
 */
void* pthreadFunc(void* arg) {
  int testCount = 0;  // 運行次數計數,用于超過設置的loop次數后退出
  bool timedwait_flag = false;

  // 從自定義線程參數中獲取token, 配置文件等參數.
  ParamStruct* tst = static_cast<ParamStruct*>(arg);
  if (tst == NULL) {
    std::cout << "arg is not valid." << std::endl;
    return NULL;
  }

  pthread_mutex_init(&(tst->mtx), NULL);

  // 初始化自定義回調參數
  ParamCallBack cbParam(tst);

  /*
   * 1. 創建流式文本語音合成FlowingSynthesizerRequest對象.
   *
   * 流式文本語音合成文檔詳見:
   * http://bestwisewords.com/zh/isi/developer-reference/streaming-text-to-speech-synthesis/
   */

  AlibabaNls::FlowingSynthesizerRequest* request =
      AlibabaNls::NlsClient::getInstance()->createFlowingSynthesizerRequest();
  if (request == NULL) {
    std::cout << "createFlowingSynthesizerRequest failed." << std::endl;
    return NULL;
  }

  /*
   * 2. 設置用于接收結果的回調
   */
  // 設置音頻合成可以開始的回調函數
  request->setOnSynthesisStarted(OnSynthesisStarted, &cbParam);
  // 設置音頻合成結束回調函數
  request->setOnSynthesisCompleted(OnSynthesisCompleted, &cbParam);
  // 設置音頻合成通道關閉回調函數
  request->setOnChannelClosed(OnSynthesisChannelClosed, &cbParam);
  // 設置異常失敗回調函數
  request->setOnTaskFailed(OnSynthesisTaskFailed, &cbParam);
  // 設置文本音頻數據接收回調函數
  request->setOnBinaryDataReceived(OnBinaryDataRecved, &cbParam);
  // 設置字幕信息
  request->setOnSentenceSynthesis(OnSentenceSynthesis, &cbParam);
  // 一句話開始
  request->setOnSentenceBegin(OnSentenceBegin, &cbParam);
  // 一句話結束
  request->setOnSentenceEnd(OnSentenceEnd, &cbParam);
  // 設置所有服務端返回信息回調函數
  // request->setOnMessage(onMessage, &cbParam);
  // 開啟所有服務端返回信息回調函數, 其他回調(除了OnBinaryDataRecved)失效
  // request->setEnableOnMessage(true);

  /*
   * 3. 設置request的相關參數
   */
  // 發音人, 包含"xiaoyun", "ruoxi", "xiaogang"等. 可選參數, 默認是xiaoyun
  request->setVoice(g_voice.c_str());
  // 音量, 范圍是0~100, 可選參數, 默認50
  request->setVolume(50);
  // 音頻編碼格式, 可選參數, 默認是wav. 支持的格式pcm, wav, mp3
  request->setFormat("wav");
  // 音頻采樣率, 包含8000, 16000. 可選參數, 默認是16000
  request->setSampleRate(sample_rate);
  // 語速, 范圍是-500~500, 可選參數, 默認是0
  request->setSpeechRate(0);
  // 語調, 范圍是-500~500, 可選參數, 默認是0
  request->setPitchRate(0);
  // 開啟字幕
  request->setEnableSubtitle(enableSubtitle);

  // 設置AppKey, 必填參數, 請參照官網申請
  if (strlen(tst->appkey) > 0) {
    request->setAppKey(tst->appkey);
  }
  // 設置賬號校驗token, 必填參數
  if (strlen(tst->token) > 0) {
    request->setToken(tst->token);
  }

  if (strlen(tst->url) > 0) {
    request->setUrl(tst->url);
  }

  // 設置鏈接超時500ms
  // request->setTimeout(500);
  // 獲取返回文本的編碼格式
  // const char* output_format = request->getOutputFormat();
  // std::cout << "text format: " << output_format << std::endl;

  /*
   * 4.
   * start()為異步操作。成功則開始返回BinaryRecv事件。失敗返回TaskFailed事件。
   */
  std::cout << "start -> pid " << pthread_self() << std::endl;
  struct timespec outtime;
  struct timeval now;
  int ret = request->start();
  testCount++;
  if (ret < 0) {
    std::cout << "start failed. pid:" << pthread_self() << std::endl;
    const char* request_info = request->dumpAllInfo();
    if (request_info) {
      std::cout << "  all info: " << request_info << std::endl;
    }
    AlibabaNls::NlsClient::getInstance()->releaseFlowingSynthesizerRequest(
        request);  // start()失敗,釋放request對象
    return NULL;
  } else {
    std::cout << "start success. pid " << pthread_self() << std::endl;
    /*
     * 等待started事件返回表示start()成功, 然后再發送音頻數據。
     * 語音服務器存在來不及處理當前請求的情況, 10s內不返回任何回調的問題,
     * 然后在10s后返回一個TaskFailed回調, 所以需要設置一個超時機制。
     */
    std::cout << "wait started callback." << std::endl;
    gettimeofday(&now, NULL);
    outtime.tv_sec = now.tv_sec + 10;
    outtime.tv_nsec = now.tv_usec * 1000;
    pthread_mutex_lock(&(cbParam.mtxWord));
    if (ETIMEDOUT == pthread_cond_timedwait(&(cbParam.cvWord),
                                            &(cbParam.mtxWord), &outtime)) {
      std::cout << "start timeout" << std::endl;
      timedwait_flag = true;
      pthread_mutex_unlock(&(cbParam.mtxWord));
      // start()調用超時,cancel()取消當次請求。
      request->cancel();
      return NULL;
    }
    pthread_mutex_unlock(&(cbParam.mtxWord));
  }

  /*
   * 5. 模擬大模型流式返回文本結果,進行逐個語音合成
   */
  std::string text_str(tst->text);
  if (!text_str.empty()) {
    const char* delims[] = {"。", "!", ";", "?", "\n"};
    std::vector<std::string> delimiters(
        delims, delims + sizeof(delims) / sizeof(delims[0]));
    std::vector<std::string> sentences = splitString(text_str, delimiters);
    for (std::vector<std::string>::const_iterator it = sentences.begin();
         it != sentences.end(); ++it) {
      std::cout << "sendText: " << *it << std::endl;
      ret = request->sendText(it->c_str());
      if (ret < 0) {
        break;
      }
      usleep(500 * 1000);
    }  // for
    if (ret < 0) {
      std::cout << "sendText failed. pid:" << pthread_self() << std::endl;
      const char* request_info = request->dumpAllInfo();
      if (request_info) {
        std::cout << "  all info: " << request_info << std::endl;
      }
      AlibabaNls::NlsClient::getInstance()->releaseFlowingSynthesizerRequest(
          request);  // start()失敗,釋放request對象
      return NULL;
    }
  }

  /*
   * 6. start成功,開始等待接收完所有合成數據。
   *    stop()為無意義接口,調用與否都會跑完全程.
   *    cancel()立即停止工作, 且不會有回調返回, 失敗返回TaskFailed事件。
   */
  //    ret = request->cancel();
  ret = request->stop();

  /*
   * 開始等待接收完所有合成數據。
   */
  if (ret == 0) {
    /*
     * 等待started事件返回表示start()成功, 然后再發送音頻數據。
     * 語音服務器存在來不及處理當前請求的情況, 10s內不返回任何回調的問題,
     * 然后在10s后返回一個TaskFailed回調, 所以需要設置一個超時機制。
     */
    // 等待closed事件后再進行釋放, 否則會出現崩潰
    std::cout << "wait closed callback." << std::endl;
    /*
     * 語音服務器存在來不及處理當前請求, 10s內不返回任何回調的問題,
     * 然后在10s后返回一個TaskFailed回調, 錯誤信息為:
     * "Gateway:IDLE_TIMEOUT:Websocket session is idle for too long time,
     * the last directive is 'XXXX'!" 所以需要設置一個超時機制.
     */
    gettimeofday(&now, NULL);
    outtime.tv_sec = now.tv_sec + 30;
    outtime.tv_nsec = now.tv_usec * 1000;
    // 等待closed事件后再進行釋放, 否則會出現崩潰
    pthread_mutex_lock(&(cbParam.mtxWord));
    if (ETIMEDOUT == pthread_cond_timedwait(&(cbParam.cvWord),
                                            &(cbParam.mtxWord), &outtime)) {
      std::cout << "stop timeout" << std::endl;
      pthread_mutex_unlock(&(cbParam.mtxWord));
      return NULL;
    }
    pthread_mutex_unlock(&(cbParam.mtxWord));
  } else {
    std::cout << "ret is " << ret << ", pid " << pthread_self() << std::endl;
  }
  gettimeofday(&now, NULL);
  std::cout << "current request task_id:" << request->getTaskId() << std::endl;
  std::cout << "stop finished. pid " << pthread_self() << " tv: " << now.tv_sec
            << std::endl;

  /*
   * 7. 完成所有工作后釋放當前請求。
   *    請在closed事件(確定完成所有工作)后再釋放, 否則容易破壞內部狀態機,
   * 會強制卸載正在運行的請求。
   */
  const char* request_info = request->dumpAllInfo();
  if (request_info) {
    std::cout << "  all info: " << request_info << std::endl;
  }
  AlibabaNls::NlsClient::getInstance()->releaseFlowingSynthesizerRequest(
      request);
  std::cout << "release Synthesizer success. pid " << pthread_self()
            << std::endl;

  pthread_mutex_destroy(&(tst->mtx));

  return NULL;
}

/**
 * 合成多個文本數據;
 * sdk多線程指一個文本數據對應一個線程, 非一個文本數據對應多個線程.
 * 示例代碼為同時開啟4個線程合成4個文件;
 * 免費用戶并發連接不能超過2個;
 */
#define AUDIO_TEXT_NUMS 4
#define AUDIO_FILE_NAME_LENGTH 32
int flowingSynthesizerMultFile(const char* appkey, int threads) {
  /**
   * 獲取當前系統時間戳,判斷token是否過期
   */
  std::time_t curTime = std::time(0);
  if (g_token.empty()) {
    if (g_expireTime - curTime < 10) {
      std::cout << "the token will be expired, please generate new token by "
                   "AccessKey-ID and AccessKey-Secret."
                << std::endl;
      int ret = generateToken(g_akId, g_akSecret, &g_token, &g_expireTime);
      if (ret < 0) {
        std::cout << "generate token failed" << std::endl;
        return -1;
      } else {
        if (g_token.empty() || g_expireTime < 0) {
          std::cout << "generate empty token" << std::endl;
          return -2;
        }
        std::cout << "token: " << g_token << std::endl;
      }
    }
  }

  /* 不要超過AUDIO_TEXT_LENGTH */
  const char texts[AUDIO_TEXT_LENGTH] = {
      "唧唧復唧唧,木蘭當戶織。不聞機杼聲,唯聞女嘆息。問女何所思,問女何所憶。"
      "女亦無所思,女亦無所憶。昨夜見軍帖,可汗大點兵。軍書十二卷,卷卷有爺名。"
      "阿爺無大兒,木蘭無長兄。愿為市鞍馬,從此替爺征。東市買駿馬,西市買鞍韉,"
      "南市買轡頭,北市買長鞭。旦辭爺娘去,暮宿黃河邊。不聞爺娘喚女聲,但聞黃河"
      "流水鳴濺濺。旦辭黃河去,暮至黑山頭。不聞爺娘喚女聲,但聞燕山胡騎鳴啾啾。"
      " 萬里赴戎機,關山度若飛。朔氣傳金柝,寒光照鐵衣。將軍百戰死,壯士十年歸"
      "。 "
      "歸來見天子,天子坐明堂。策勛十二轉,賞賜百千強。可汗問所欲,木蘭不用尚書"
      "郎,愿馳千里足,送兒還故鄉。 "
      "爺娘聞女來,出郭相扶將;阿姊聞妹來,當戶理紅妝;小弟聞姊來,磨刀霍霍向豬"
      "羊。開我東閣門,坐我西閣床。脫我戰時袍,著我舊時裳。當窗理云鬢,對鏡帖花"
      "黃。出門看火伴,火伴皆驚忙:同行十二年,不知木蘭是女郎。 "
      "雄兔腳撲朔,雌兔眼迷離;雙兔傍地走,安能辨我是雄雌?"};

  ParamStruct pa[threads];

  for (int i = 0; i < threads; i++) {
    memset(pa[i].token, 0, DEFAULT_STRING_LEN);
    memcpy(pa[i].token, g_token.c_str(), g_token.length());

    memset(pa[i].appkey, 0, DEFAULT_STRING_LEN);
    memcpy(pa[i].appkey, appkey, strlen(appkey));

    memset(pa[i].text, 0, AUDIO_TEXT_LENGTH);
    if (g_text.empty()) {
      memcpy(pa[i].text, texts, strlen(texts));
    } else {
      memcpy(pa[i].text, g_text.data(), strlen(g_text.data()));
    }

    memset(pa[i].url, 0, DEFAULT_STRING_LEN);
    if (!g_url.empty()) {
      memcpy(pa[i].url, g_url.c_str(), g_url.length());
    }
  }

  std::vector<pthread_t> pthreadId(threads);
  // 啟動四個工作線程, 同時識別四個音頻文件
  for (int j = 0; j < threads; j++) {
    pthread_create(&pthreadId[j], NULL, &pthreadFunc, (void*)&(pa[j]));
  }

  std::cout << "start pthread_join..." << std::endl;

  for (int j = 0; j < threads; j++) {
    pthread_join(pthreadId[j], NULL);
  }

  std::cout << "flowingSynthesizerMultFile exit..." << std::endl;
  return 0;
}

int main(int argc, char* argv[]) {
  std::string g_appkey = getenv("NLS_APPKEY_ENV");
  g_akId = getenv("NLS_AK_ENV");
  g_akSecret = getenv("NLS_SK_ENV");

  std::cout << " appKey: " << g_appkey << std::endl;
  std::cout << " akId: " << g_akId << std::endl;
  std::cout << " akSecret: " << g_akSecret << std::endl;
  std::cout << " voice: " << g_voice << std::endl;
  std::cout << "\n" << std::endl;

  int ret = AlibabaNls::NlsClient::getInstance()->setLogConfig(
      "log-flowingSynthesizer", AlibabaNls::LogDebug, 400, 50, NULL);
  if (ret < 0) {
    std::cout << "set log failed." << std::endl;
    return -1;
  }

  // 設置運行環境需要的套接口地址類型, 默認為AF_INET
  // 必須在startWorkThread()前調用
  // AlibabaNls::NlsClient::getInstance()->setAddrInFamily("AF_INET");

  // 私有云部署的情況下進行直連IP的設置
  // 必須在startWorkThread()前調用
  // AlibabaNls::NlsClient::getInstance()->setDirectHost("xxx.xxx.xxx.xxx");

  std::cout << "startWorkThread begin... " << std::endl;

  // 啟動工作線程, 在創建請求和啟動前必須調用此函數
  // 入參為負時, 啟動當前系統中可用的核數
  // 高并發的情況下推薦4, 單請求的情況推薦為1
  // 若高并發CPU占用率較高, 則可填-1啟用所有CPU核
  AlibabaNls::NlsClient::getInstance()->startWorkThread(1);

  std::cout << "startWorkThread finish" << std::endl;

  // 合成多個文本
  ret = flowingSynthesizerMultFile(g_appkey.c_str(), g_threads);
  if (ret) {
    std::cout << "flowingSynthesizerMultFile failed." << std::endl;
    AlibabaNls::NlsClient::releaseInstance();
    return -2;
  }

  // 所有工作完成,進程退出前,釋放nlsClient.
  // 請注意, releaseInstance()非線程安全.
  std::cout << "releaseInstance -> " << std::endl;
  AlibabaNls::NlsClient::releaseInstance();
  std::cout << "releaseInstance done." << std::endl;

  return 0;
}

狀態碼

C++ SDK狀態碼

狀態碼

狀態消息

原因

解決方案

0

Success

成功

-10

DefaultError

默認錯誤。

暫未使用。

-11

JsonParseFailed

錯誤的JSON格式。

請檢查傳入的 JSON 字符串是否符合 JSON 格式。

-12

JsonObjectError

錯誤的JSON對象。

建議重新嘗試。

-13

MallocFailed

Malloc失敗。

請檢查內存是否充足。

-14

ReallocFailed

Realloc失敗。

請檢查內存是否充足。

-15

InvalidInputParam

傳入無效的參數。

暫未使用。

-50

InvalidLogLevel

無效日志級別。

請檢查設置的Log級別。

-51

InvalidLogFileSize

無效日志文件大小。

請檢查設置的Log文件大小參數。

-52

InvalidLogFileNum

無效日志文件數量。

請檢查設置的Log文件數量參數。

-100

EncoderExistent

NLS的編碼器已存在。

建議重新嘗試。

-101

EncoderInexistent

NLS的編碼器不存在。

建議重新初始化。

-102

OpusEncoderCreateFailed

Opus編碼器創建失敗。

建議重新初始化。

-103

OggOpusEncoderCreateFailed

OggOpus編碼器創建失敗。

建議重新初始化。

-104

InvalidEncoderType

encoder類型無效。

編譯時可能關閉OPUS但是又使用,或請檢查ENCODER_TYPE

-150

EventClientEmpty

主工作線程空指針, 已釋放。

建議重新初始化,即startWorkThread()

-151

SelectThreadFailed

工作線程選擇失敗, 未初始化。

建議重新初始化,即startWorkThread()

-160

StartCommandFailed

發送start命令失敗。

建議重新嘗試

-161

InvokeStartFailed

請求狀態機不對, 導致start失敗。

請檢查當前請求是否未創建或者已經完成。

-162

InvokeSendAudioFailed

請求狀態機不對, 導致sendAudio失敗。

請檢查當前請求是否已經啟動(即收到started事件回調)或者已經完成。

-163

InvalidOpusFrameSize

opus幀長無效, 默認為640字節。

OPU編碼模式下,sendAudio一幀只接收640字節數據。

-164

InvokeStopFailed

請求狀態機不對, 導致stop失敗。

請檢查當前請求是否未啟動(即收到started事件回調)或者已經完成。

-165

InvokeCancelFailed

請求狀態機不對, 導致stop失敗。

請檢查當前請求是否未啟動(即收到started事件回調)或者已經完成。

-166

InvokeStControlFailed

請求狀態機不對, 導致stControl失敗。

請檢查當前請求是否未啟動(即收到started事件回調)或者已經完成。

-200

NlsEventEmpty

NLS事件為空。

SDK內部使用, NlsEvent幀丟失。

-201

NewNlsEventFailed

創建NlsEvent失敗。

SDK內部使用, NlsEvent幀創建失敗。

-202

NlsEventMsgEmpty

NLS事件中消息為空。

parseJsonMsg()進行解析時發現消息字符串為空。

-203

InvalidNlsEventMsgType

無效的NLS事件中消息類型。

SDK內部使用, NlsEvent幀的事件類型不合法。

-204

InvalidNlsEventMsgStatusCode

無效的NLS事件中消息狀態碼。

SDK內部使用, NlsEvent幀的事件消息狀態不合法。

-205

InvalidNlsEventMsgHeader

無效的NLS事件中消息頭。

SDK內部使用, NlsEvent幀的事件消息頭不合法。

-250

CancelledExitStatus

已調用Cancel。

暫未使用。

-251

InvalidWorkStatus

無效的工作狀態。

SDK內部使用, 當前請求內部狀態不合法。

-252

InvalidNodeQueue

WorkThread中NodeQueue無效。

SDK內部使用, 當前待運行的請求不合法,建議釋放當前請求重新嘗試。

-300

InvalidRequestParams

請求的入參無效。

SendAudio傳入的數據為空。

-301

RequestEmpty

請求是空指針。

SDK內部使用, 當前請求已經釋放,建議釋放當前請求重新嘗試。

-302

InvalidRequest

無效的請求。

SDK內部使用, 當前請求已經釋放,建議釋放當前請求重新嘗試。

-303

SetParamsEmpty

設置傳入的參數為空。

請檢查傳入的參數是否為空。

-350

GetHttpHeaderFailed

獲得http頭失敗。

SDK內部使用, 根據日志中反饋信息詳細定位。

-351

HttpGotBadStatus

http錯誤的狀態。

SDK內部使用, 根據日志中反饋信息詳細定位。

-352

WsResponsePackageFailed

解析WebSocket返回包失敗。

SDK內部使用, 根據日志中反饋信息詳細定位。

-353

WsResponsePackageEmpty

解析WebSocket返回包為空。

SDK內部使用, 根據日志中反饋信息詳細定位。

-354

WsRequestPackageEmpty

WebSocket請求包為空。

SDK內部使用, 根據日志中反饋信息詳細定位。

-355

UnknownWsFrameHeadType

未知WebSocket幀頭類型。

SDK內部使用, 根據日志中反饋信息詳細定位。

-356

InvalidWsFrameHeaderSize

無效的WebSocket幀頭大小。

SDK內部使用, 根據日志中反饋信息詳細定位。

-357

InvalidWsFrameHeaderBody

無效的WebSocket幀頭本體。

SDK內部使用, 根據日志中反饋信息詳細定位。

-358

InvalidWsFrameBody

無效的WebSocket幀本體。

SDK內部使用, 根據日志中反饋信息詳細定位。

-359

WsFrameBodyEmpty

幀數據為空, 常見為收到了臟數據。

SDK內部使用, 根據日志中反饋信息詳細定位。

-400

NodeEmpty

Node為空指針。

建議釋放當前請求重新嘗試。

-401

InvaildNodeStatus

Node所處狀態無效。

SDK內部使用, 建議釋放當前請求重新嘗試。

-402

GetAddrinfoFailed

通過DNS解析地址識別。

SDK內部使用, 請檢查當前環境的DNS是否可用。

-403

ConnectFailed

聯網失敗。

請檢查當前網絡環境是否可用。

-404

InvalidDnsSource

當前設備無DNS。

SDK內部使用, 請檢查當前環境的DNS是否可用。

-405

ParseUrlFailed

無效URl。

請檢查設置的URL是否有效。

-406

SslHandshakeFailed

SSL握手失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-407

SslCtxEmpty

SSL_CTX未空。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-408

SslNewFailed

SSL_new失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-409

SslSetFailed

SSL設置參數失敗.

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-410

SslConnectFailed

SSL_connect失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-411

SslWriteFailed

SSL發送數據失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-412

SslReadSysError

SSL接收數據收到SYSCALL錯誤。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-413

SslReadFailed

SSL接收數據失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-414

SocketFailed

創建Socket失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-415

SetSocketoptFailed

設置Socket參數失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-416

SocketConnectFailed

進行Socket鏈接失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-417

SocketWriteFailed

Socket發送數據失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-418

SocketReadFailed

Socket接收數據失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-430

NlsReceiveFailed

NLS接收幀數據失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-431

NlsReceiveEmpty

NLS接收幀數據為空。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-432

ReadFailed

接收數據失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-433

NlsSendFailed

NLS發送數據失敗。

SDK內部使用, 請檢查當前網絡環境是否可用,并再次嘗試。

-434

NewOutputBufferFailed

創建buffer失敗。

SDK內部使用, 請檢查內存是否充足。

-435

NlsEncodingFailed

音頻編碼失敗。

SDK內部使用, 建議釋放當前請求重新嘗試。

-436

EventEmpty

event為空。

SDK內部使用, 建議釋放當前請求重新嘗試。

-437

EvbufferTooMuch

evbuffer中數據太多。

SDK內部使用, 發送數據緩存已滿(16K音頻最大緩存320000,8K音頻最大緩存160000),請檢查是否發送音頻數據過頻或一次發送過多數據。

-438

EvutilSocketFalied

evutil設置參數失敗。

SDK內部使用, 建議釋放當前請求重新嘗試。

-439

InvalidExitStatus

無效的退出狀態。

請檢查是否已經cancel了當前請求。

-450

InvalidAkId

阿里云賬號AK ID無效。

請檢查阿里云賬號AK ID是否為空。

-451

InvalidAkSecret

阿里云賬號AK Secret無效。

請檢查阿里云賬號AK Secret是否為空。

-452

InvalidAppKey

項目appKey無效。

請檢查阿里云項目appKey是否為空。

-453

InvalidDomain

domain無效。

請檢查輸入的domain是否為空。

-454

InvalidAction

action無效。

請檢查輸入的action是否為空。

-455

InvalidServerVersion

ServerVersion無效

請檢查輸入的ServerVersion是否為空。

-456

InvalidServerResource

ServerResource無效。

請檢查輸入的ServerResource是否為空。

-457

InvalidRegionId

RegionId無效。

請檢查輸入的Region Id是否為空。

-500

InvalidFileLink

無效的錄音文件鏈接

錄音文件轉寫文件鏈接為空。

-501

ErrorStatusCode

錯誤的狀態碼。

錄音文件轉寫返回錯誤,詳見錯誤碼。

-502

IconvOpenFailed

申請轉換描述失敗。

UTF8與GBK轉換失敗。

-503

IconvFailed

編碼轉換失敗。

UTF8與GBK轉換失敗。

-504

ClientRequestFaild

賬號客戶端請求失敗。

錄音文件轉寫返回失敗。

-999

NlsMaxErrorCode

其他狀態碼

狀態碼

狀態消息

原因

解決方案

10000001

NewSslCtxFailed

SSL: couldn't create a context!

建議重新初始化。

10000002

DefaultErrorCode

return of SSL_read: error:00000000:lib(0):func(0):reason(0)

建議重新嘗試。

return of SSL_read: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init

10000003

SysErrorCode

系統錯誤

根據系統反饋的錯誤信息進行處理。

10000004

EmptyUrl

URL: The url is empty.

傳入的URL為空, 請重新填寫正確URL。

10000005

InvalidWsUrl

Could not parse WebSocket url:

傳入的URL格式錯誤, 請重新填寫正確URL。

10000007

JsonStringParseFailed

JSON: Json parse failed.

JSON格式異常, 請通過日志查看具體的錯誤點。

10000008

UnknownWsHeadType

WEBSOCKET: unkown head type.

聯網失敗,請檢查本機DNS解析和URL是否有效。

10000009

HttpConnectFailed

HTTP: connect failed.

與云端連接失敗,請檢查網絡后,重試。

10000010

MemNotEnough

內存不足

請檢查內存是否充足。

10000015

SysConnectFailed

connect failed.

聯網失敗,請檢查本機DNS解析和URL是否有效。

10000100

HttpGotBadStatusWith403

Got bad status host=xxxxx line=HTTP/1.1 403 Forbidden

鏈接被拒,請檢查賬號特別是token是否過期。

10000101

EvSendTimeout

Send timeout. socket error:

libevent發送event超時,請檢查回調中是否有耗時任務,或并發過大導致無法及>時處理事件。

10000102

EvRecvTimeout

Recv timeout. socket error:

libevent接收event超時,請檢查回調中是否有耗時任務,或并發過大導致無法及>時處理事件。

10000103

EvUnknownEvent

Unknown event:

未知的libevent事件,建議重新嘗試。

10000104

OpNowInProgress

Operation now in progress

鏈接正在進行中,建議重新嘗試。

10000105

BrokenPipe

Broken pipe

pipe處理不過來,建議重新嘗試。

10000110

TokenHasExpired

Gateway:ACCESS_DENIED:The token 'xxx' has expired!

請更新Token。

10000111

TokenIsInvalid

Meta:ACCESS_DENIED:The token 'xxx' is invalid!

請檢查Token的有效性。

10000112

NoPrivilegeToVoice

Gateway:ACCESS_DENIED:No privilege to this voice! (voice: zhinan, privilege: 0)

此發音人無權使用。

10000113

MissAuthHeader

Gateway:ACCESS_DENIED:Missing authorization header!

請檢查賬號是否有權限,或并發是否在限度內。

10000120

Utf8ConvertError

utf8ToGbk failed

UTF-8轉碼失敗,常為系統問題,建議重新嘗試。

20000000

SuccessStatusCode

成功

服務端響應狀態碼

關于服務狀態碼,請參見服務狀態碼