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

C++ SDK

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

前提條件

下載安裝

SDK下載

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

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

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

    最新SDK包

    平臺

    MD5

    alibabacloud-nls-cpp-sdk3.2.0a-master_e90fba0.zip

    SDK源碼

    ea8c14dbdcb6f587488eab6de2767b19

    NlsCppSdk_Linux-x86_64_3.2.0a_e90fba0.tar.gz

    Linux x86_64

    3f107f234771190a0dca4c1d263e2b47

    說明

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

    其中:

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

    • NlsCppSdk_<平臺>_<版本號>_<github commit id>.tar.gz為對應(yīng)平臺下開發(fā)需要的SDK包,詳見內(nèi)部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源碼中,語音服務(wù)范例音頻,可用于功能測試,如下表所示。

    文件名

    描述

    • test0.wav

    • test1.wav

    • test2.wav

    • test3.wav

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

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

    文件名

    描述

    nlsClient.h

    SDK實例。

    nlsEvent.h

    回調(diào)事件說明。

    nlsGlobal.h

    SDK全局頭文件。

    nlsToken.h

    SDK Access Token實例。

    iNlsRequest.h

    NLS請求基礎(chǔ)頭文件。

    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庫文件和可執(zhí)行程序:srDemo(一句話識別)、stDemo(實時語音識別)、syDemo(語音合成)、daDemo(語音對話)、fsDemo(流式文本語音合成)。

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

      cd build/demo 
      ./fsDemo 

關(guān)鍵接口

基礎(chǔ)接口

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

    接口名

    啟用版本

    功能描述

    getInstance

    2.x

    獲取(創(chuàng)建)NlsClient實例。

    setLogConfig

    2.x

    設(shè)置日志文件與存儲路徑。

    setDirectHost

    3.x

    跳過DNS域名解析直接設(shè)置服務(wù)器IPV4地址,若調(diào)用則需要在startWorkThread之前。

    setAddrInFamily

    3.1.12

    設(shè)置套接口地址結(jié)構(gòu)的類型,默認為AF_INET僅返回IPV4相關(guān)的地址信息,需要在startWorkThread之前調(diào)用。

    setUseSysGetAddrInfo

    3.1.13

    libeventDNS無法滿足,無法完成DNS,可調(diào)用此接口切換成系統(tǒng)的接口,需要在startWorkThread之前調(diào)用。

    calculateUtf8Chars

    3.1.14

    統(tǒng)計文本內(nèi)容字符數(shù),需要傳入UTF-8編碼的文本內(nèi)容,其中1個漢字、1個英文字母或1個標點均算作1個字符。

    setSyncCallTimeout

    3.1.17

    設(shè)置同步調(diào)用模式的超時時間(ms), 0則為關(guān)閉同步模式,默認0。此模式start()后收到服務(wù)端結(jié)果再return出去,stop()后收到close()回調(diào)再return出去。

    startWorkThread

    3.x

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

    getVersion

    3.x

    獲取SDK版本號。

    releaseInstance

    2.x

    銷毀NlsClient對象實例。

    createFlowingSynthesizerRequest

    3.2

    創(chuàng)建流式文本語音合成對象,線程安全,支持高并發(fā)請求。

    releaseFlowingSynthesizerRequest

    3.2

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

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

    接口名

    功能描述

    setAccessKeyId

    設(shè)置阿里云賬號AccessKey ID。

    setKeySecret

    設(shè)置阿里云賬號AccessKey Secret。

    setDomain

    設(shè)置域名,非必填。

    setServerVersion

    設(shè)置API版本,非必填。

    setServerResourcePath

    設(shè)置服務(wù)路徑,非必填。

    setRegionId

    設(shè)置服務(wù)的確ID,非必填。

    setAction

    設(shè)置功能,非必填。

    applyNlsToken

    申請獲取Token ID。

    getToken

    獲取Token ID。

    getExpireTime

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

    getErrorMsg

    獲得錯誤信息

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

    接口名

    功能描述

    getStatusCode

    獲取狀態(tài)碼,正常情況為0或者20000000,失敗時對應(yīng)失敗的錯誤碼。

    getErrorMessage

    TaskFailed回調(diào)中,獲取NlsRequest操作過程中出現(xiàn)失敗時的錯誤信息。

    getTaskId

    獲取任務(wù)的TaskId

    getBinaryData

    獲取云端返回的二進制數(shù)據(jù)。

    getAllResponse

    獲取云端返回的結(jié)果。

流式文本合成接口

接口說明以flowingSynthesizerRequest.h內(nèi)容為準。

接口名

啟用版本

功能描述

setOnSynthesisStarted

3.2

設(shè)置流式文本語音合成啟動回調(diào)函數(shù)。

setOnSynthesisCompleted

3.2

設(shè)置語音合成結(jié)束回調(diào)函數(shù)。

setOnChannelClosed

2.x

設(shè)置通道關(guān)閉回調(diào)函數(shù)。

setOnTaskFailed

2.x

設(shè)置錯誤回調(diào)函數(shù)。

setOnSentenceBegin

3.2

服務(wù)端檢測到了一句話的開始的回調(diào)函數(shù)。

setOnSentenceEnd

3.2

服務(wù)端檢測到了一句話的結(jié)束,返回該句的全量時間戳的回調(diào)函數(shù)。

setOnBinaryDataReceived

2.x

設(shè)置語音合成二進制音頻數(shù)據(jù)接收回調(diào)函數(shù)。

setOnSentenceSynthesis

3.2

增量返回語音合成的結(jié)果,包含最新的音頻和時間戳、句內(nèi)全量、句間增量的回調(diào)函數(shù)。

setOnMessage

3.1.16

設(shè)置服務(wù)端response message回調(diào)函數(shù),所有回調(diào)從此回調(diào)輸出由用戶自行解析。非必填。設(shè)置后需setEnableOnMessage啟動。

setAppKey

2.x

設(shè)置AppKey。

setToken

2.x

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

setUrl

2.x

設(shè)置服務(wù)URL地址。非必填。

sendText

3.2

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

setVoice

2.x

發(fā)音人voice設(shè)置。

setVolume

2.x

音量volume設(shè)置。

setFormat

2.x

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

setSampleRate

2.x

音頻采樣率設(shè)置。

setSpeechRate

2.x

語速設(shè)置。

setPitchRate

2.x

語調(diào)設(shè)置。

setEnableSubtitle

2.x

是否開啟字幕功能。

setPayloadParam

2.x

參數(shù)設(shè)置,入?yún)镴SON格式字符串。

setTimeout

2.x

設(shè)置鏈接超時時間,默認5000ms。

setContextParam

2.x

設(shè)置用戶自定義參數(shù),入?yún)镴SON格式字符串。

AppendHttpHeaderParam

2.x

設(shè)置用戶自定義ws階段HTTP header參數(shù)。

setSendTimeout

3.1.14

設(shè)置發(fā)送超時時間,默認5000ms。

setEnableOnMessage

3.1.16

設(shè)置開啟服務(wù)器返回消息回調(diào)。

getTaskId

3.1.17

獲得當前請求的task_id

start

2.x

啟動FlowingSynthesizerRequest

stop

3.2

結(jié)束合成任務(wù),后續(xù)需要等待合成完畢。

cancel

2.x

不會與服務(wù)端確認關(guān)閉,直接關(guān)閉語音合成過程。

代碼示例

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

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

  • 調(diào)用接口前,需配置環(huán)境變量,通過環(huán)境變量讀取訪問憑證。智能語音交互的AccessKey IDAccessKey SecretAppKey的環(huán)境變量名: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

/**
 * 全局維護一個服務(wù)鑒權(quán)token和其對應(yīng)的有效期時間戳,
 * 每次調(diào)用服務(wù)之前,首先判斷token是否已經(jīng)過期,
 * 如果已經(jīng)過期,則根據(jù)AccessKey ID和AccessKey
 * Secret重新生成一個token,并更新這個全局的token和其有效期時間戳。
 *
 * 注意:不要每次調(diào)用服務(wù)之前都重新生成新token,只需在token即將過期時重新生成即可。所有的服務(wù)并發(fā)可共用一個token。
 */
// 自定義線程參數(shù)
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;
};

// 自定義事件回調(diào)參數(shù)
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;
}

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

/**
 * @brief 合成過程發(fā)生異常時, sdk內(nèi)部線程上報TaskFailed事件
 * @note 上報TaskFailed事件之后,SDK內(nèi)部會關(guān)閉識別連接通道.
 * @param cbEvent 回調(diào)事件結(jié)構(gòu), 詳見nlsEvent.h
 * @param cbParam 回調(diào)自定義參數(shù),默認為NULL, 可以根據(jù)需求自定義參數(shù)
 * @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 識別結(jié)束或發(fā)生異常時,會關(guān)閉連接通道,
 * sdk內(nèi)部線程上報ChannelCloseed事件
 * @param cbEvent 回調(diào)事件結(jié)構(gòu), 詳見nlsEvent.h
 * @param cbParam 回調(diào)自定義參數(shù),默認為NULL, 可以根據(jù)需求自定義參數(shù)
 * @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;  // 獲取服務(wù)端返回的全部信息
  }
}

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

  if (g_save_audio && data.size() > 0) {
    // 以追加形式將二進制音頻數(shù)據(jù)寫入文件
    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()  // 獲取消息的狀態(tài)碼,成功為0或者20000000,失敗時對應(yīng)失敗的錯誤碼
      << std::endl;
}

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

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

/**
 * @brief 服務(wù)端返回的所有信息會通過此回調(diào)反饋,
 * @param cbEvent 回調(diào)事件結(jié)構(gòu), 詳見nlsEvent.h
 * @param cbParam 回調(diào)自定義參數(shù),默認為NULL, 可以根據(jù)需求自定義參數(shù)
 * @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回調(diào)        |
 *                   |                              |
 *      releaseFlowingSynthesizerRequest(request) --|
 *        進行循環(huán)。
 */
void* pthreadFunc(void* arg) {
  int testCount = 0;  // 運行次數(shù)計數(shù),用于超過設(shè)置的loop次數(shù)后退出
  bool timedwait_flag = false;

  // 從自定義線程參數(shù)中獲取token, 配置文件等參數(shù).
  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);

  // 初始化自定義回調(diào)參數(shù)
  ParamCallBack cbParam(tst);

  /*
   * 1. 創(chuàng)建流式文本語音合成FlowingSynthesizerRequest對象.
   *
   * 流式文本語音合成文檔詳見:
   * http://m.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. 設(shè)置用于接收結(jié)果的回調(diào)
   */
  // 設(shè)置音頻合成可以開始的回調(diào)函數(shù)
  request->setOnSynthesisStarted(OnSynthesisStarted, &cbParam);
  // 設(shè)置音頻合成結(jié)束回調(diào)函數(shù)
  request->setOnSynthesisCompleted(OnSynthesisCompleted, &cbParam);
  // 設(shè)置音頻合成通道關(guān)閉回調(diào)函數(shù)
  request->setOnChannelClosed(OnSynthesisChannelClosed, &cbParam);
  // 設(shè)置異常失敗回調(diào)函數(shù)
  request->setOnTaskFailed(OnSynthesisTaskFailed, &cbParam);
  // 設(shè)置文本音頻數(shù)據(jù)接收回調(diào)函數(shù)
  request->setOnBinaryDataReceived(OnBinaryDataRecved, &cbParam);
  // 設(shè)置字幕信息
  request->setOnSentenceSynthesis(OnSentenceSynthesis, &cbParam);
  // 一句話開始
  request->setOnSentenceBegin(OnSentenceBegin, &cbParam);
  // 一句話結(jié)束
  request->setOnSentenceEnd(OnSentenceEnd, &cbParam);
  // 設(shè)置所有服務(wù)端返回信息回調(diào)函數(shù)
  // request->setOnMessage(onMessage, &cbParam);
  // 開啟所有服務(wù)端返回信息回調(diào)函數(shù), 其他回調(diào)(除了OnBinaryDataRecved)失效
  // request->setEnableOnMessage(true);

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

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

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

  // 設(shè)置鏈接超時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()成功, 然后再發(fā)送音頻數(shù)據(jù)。
     * 語音服務(wù)器存在來不及處理當前請求的情況, 10s內(nèi)不返回任何回調(diào)的問題,
     * 然后在10s后返回一個TaskFailed回調(diào), 所以需要設(shè)置一個超時機制。
     */
    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()調(diào)用超時,cancel()取消當次請求。
      request->cancel();
      return NULL;
    }
    pthread_mutex_unlock(&(cbParam.mtxWord));
  }

  /*
   * 5. 模擬大模型流式返回文本結(jié)果,進行逐個語音合成
   */
  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成功,開始等待接收完所有合成數(shù)據(jù)。
   *    stop()為無意義接口,調(diào)用與否都會跑完全程.
   *    cancel()立即停止工作, 且不會有回調(diào)返回, 失敗返回TaskFailed事件。
   */
  //    ret = request->cancel();
  ret = request->stop();

  /*
   * 開始等待接收完所有合成數(shù)據(jù)。
   */
  if (ret == 0) {
    /*
     * 等待started事件返回表示start()成功, 然后再發(fā)送音頻數(shù)據(jù)。
     * 語音服務(wù)器存在來不及處理當前請求的情況, 10s內(nèi)不返回任何回調(diào)的問題,
     * 然后在10s后返回一個TaskFailed回調(diào), 所以需要設(shè)置一個超時機制。
     */
    // 等待closed事件后再進行釋放, 否則會出現(xiàn)崩潰
    std::cout << "wait closed callback." << std::endl;
    /*
     * 語音服務(wù)器存在來不及處理當前請求, 10s內(nèi)不返回任何回調(diào)的問題,
     * 然后在10s后返回一個TaskFailed回調(diào), 錯誤信息為:
     * "Gateway:IDLE_TIMEOUT:Websocket session is idle for too long time,
     * the last directive is 'XXXX'!" 所以需要設(shè)置一個超時機制.
     */
    gettimeofday(&now, NULL);
    outtime.tv_sec = now.tv_sec + 30;
    outtime.tv_nsec = now.tv_usec * 1000;
    // 等待closed事件后再進行釋放, 否則會出現(xiàn)崩潰
    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事件(確定完成所有工作)后再釋放, 否則容易破壞內(nèi)部狀態(tài)機,
   * 會強制卸載正在運行的請求。
   */
  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;
}

/**
 * 合成多個文本數(shù)據(jù);
 * sdk多線程指一個文本數(shù)據(jù)對應(yīng)一個線程, 非一個文本數(shù)據(jù)對應(yīng)多個線程.
 * 示例代碼為同時開啟4個線程合成4個文件;
 * 免費用戶并發(fā)連接不能超過2個;
 */
#define AUDIO_TEXT_NUMS 4
#define AUDIO_FILE_NAME_LENGTH 32
int flowingSynthesizerMultFile(const char* appkey, int threads) {
  /**
   * 獲取當前系統(tǒng)時間戳,判斷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] = {
      "唧唧復(fù)唧唧,木蘭當戶織。不聞機杼聲,唯聞女嘆息。問女何所思,問女何所憶。"
      "女亦無所思,女亦無所憶。昨夜見軍帖,可汗大點兵。軍書十二卷,卷卷有爺名。"
      "阿爺無大兒,木蘭無長兄。愿為市鞍馬,從此替爺征。東市買駿馬,西市買鞍韉,"
      "南市買轡頭,北市買長鞭。旦辭爺娘去,暮宿黃河邊。不聞爺娘喚女聲,但聞黃河"
      "流水鳴濺濺。旦辭黃河去,暮至黑山頭。不聞爺娘喚女聲,但聞燕山胡騎鳴啾啾。"
      " 萬里赴戎機,關(guān)山度若飛。朔氣傳金柝,寒光照鐵衣。將軍百戰(zhàn)死,壯士十年歸"
      "。 "
      "歸來見天子,天子坐明堂。策勛十二轉(zhuǎn),賞賜百千強。可汗問所欲,木蘭不用尚書"
      "郎,愿馳千里足,送兒還故鄉(xiāng)。 "
      "爺娘聞女來,出郭相扶將;阿姊聞妹來,當戶理紅妝;小弟聞姊來,磨刀霍霍向豬"
      "羊。開我東閣門,坐我西閣床。脫我戰(zhàn)時袍,著我舊時裳。當窗理云鬢,對鏡帖花"
      "黃。出門看火伴,火伴皆驚忙:同行十二年,不知木蘭是女郎。 "
      "雄兔腳撲朔,雌兔眼迷離;雙兔傍地走,安能辨我是雄雌?"};

  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;
  }

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

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

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

  // 啟動工作線程, 在創(chuàng)建請求和啟動前必須調(diào)用此函數(shù)
  // 入?yún)樨摃r, 啟動當前系統(tǒng)中可用的核數(shù)
  // 高并發(fā)的情況下推薦4, 單請求的情況推薦為1
  // 若高并發(fā)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;
}

狀態(tài)碼

C++ SDK狀態(tài)碼

狀態(tài)碼

狀態(tài)消息

原因

解決方案

0

Success

成功

-10

DefaultError

默認錯誤。

暫未使用。

-11

JsonParseFailed

錯誤的JSON格式。

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

-12

JsonObjectError

錯誤的JSON對象。

建議重新嘗試。

-13

MallocFailed

Malloc失敗。

請檢查內(nèi)存是否充足。

-14

ReallocFailed

Realloc失敗。

請檢查內(nèi)存是否充足。

-15

InvalidInputParam

傳入無效的參數(shù)。

暫未使用。

-50

InvalidLogLevel

無效日志級別。

請檢查設(shè)置的Log級別。

-51

InvalidLogFileSize

無效日志文件大小。

請檢查設(shè)置的Log文件大小參數(shù)。

-52

InvalidLogFileNum

無效日志文件數(shù)量。

請檢查設(shè)置的Log文件數(shù)量參數(shù)。

-100

EncoderExistent

NLS的編碼器已存在。

建議重新嘗試。

-101

EncoderInexistent

NLS的編碼器不存在。

建議重新初始化。

-102

OpusEncoderCreateFailed

Opus編碼器創(chuàng)建失敗。

建議重新初始化。

-103

OggOpusEncoderCreateFailed

OggOpus編碼器創(chuàng)建失敗。

建議重新初始化。

-104

InvalidEncoderType

encoder類型無效。

編譯時可能關(guān)閉OPUS但是又使用,或請檢查ENCODER_TYPE

-150

EventClientEmpty

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

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

-151

SelectThreadFailed

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

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

-160

StartCommandFailed

發(fā)送start命令失敗。

建議重新嘗試

-161

InvokeStartFailed

請求狀態(tài)機不對, 導(dǎo)致start失敗。

請檢查當前請求是否未創(chuàng)建或者已經(jīng)完成。

-162

InvokeSendAudioFailed

請求狀態(tài)機不對, 導(dǎo)致sendAudio失敗。

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

-163

InvalidOpusFrameSize

opus幀長無效, 默認為640字節(jié)。

OPU編碼模式下,sendAudio一幀只接收640字節(jié)數(shù)據(jù)。

-164

InvokeStopFailed

請求狀態(tài)機不對, 導(dǎo)致stop失敗。

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

-165

InvokeCancelFailed

請求狀態(tài)機不對, 導(dǎo)致stop失敗。

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

-166

InvokeStControlFailed

請求狀態(tài)機不對, 導(dǎo)致stControl失敗。

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

-200

NlsEventEmpty

NLS事件為空。

SDK內(nèi)部使用, NlsEvent幀丟失。

-201

NewNlsEventFailed

創(chuàng)建NlsEvent失敗。

SDK內(nèi)部使用, NlsEvent幀創(chuàng)建失敗。

-202

NlsEventMsgEmpty

NLS事件中消息為空。

parseJsonMsg()進行解析時發(fā)現(xiàn)消息字符串為空。

-203

InvalidNlsEventMsgType

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

SDK內(nèi)部使用, NlsEvent幀的事件類型不合法。

-204

InvalidNlsEventMsgStatusCode

無效的NLS事件中消息狀態(tài)碼。

SDK內(nèi)部使用, NlsEvent幀的事件消息狀態(tài)不合法。

-205

InvalidNlsEventMsgHeader

無效的NLS事件中消息頭。

SDK內(nèi)部使用, NlsEvent幀的事件消息頭不合法。

-250

CancelledExitStatus

已調(diào)用Cancel。

暫未使用。

-251

InvalidWorkStatus

無效的工作狀態(tài)。

SDK內(nèi)部使用, 當前請求內(nèi)部狀態(tài)不合法。

-252

InvalidNodeQueue

WorkThread中NodeQueue無效。

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

-300

InvalidRequestParams

請求的入?yún)o效。

SendAudio傳入的數(shù)據(jù)為空。

-301

RequestEmpty

請求是空指針。

SDK內(nèi)部使用, 當前請求已經(jīng)釋放,建議釋放當前請求重新嘗試。

-302

InvalidRequest

無效的請求。

SDK內(nèi)部使用, 當前請求已經(jīng)釋放,建議釋放當前請求重新嘗試。

-303

SetParamsEmpty

設(shè)置傳入的參數(shù)為空。

請檢查傳入的參數(shù)是否為空。

-350

GetHttpHeaderFailed

獲得http頭失敗。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-351

HttpGotBadStatus

http錯誤的狀態(tài)。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-352

WsResponsePackageFailed

解析WebSocket返回包失敗。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-353

WsResponsePackageEmpty

解析WebSocket返回包為空。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-354

WsRequestPackageEmpty

WebSocket請求包為空。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-355

UnknownWsFrameHeadType

未知WebSocket幀頭類型。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-356

InvalidWsFrameHeaderSize

無效的WebSocket幀頭大小。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-357

InvalidWsFrameHeaderBody

無效的WebSocket幀頭本體。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-358

InvalidWsFrameBody

無效的WebSocket幀本體。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-359

WsFrameBodyEmpty

幀數(shù)據(jù)為空, 常見為收到了臟數(shù)據(jù)。

SDK內(nèi)部使用, 根據(jù)日志中反饋信息詳細定位。

-400

NodeEmpty

Node為空指針。

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

-401

InvaildNodeStatus

Node所處狀態(tài)無效。

SDK內(nèi)部使用, 建議釋放當前請求重新嘗試。

-402

GetAddrinfoFailed

通過DNS解析地址識別。

SDK內(nèi)部使用, 請檢查當前環(huán)境的DNS是否可用。

-403

ConnectFailed

聯(lián)網(wǎng)失敗。

請檢查當前網(wǎng)絡(luò)環(huán)境是否可用。

-404

InvalidDnsSource

當前設(shè)備無DNS。

SDK內(nèi)部使用, 請檢查當前環(huán)境的DNS是否可用。

-405

ParseUrlFailed

無效URl。

請檢查設(shè)置的URL是否有效。

-406

SslHandshakeFailed

SSL握手失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-407

SslCtxEmpty

SSL_CTX未空。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-408

SslNewFailed

SSL_new失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-409

SslSetFailed

SSL設(shè)置參數(shù)失敗.

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-410

SslConnectFailed

SSL_connect失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-411

SslWriteFailed

SSL發(fā)送數(shù)據(jù)失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-412

SslReadSysError

SSL接收數(shù)據(jù)收到SYSCALL錯誤。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-413

SslReadFailed

SSL接收數(shù)據(jù)失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-414

SocketFailed

創(chuàng)建Socket失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-415

SetSocketoptFailed

設(shè)置Socket參數(shù)失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-416

SocketConnectFailed

進行Socket鏈接失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-417

SocketWriteFailed

Socket發(fā)送數(shù)據(jù)失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-418

SocketReadFailed

Socket接收數(shù)據(jù)失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-430

NlsReceiveFailed

NLS接收幀數(shù)據(jù)失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-431

NlsReceiveEmpty

NLS接收幀數(shù)據(jù)為空。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-432

ReadFailed

接收數(shù)據(jù)失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-433

NlsSendFailed

NLS發(fā)送數(shù)據(jù)失敗。

SDK內(nèi)部使用, 請檢查當前網(wǎng)絡(luò)環(huán)境是否可用,并再次嘗試。

-434

NewOutputBufferFailed

創(chuàng)建buffer失敗。

SDK內(nèi)部使用, 請檢查內(nèi)存是否充足。

-435

NlsEncodingFailed

音頻編碼失敗。

SDK內(nèi)部使用, 建議釋放當前請求重新嘗試。

-436

EventEmpty

event為空。

SDK內(nèi)部使用, 建議釋放當前請求重新嘗試。

-437

EvbufferTooMuch

evbuffer中數(shù)據(jù)太多。

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

-438

EvutilSocketFalied

evutil設(shè)置參數(shù)失敗。

SDK內(nèi)部使用, 建議釋放當前請求重新嘗試。

-439

InvalidExitStatus

無效的退出狀態(tài)。

請檢查是否已經(jīng)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

無效的錄音文件鏈接

錄音文件轉(zhuǎn)寫文件鏈接為空。

-501

ErrorStatusCode

錯誤的狀態(tài)碼。

錄音文件轉(zhuǎn)寫返回錯誤,詳見錯誤碼。

-502

IconvOpenFailed

申請轉(zhuǎn)換描述失敗。

UTF8與GBK轉(zhuǎn)換失敗。

-503

IconvFailed

編碼轉(zhuǎn)換失敗。

UTF8與GBK轉(zhuǎn)換失敗。

-504

ClientRequestFaild

賬號客戶端請求失敗。

錄音文件轉(zhuǎn)寫返回失敗。

-999

NlsMaxErrorCode

其他狀態(tài)碼

狀態(tài)碼

狀態(tài)消息

原因

解決方案

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

系統(tǒng)錯誤

根據(jù)系統(tǒng)反饋的錯誤信息進行處理。

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.

聯(lián)網(wǎng)失敗,請檢查本機DNS解析和URL是否有效。

10000009

HttpConnectFailed

HTTP: connect failed.

與云端連接失敗,請檢查網(wǎng)絡(luò)后,重試。

10000010

MemNotEnough

內(nèi)存不足

請檢查內(nèi)存是否充足。

10000015

SysConnectFailed

connect failed.

聯(lián)網(wǎng)失敗,請檢查本機DNS解析和URL是否有效。

10000100

HttpGotBadStatusWith403

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

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

10000101

EvSendTimeout

Send timeout. socket error:

libevent發(fā)送event超時,請檢查回調(diào)中是否有耗時任務(wù),或并發(fā)過大導(dǎo)致無法及>時處理事件。

10000102

EvRecvTimeout

Recv timeout. socket error:

libevent接收event超時,請檢查回調(diào)中是否有耗時任務(wù),或并發(fā)過大導(dǎo)致無法及>時處理事件。

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)

此發(fā)音人無權(quán)使用。

10000113

MissAuthHeader

Gateway:ACCESS_DENIED:Missing authorization header!

請檢查賬號是否有權(quán)限,或并發(fā)是否在限度內(nèi)。

10000120

Utf8ConvertError

utf8ToGbk failed

UTF-8轉(zhuǎn)碼失敗,常為系統(tǒng)問題,建議重新嘗試。

20000000

SuccessStatusCode

成功

服務(wù)端響應(yīng)狀態(tài)碼

關(guān)于服務(wù)狀態(tài)碼,請參見服務(wù)狀態(tài)碼