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

C++ SDK

更新時(shí)間:

本文介紹如何使用阿里云智能語音交互提供的C++ SDK,包括SDK的安裝方法、SDK代碼示例以及常見問題等。

SDK下載

說明
  • 當(dāng)前最新版本:3.1.17,支持Linux、Windows平臺(tái)。發(fā)布日期:2023年08月09日。

  • 使用SDK前,請(qǐng)先閱讀接口說明,詳情請(qǐng)參見接口說明

  • 該版本C++ SDK API 3.1和上一版本API 2.0(已下線)定義有區(qū)別,本文以當(dāng)前版本為例進(jìn)行介紹。

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

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

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

    最新SDK包

    平臺(tái)

    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

    NlsCppSdk_Linux-aarch64_3.1.15_fa30fba.tar.gz

    Linux aarch64

    76c34a3ab397d7285963a139b9270ff4

    NlsCppSdk_Windows_3.1.16_4776504.zip

    Windows

    c428e5cf1295d8933d23a4945683e250

    其中:

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

    • NlsCppSdk_<平臺(tái)>_<版本號(hào)>_<github commit id>.tar.gz為對(duì)應(yīng)平臺(tái)下開發(fā)需要的SDK包,詳見內(nèi)部readme.md。

SDK包文件說明

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

  • CMakeLists.txt:SDK源碼中,以Linux平臺(tái)為例的示例代碼工程CMakeList文件。

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

  • 文件名

    描述

    speechRecognizerDemo.cpp

    一句話識(shí)別示例。

    speechSynthesizerDemo.cpp

    語音合成示例。

    speechTranscriberDemo.cpp

    實(shí)時(shí)語音識(shí)別示例。

    fileTransferDemo.cpp

    錄音文件識(shí)別示例。

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

  • 文件名

    描述

    • test0.wav

    • test1.wav

    • test2.wav

    • test3.wav

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

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

    文件名

    描述

    nlsClient.h

    SDK實(shí)例。

    nlsEvent.h

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

    nlsGlobal.h

    SDK全局頭文件。

    nlsToken.h

    SDK Access Token實(shí)例。

    iNlsRequest.h

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

    speechRecognizerRequest.h

    一句話識(shí)別。

    speechSynthesizerRequest.h

    語音合成、長(zhǎng)文本語音合成。

    speechTranscriberRequest.h

    實(shí)時(shí)音頻流識(shí)別。

    FileTrans.h

    錄音文件識(shí)別。

  • lib:SDK庫(kù)文件。

  • readme.md:SDK說明。

  • release.log:版本說明。

  • version:版本號(hào)。

編譯運(yùn)行

Linux平臺(tái)編譯

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

    • CMake 3.0

    • Glibc 2.5

    • Gcc 4.8.5

  2. 在Linux終端運(yùn)行如下腳本。

    1. 進(jìn)入SDK源碼的根目錄。

    2. 生成SDK庫(kù)文件和可執(zhí)行程序:srDemo(一句話識(shí)別)、stDemo(實(shí)時(shí)語音識(shí)別)、syDemo(語音合成)、daDemo(語音對(duì)話)。

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

      cd build/demo 
      ./syDemo 

Windows平臺(tái)編譯

推薦直接使用已經(jīng)編譯好的庫(kù)NlsCppSdk_Windows_<version>_<github commit id>.zip進(jìn)行集成。若有編譯需求,請(qǐng)下載alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip并解壓到本地,或從GitHub獲取最新代碼,然后參考其中readme.md的編譯步驟。

關(guān)鍵接口

  • 基礎(chǔ)接口

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

      接口名

      啟用版本

      功能描述

      getInstance

      2.x

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

      setLogConfig

      2.x

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

      setDirectHost

      3.x

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

      setAddrInFamily

      3.1.12

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

      setUseSysGetAddrInfo

      3.1.13

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

      calculateUtf8Chars

      3.1.14

      統(tǒng)計(jì)文本內(nèi)容字符數(shù),需要傳入U(xiǎn)TF-8編碼的文本內(nèi)容,其中1個(gè)漢字、1個(gè)英文字母或1個(gè)標(biāo)點(diǎn)均算作1個(gè)字符。

      setSyncCallTimeout

      3.1.17

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

      startWorkThread

      3.x

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

      getVersion

      3.x

      獲取SDK版本號(hào)。

      releaseInstance

      2.x

      銷毀NlsClient對(duì)象實(shí)例。

      CreateSynthesizerRequest

      2.x

      創(chuàng)建語音合成對(duì)象,線程安全,支持高并發(fā)請(qǐng)求。創(chuàng)建此對(duì)象時(shí)即可通過入?yún)⒋_定是長(zhǎng)文本語音合成還是短文本語音合成。300字以內(nèi)可用短文本語音合成,300字以上可考慮使用長(zhǎng)文本語音合成。字符計(jì)算可調(diào)用接口calculateUtf8Chars。

      releaseSynthesizerRequest

      2.x

      銷毀語音合成對(duì)象,需要在當(dāng)前請(qǐng)求的closed事件后調(diào)用。

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

      接口名

      功能描述

      setAccessKeyId

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

      setKeySecret

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

      setDomain

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

      setServerVersion

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

      setServerResourcePath

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

      setRegionId

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

      setAction

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

      applyNlsToken

      申請(qǐng)獲取TokenId。

      getToken

      獲取TokenId

      getExpireTime

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

      getErrorMsg

      獲得錯(cuò)誤信息。

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

      接口名

      功能描述

      getStatusCode

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

      getErrorMessage

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

      getTaskId

      獲取任務(wù)的TaskId。

      getBinaryData

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

      getAllResponse

      獲取云端返回的識(shí)別結(jié)果。

  • 識(shí)別接口

    SpeechSynthesizerRequest:語音合成請(qǐng)求對(duì)象,用于語音合成及長(zhǎng)文本語音合成。接口說明以speechSynthesizerRequest.h內(nèi)容為準(zhǔn)。

    接口名

    啟用版本

    功能描述

    setOnSynthesisCompleted

    2.x

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

    setOnChannelClosed

    2.x

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

    setOnTaskFailed

    2.x

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

    setOnBinaryDataReceived

    2.x

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

    setOnMetaInfo

    2.x

    設(shè)置文本對(duì)應(yīng)的日志信息接收回調(diào)函數(shù)。

    setOnMessage

    3.1.16

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

    setAppKey

    2.x

    設(shè)置AppKey。

    setToken

    2.x

    口令認(rèn)證。所有的請(qǐng)求都必須通過SetToken方法認(rèn)證通過,才可以使用。

    setUrl

    2.x

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

    setText

    2.x

    待合成音頻文本內(nèi)容text設(shè)置。300字以內(nèi)可用短文本語音合成,300字以上可考慮使用長(zhǎng)文本語音合成。字符計(jì)算可調(diào)用接口calculateUtf8Chars。

    setVoice

    2.x

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

    setVolume

    2.x

    音量volume設(shè)置。

    setFormat

    2.x

    輸出音頻編碼格式Format設(shè)置(默認(rèn)是PCM,支持的格式PCM、WAV、MP3)。

    setSampleRate

    2.x

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

    setSpeechRate

    2.x

    語速設(shè)置。

    setPitchRate

    2.x

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

    setMethod

    2.x

    合成方法method設(shè)置,默認(rèn)0。

    • 0:統(tǒng)計(jì)參數(shù)合成:基于統(tǒng)計(jì)參數(shù)的語音合成,優(yōu)點(diǎn)是能適應(yīng)的韻律特征的范圍較寬,合成器比特率低,資源占用小,性能高,音質(zhì)適中。

    • 1:波形拼接合成:基于高質(zhì)量音庫(kù)提取學(xué)習(xí)合成,資源占用相對(duì)較高,音質(zhì)較好,更加貼近真實(shí)發(fā)音,但沒有參數(shù)合成穩(wěn)定。

    setEnableSubtitle

    2.x

    是否開啟字幕功能。

    setPayloadParam

    2.x

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

    setTimeout

    2.x

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

    setContextParam

    2.x

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

    AppendHttpHeaderParam

    2.x

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

    setSendTimeout

    3.1.14

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

    setEnableOnMessage

    3.1.16

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

    getTaskId

    3.1.17

    獲得當(dāng)前請(qǐng)求的task_id。

    start

    2.x

    啟動(dòng)SpeechSynthesizerRequest。

    cancel

    2.x

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

C++SDK錯(cuò)誤碼

狀態(tài)碼

狀態(tài)消息

原因

解決方案

0

Success

成功

-10

DefaultError

默認(rèn)錯(cuò)誤

暫未使用。

-11

JsonParseFailed

錯(cuò)誤的JSON格式

請(qǐng)檢查傳入的JSON字符串是否符合JSON格式。

-12

JsonObjectError

錯(cuò)誤的JSON對(duì)象

建議重新嘗試。

-13

MallocFailed

Malloc失敗

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

-14

ReallocFailed

Realloc失敗

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

-15

InvalidInputParam

傳入無效的參數(shù)

暫未使用。

-50

InvalidLogLevel

無效日志級(jí)別

請(qǐng)檢查設(shè)置的Log級(jí)別。

-51

InvalidLogFileSize

無效日志文件大小

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

-52

InvalidLogFileNum

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

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

-100

EncoderExistent

NLS的編碼器已存在

建議重新嘗試。

-101

EncoderInexistent

NLS的編碼器不存在

建議重新初始化。

-102

OpusEncoderCreateFailed

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

建議重新初始化。

-103

OggOpusEncoderCreateFailed

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

建議重新初始化。

-104

InvalidEncoderType

encoder類型無效

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

-150

EventClientEmpty

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

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

-151

SelectThreadFailed

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

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

-160

StartCommandFailed

發(fā)送start命令失敗

建議重新嘗試。

-161

InvokeStartFailed

請(qǐng)求狀態(tài)機(jī)不對(duì),導(dǎo)致start失敗

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

-162

InvokeSendAudioFailed

請(qǐng)求狀態(tài)機(jī)不對(duì),導(dǎo)致sendAudio失敗

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

-163

InvalidOpusFrameSize

opus幀長(zhǎng)無效,默認(rèn)為640字節(jié)

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

-164

InvokeStopFailed

請(qǐng)求狀態(tài)機(jī)不對(duì),導(dǎo)致stop失敗

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

-165

InvokeCancelFailed

請(qǐng)求狀態(tài)機(jī)不對(duì),導(dǎo)致stop失敗

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

-166

InvokeStControlFailed

請(qǐng)求狀態(tài)機(jī)不對(duì),導(dǎo)致stControl失敗

請(qǐng)檢查當(dāng)前請(qǐng)求是否未啟動(dòng)(即收到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()進(jìn)行解析時(shí)發(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)部使用,當(dāng)前請(qǐng)求內(nèi)部狀態(tài)不合法。

-252

InvalidNodeQueue

workThread中NodeQueue無效

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

-300

InvalidRequestParams

請(qǐng)求的入?yún)o效

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

-301

RequestEmpty

請(qǐng)求是空指針

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

-302

InvalidRequest

無效的請(qǐng)求

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

-303

SetParamsEmpty

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

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

-350

GetHttpHeaderFailed

獲得http頭失敗

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

-351

HttpGotBadStatus

http錯(cuò)誤的狀態(tài)

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

-352

WsResponsePackageFailed

解析websocket返回包失敗

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

-353

WsResponsePackageEmpty

解析websocket返回包為空

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

-354

WsRequestPackageEmpty

websocket請(qǐng)求包為空

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

-355

UnknownWsFrameHeadType

未知websocket幀頭類型

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

-356

InvalidWsFrameHeaderSize

無效的websocket幀頭大小

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

-357

InvalidWsFrameHeaderBody

無效的websocket幀頭本體

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

-358

InvalidWsFrameBody

無效的websocket幀本體

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

-359

WsFrameBodyEmpty

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

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

-400

NodeEmpty

node為空指針

建議釋放當(dāng)前請(qǐng)求重新嘗試。

-401

InvaildNodeStatus

node所處狀態(tài)無效

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

-402

GetAddrinfoFailed

通過DNS解析地址識(shí)別

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

-403

ConnectFailed

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

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

-404

InvalidDnsSource

當(dāng)前設(shè)備無DNS

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

-405

ParseUrlFailed

無效URL

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

-406

SslHandshakeFailed

SSL握手失敗

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

-407

SslCtxEmpty

SSL_CTX未空

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

-408

SslNewFailed

SSL_new失敗

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

-409

SslSetFailed

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

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

-410

SslConnectFailed

SSL_connect失敗

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

-411

SslWriteFailed

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

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

-412

SslReadSysError

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

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

-413

SslReadFailed

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

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

-414

SocketFailed

創(chuàng)建socket失敗

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

-415

SetSocketoptFailed

設(shè)置socket參數(shù)失敗

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

-416

SocketConnectFailed

進(jìn)行socket鏈接失敗

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

-417

SocketWriteFailed

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

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

-418

SocketReadFailed

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

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

-430

NlsReceiveFailed

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

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

-431

NlsReceiveEmpty

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

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

-432

ReadFailed

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

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

-433

NlsSendFailed

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

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

-434

NewOutputBufferFailed

創(chuàng)建buffer失敗

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

-435

NlsEncodingFailed

音頻編碼失敗

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

-436

EventEmpty

event為空

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

-437

EvbufferTooMuch

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

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

-438

EvutilSocketFailed

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

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

-439

InvalidExitStatus

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

請(qǐng)檢查是否已經(jīng)cancel了當(dāng)前請(qǐng)求。

-450

InvalidAkId

阿里云賬號(hào)ak id無效

請(qǐng)檢查阿里云賬號(hào)ak id是否為空。

-451

InvalidAkSecret

阿里云賬號(hào)ak secret無效

請(qǐng)檢查阿里云賬號(hào)ak secret是否為空。

-452

InvalidAppKey

項(xiàng)目appKey無效

請(qǐng)檢查阿里云項(xiàng)目appKey是否為空。

-453

InvalidDomain

domain無效

請(qǐng)檢查輸入的domain是否為空。

-454

InvalidAction

action無效

請(qǐng)檢查輸入的action是否為空。

-455

InvalidServerVersion

ServerVersion無效

請(qǐng)檢查輸入的ServerVersion是否為空。

-456

InvalidServerResource

ServerResource無效

請(qǐng)檢查輸入的ServerResource是否為空。

-457

InvalidRegionId

RegionId無效

請(qǐng)檢查輸入的RegionId是否為空。

-500

InvalidFileLink

無效的錄音文件鏈接

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

-501

ErrorStatusCode

錯(cuò)誤的狀態(tài)碼

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

-502

IconvOpenFailed

申請(qǐng)轉(zhuǎn)換描述失敗

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

-503

IconvFailed

編碼轉(zhuǎn)換失敗

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

-504

ClientRequestFaild

賬號(hào)客戶端請(qǐng)求失敗

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

-999

NlsMaxErrorCode

其他狀態(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)錯(cuò)誤。

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

10000004

EmptyUrl

URL: The url is empty.

傳入的URL為空,請(qǐng)重新填寫正確URL。

10000005

InvalidWsUrl

Could not parse WebSocket url:

傳入的URL格式錯(cuò)誤,請(qǐng)重新填寫正確URL。

10000007

JsonStringParseFailed

JSON: Json parse failed.

JSON格式異常,請(qǐng)通過日志查看具體的錯(cuò)誤點(diǎn)。

10000008

UnknownWsHeadType

WEBSOCKET: unkown head type.

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

10000009

HttpConnectFailed

HTTP: connect failed.

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

10000010

MemNotEnough

內(nèi)存不足。

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

10000015

SysConnectFailed

connect failed.

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

10000100

HttpGotBadStatusWith403

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

鏈接被拒,請(qǐng)檢查賬號(hào)特別是token是否過期。

10000101

EvSendTimeout

Send timeout. socket error:

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

10000102

EvRecvTimeout

Recv timeout. socket error:

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

10000103

EvUnknownEvent

Unknown event:

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

10000104

OpNowInProgress

Operation now in progress

鏈接正在進(jìn)行中,建議重新嘗試。

10000105

BrokenPipe

Broken pipe

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

10000110

TokenHasExpired

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

請(qǐng)更新Token。

10000111

TokenIsInvalid

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

請(qǐng)檢查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!

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

10000120

Utf8ConvertError

utf8ToGbk failed

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

20000000

SuccessStatusCode

成功

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

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

代碼示例

說明
  • 示例中使用SDK內(nèi)置的默認(rèn)外網(wǎng)訪問服務(wù)URL,如果您使用阿里云上海ECS且需要使用內(nèi)網(wǎng)訪問URL,則在創(chuàng)建speechSynthesizerRequest的對(duì)象中設(shè)置內(nèi)網(wǎng)訪問的URL。

    request->setUrl("wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1");
  • 示例中將合成的音頻保存在文件中,如果您需要播放音頻且對(duì)實(shí)時(shí)性要求較高,建議使用流式播放,即邊接收語音數(shù)據(jù)邊播放,減少延時(shí),而無需等待合成結(jié)束后再處理語音流。

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

  • 調(diào)用接口前,需配置環(huán)境變量,通過環(huán)境變量讀取訪問憑證。智能語音交互的AccessKey ID、AccessKey Secret和AppKey的環(huán)境變量名:NLS_AK_ENVNLS_SK_ENVNLS_APPKEY_ENV

#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <ctime>
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <sys/time.h>
#include <errno.h>
#include "nlsClient.h"
#include "nlsEvent.h"
#include "nlsToken.h"
#include "speechSynthesizerRequest.h"

using namespace AlibabaNlsCommon; 
using AlibabaNls::NlsClient; 
using AlibabaNls::NlsEvent; 
using AlibabaNls::LogDebug; 
using AlibabaNls::LogInfo; 
using AlibabaNls::LogError;
using AlibabaNls::TtsVersion;
using AlibabaNls::SpeechSynthesizerRequest;

//自定義線程參數(shù)。
struct ParamStruct {
  std::string text; 
  std::string token; 
  std::string appkey;   
  std::string audioFile; 
};
//自定義事件回調(diào)參數(shù)。
struct ParamCallBack {
 public:
  ParamCallBack() {
    pthread_mutex_init(&mtxWord, NULL);
    pthread_cond_init(&cvWord, NULL);
  };
  ~ParamCallBack() {
    pthread_mutex_destroy(&mtxWord);
    pthread_cond_destroy(&cvWord);
  };

  std::string binAudioFile; 
  std::ofstream audioFile; 

  pthread_mutex_t mtxWord;
  pthread_cond_t cvWord;
};

/**
 * 全局維護(hù)一個(gè)服務(wù)鑒權(quán)token和其對(duì)應(yīng)的有效期時(shí)間戳,
 * 每次調(diào)用服務(wù)之前,首先判斷token是否已經(jīng)過期,
 * 如果已經(jīng)過期,則根據(jù)AccessKey ID和AccessKey Secret重新生成一個(gè)token,并更新這個(gè)全局的token和其有效期時(shí)間戳。
 *
 * 獲取Token具體操作,請(qǐng)參見:http://bestwisewords.com/document_detail/450514.html
 *
 * 注意:不要每次調(diào)用服務(wù)之前都重新生成新token,只需在token即將過期時(shí)重新生成即可。所有的服務(wù)并發(fā)可共用一個(gè)token。
 */
std::string g_akId = "";
std::string g_akSecret = "";
std::string g_token = "";
long g_expireTime = -1;

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

  int ret = nlsTokenRequest.applyNlsToken();
  if (ret < 0) {
    // 獲取失敗原因。
    printf("generateToken Failed, error code:%d msg:%s\n",
        ret, nlsTokenRequest.getErrorMsg());
    return ret;
  }
  *token = nlsTokenRequest.getToken();
  *expireTime = nlsTokenRequest.getExpireTime();
  return 0;
}

/**
 * @brief sdk在接收到云端返回合成結(jié)束消息時(shí), sdk內(nèi)部線程上報(bào)Completed事件
 * @note 上報(bào)Completed事件之后,SDK內(nèi)部會(huì)關(guān)閉識(shí)別連接通道.
 * @param cbEvent 回調(diào)事件結(jié)構(gòu), 詳見nlsEvent.h
 * @param cbParam 回調(diào)自定義參數(shù),默認(rèn)為NULL, 可以根據(jù)需求自定義參數(shù)
 * @return
 */
void OnSynthesisCompleted(NlsEvent* cbEvent, void* cbParam) { 
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam; 
  // 演示如何打印/使用用戶自定義參數(shù)示例。
  printf("OnSynthesisCompleted: %s\n", tmpParam->binAudioFile.c_str()); 
  // 獲取消息的狀態(tài)碼,成功為0或者20000000,失敗時(shí)對(duì)應(yīng)失敗的錯(cuò)誤碼。
  // 當(dāng)前任務(wù)的task id,方便定位問題,作為和服務(wù)端交互的唯一標(biāo)識(shí)建議輸出。
  printf("OnSynthesisCompleted: status code=%d, task id=%s\n", cbEvent->getStatusCode(), cbEvent->getTaskId()); 
  // 獲取服務(wù)端返回的全部信息。
  //printf("OnSynthesisCompleted: all response=%s\n", cbEvent->getAllResponse()); 
} 

/**
 * @brief 合成過程發(fā)生異常時(shí), sdk內(nèi)部線程上報(bào)TaskFailed事件
 * @note 上報(bào)TaskFailed事件之后,SDK內(nèi)部會(huì)關(guān)閉識(shí)別連接通道.
 * @param cbEvent 回調(diào)事件結(jié)構(gòu), 詳見nlsEvent.h
 * @param cbParam 回調(diào)自定義參數(shù),默認(rèn)為NULL, 可以根據(jù)需求自定義參數(shù)
 * @return
 */
void OnSynthesisTaskFailed(NlsEvent* cbEvent, void* cbParam) { 
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam; 
  // 演示如何打印/使用用戶自定義參數(shù)示例。
  printf("OnSynthesisTaskFailed: %s\n", tmpParam->binAudioFile.c_str()); 
  // 當(dāng)前任務(wù)的task id。
  printf("OnSynthesisTaskFailed: status code=%d, task id=%s, error message=%s\n", 
      cbEvent->getStatusCode(), cbEvent->getTaskId(), cbEvent->getErrorMessage()); 
}

/**
 * @brief 文本上報(bào)服務(wù)端之后, 收到服務(wù)端返回的二進(jìn)制音頻數(shù)據(jù), SDK內(nèi)部線程通過BinaryDataRecved事件上報(bào)給用戶
 * @param cbEvent 回調(diào)事件結(jié)構(gòu), 詳見nlsEvent.h
 * @param cbParam 回調(diào)自定義參數(shù),默認(rèn)為NULL, 可以根據(jù)需求自定義參數(shù)
 * @return
 * @notice 此處切記不可做block操作,只可做音頻數(shù)據(jù)轉(zhuǎn)存. 若在此回調(diào)中做過多操作,
 *         會(huì)阻塞后續(xù)的數(shù)據(jù)回調(diào)和completed事件回調(diào).
 */
void OnBinaryDataRecved(NlsEvent* cbEvent, void* cbParam) { 
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;  
  // 演示如何打印/使用用戶自定義參數(shù)示例。
  printf("OnBinaryDataRecved: %s\n", tmpParam->binAudioFile.c_str());

  const std::vector<unsigned char>& data = cbEvent->getBinaryData(); // getBinaryData() :獲取文本合成的二進(jìn)制音頻數(shù)據(jù)。
  printf("OnBinaryDataRecved: status code=%d, task id=%s, data size=%d\n",
      cbEvent->getStatusCode(), cbEvent->getTaskId(), data.size());
  // 以追加形式將二進(jìn)制音頻數(shù)據(jù)寫入文件。
  if (data.size() > 0) {
    tmpParam->audioFile.write((char*)&data[0], data.size());
  }
} 

/**
 * @brief 返回 tts 文本對(duì)應(yīng)的日志信息,增量返回對(duì)應(yīng)的字幕信息
 * @param cbEvent 回調(diào)事件結(jié)構(gòu), 詳見nlsEvent.h
 * @param cbParam 回調(diào)自定義參數(shù),默認(rèn)為NULL, 可以根據(jù)需求自定義參數(shù)
 * @return
*/
void OnMetaInfo(NlsEvent* cbEvent, void* cbParam) { 
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;  
  // 演示如何打印/使用用戶自定義參數(shù)示例。
  printf("OnBinaryDataRecved: %s\n", tmpParam->binAudioFile.c_str()); 
  printf("OnMetaInfo: task id=%s, respose=%s\n", cbEvent->getTaskId(), cbEvent->getAllResponse()); 
}

/**
 * @brief 識(shí)別結(jié)束或發(fā)生異常時(shí),會(huì)關(guān)閉連接通道, sdk內(nèi)部線程上報(bào)ChannelCloseed事件
 * @param cbEvent 回調(diào)事件結(jié)構(gòu), 詳見nlsEvent.h
 * @param cbParam 回調(diào)自定義參數(shù),默認(rèn)為NULL, 可以根據(jù)需求自定義參數(shù)
 * @return
 */
void OnSynthesisChannelClosed(NlsEvent* cbEvent, void* cbParam) { 
    ParamCallBack* tmpParam = (ParamCallBack*)cbParam; 
    // 演示如何打印/使用用戶自定義參數(shù)示例。
    printf("OnSynthesisChannelClosed: %s\n", tmpParam->binAudioFile.c_str());   
    printf("OnSynthesisChannelClosed: %s\n", cbEvent->getAllResponse()); 

    //通知發(fā)送線程, 最終識(shí)別結(jié)果已經(jīng)返回, 可以調(diào)用stop()
    pthread_mutex_lock(&(tmpParam->mtxWord));
    pthread_cond_signal(&(tmpParam->cvWord));
    pthread_mutex_unlock(&(tmpParam->mtxWord));
}

/**
 * @brief 短鏈接模式下工作線程
 *        以 createSynthesizerRequest          <----|
 *                   |                              |
 *           request->start()                       |
 *                   |                              |
 *           收到OnSynthesisChannelClosed回調(diào)       |
 *                   |                              |
 *           releaseSynthesizerRequest(request) ----|
 *        進(jìn)行循環(huán)。
 */
void* pthreadFunc(void* arg) {

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

  // 1: 初始化自定義回調(diào)參數(shù)
  ParamCallBack* cbParam = new ParamCallBack();
  cbParam->binAudioFile = tst->audioFile;   
  cbParam->audioFile.open(cbParam->binAudioFile.c_str(), std::ios::binary | std::ios::out);

  /*
   * 1. 創(chuàng)建語音識(shí)別SpeechSynthesizerRequest對(duì)象.
   *
   * 默認(rèn)為實(shí)時(shí)短文本語音合成請(qǐng)求, 支持一次性合成300字符以內(nèi)的文字,
   * 其中1個(gè)漢字、1個(gè)英文字母或1個(gè)標(biāo)點(diǎn)均算作1個(gè)字符,
   * 超過300個(gè)字符的內(nèi)容將會(huì)報(bào)錯(cuò)(或者截?cái)?.
   * 一次性合成超過300字符可考慮長(zhǎng)文本語音合成功能.
   *
   * 實(shí)時(shí)短文本語音合成文檔詳見: http://bestwisewords.com/document_detail/84435.html
   * 長(zhǎng)文本語音合成文檔詳見: http://bestwisewords.com/document_detail/130509.html
   */
  TtsVersion tts_version = AlibabaNls::ShortTts;
  int chars_cnt = NlsClient::getInstance()->calculateUtf8Chars(tst->text.c_str());
  if (chars_cnt > 300) {
    tts_version = AlibabaNls::LongTts;
  }

  // 2:創(chuàng)建語音識(shí)別SpeechSynthesizerRequest對(duì)象 
  SpeechSynthesizerRequest* request =
      NlsClient::getInstance()->createSynthesizerRequest(tts_version);
  if (request == NULL) {
    printf("createSynthesizerRequest failed.\n");   
    cbParam->audioFile.close(); 
    delete cbParam;  
    return NULL; 
  }

  // 設(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->setOnMetaInfo(OnMetaInfo, cbParam);

  request->setAppKey(tst->appkey.c_str());
  // 設(shè)置賬號(hào)校驗(yàn)token, 必填參數(shù)
  request->setToken(tst->token.c_str());

  // 設(shè)置待合成文本, 必填參數(shù). 文本內(nèi)容必須為UTF-8編碼
  // 一次性合成超過300字符可考慮長(zhǎng)文本語音合成功能.
  // 長(zhǎng)文本語音合成文檔詳見: http://bestwisewords.com/document_detail/130509.html
  request->setText(tst->text.c_str());
  // 發(fā)音人, 包含"xiaoyun", "ruoxi", "xiaogang"等. 可選參數(shù), 默認(rèn)是xiaoyun
  request->setVoice("siqi");
  // 訪問個(gè)性化音色,訪問的Voice必須是個(gè)人定制音色
  //request->setPayloadParam("{\"enable_ptts\":true}");
  // 音量, 范圍是0~100, 可選參數(shù), 默認(rèn)50
  request->setVolume(50);
  // 音頻編碼格式, 可選參數(shù), 默認(rèn)是wav. 支持的格式pcm, wav, mp3
  request->setFormat("wav");
  // 音頻采樣率, 包含8000, 16000. 可選參數(shù), 默認(rèn)是16000
  request->setSampleRate(16000);
  // 語速, 范圍是-500~500, 可選參數(shù), 默認(rèn)是0
  request->setSpeechRate(0);
  // 語調(diào), 范圍是-500~500, 可選參數(shù), 默認(rèn)是0
  request->setPitchRate(0);
  // 開啟字幕
  request->setEnableSubtitle(true);

  // 3: start()為異步操作。成功則開始返回BinaryRecv事件。失敗返回TaskFailed事件。
  int ret = request->start();
  if (ret < 0) {
    printf("start() failed. may be can not connect server. please check network or firewalld\n");   
    NlsClient::getInstance()->releaseSynthesizerRequest(request); // start()失敗,釋放request對(duì)象
    cbParam->audioFile.close();
    delete cbParam;
    return NULL;
  }

  struct timeval now;
  struct timespec outtime;
  // 4: 通知云端數(shù)據(jù)發(fā)送結(jié)束.
  // stop()為無意義接口,調(diào)用與否都會(huì)跑完全程,均需等待closed事件回調(diào).
  // cancel()立即停止工作, 且不會(huì)有回調(diào)返回, 失敗返回TaskFailed事件。
  //ret = request->cancel();
  ret = request->stop();
  if (ret == 0) {
    printf("wait closed callback.\n");
    // 語音服務(wù)器存在來不及處理當(dāng)前請(qǐng)求, 10s內(nèi)不返回任何回調(diào)的問題,
    // 然后在10s后返回一個(gè)TaskFailed回調(diào), 所以需要設(shè)置一個(gè)超時(shí)機(jī)制.
    gettimeofday(&now, NULL);
    outtime.tv_sec = now.tv_sec + 30;
    outtime.tv_nsec = now.tv_usec * 1000;
    // 等待closed事件后再進(jìn)行釋放, 否則會(huì)出現(xiàn)崩潰
    pthread_mutex_lock(&(cbParam->mtxWord));
    if (ETIMEDOUT == pthread_cond_timedwait(&(cbParam->cvWord), &(cbParam->mtxWord), &outtime)) {
      printf("synthesis timeout.\n");
    }
    pthread_mutex_unlock(&(cbParam->mtxWord));
  }

  NlsClient::getInstance()->releaseSynthesizerRequest(request);

  cbParam->audioFile.close(); 
  delete cbParam;  

  return NULL;
}

// 合成單個(gè)文本數(shù)據(jù)
int speechSynthesizerFile(const char* appkey) {
  //獲取當(dāng)前系統(tǒng)時(shí)間戳,判斷token是否過期。
  std::time_t curTime = std::time(0);
  if (g_expireTime - curTime < 10) {
    printf("the token will be expired, please generate new token by AccessKey-ID and AccessKey-Secret.\n");
    if (generateToken(g_akId, g_akSecret, &g_token, &g_expireTime) < 0) {
      return -1;
    } 
  }

  ParamStruct pa;
  pa.token = g_token;
  pa.appkey = appkey;
  pa.text = "今天天氣很棒,適合去戶外旅行.";  
  pa.audioFile = "syAudio.wav"; 

  // 啟動(dòng)一個(gè)工作線程,用于單次識(shí)別。
  pthread_t pthreadId;
  pthread_create(&pthreadId, NULL, &pthreadFunc, (void *)&pa);
  pthread_join(pthreadId, NULL);
  return 0;
}

// 合成多個(gè)文本數(shù)據(jù)。
// SDK多線程指一個(gè)文本數(shù)據(jù)對(duì)應(yīng)一個(gè)線程,非一個(gè)文本數(shù)據(jù)對(duì)應(yīng)多個(gè)線程。
// 示例代碼為同時(shí)開啟2個(gè)線程合成2個(gè)文件。
// 免費(fèi)用戶并發(fā)連接不能超過2個(gè)。
#define AUDIO_TEXT_NUMS 2
#define AUDIO_TEXT_LENGTH 64
#define AUDIO_FILE_NAME_LENGTH 32
int speechTranscriberMultFile(const char* appkey) {
  //獲取當(dāng)前系統(tǒng)時(shí)間戳判斷token是否過期。
  std::time_t curTime = std::time(0);
  if (g_expireTime - curTime < 10) {
    printf("the token will be expired, please generate new token by AccessKey-ID and AccessKey-Secret.\n");
    if (generateToken(g_akId, g_akSecret, &g_token, &g_expireTime) < 0) {
      return -1;
    }
  }

  const char syAudioFiles[AUDIO_TEXT_NUMS][AUDIO_FILE_NAME_LENGTH] = 
  {
    "syAudio0.wav", 
    "syAudio1.wav"
  };
  const char texts[AUDIO_TEXT_NUMS][AUDIO_TEXT_LENGTH] =
  {
    "今日天氣真不錯(cuò),我想去操作踢足球.",
    "明天有大暴雨,還是宅在家里看電影吧."
  }; 
  ParamStruct pa[AUDIO_TEXT_NUMS]; 
  for (int i = 0; i < AUDIO_TEXT_NUMS; i ++) { 
      pa[i].token = g_token; 
      pa[i].appkey = appkey; 
      pa[i].text = texts[i]; 
      pa[i].audioFile = syAudioFiles[i]; 
  } 
  std::vector<pthread_t> pthreadId(AUDIO_TEXT_NUMS);     // 啟動(dòng)工作線程,同時(shí)識(shí)別音頻文件。
  for (int j = 0; j < AUDIO_TEXT_NUMS; j++) { 
      pthread_create(&pthreadId[j], NULL, &pthreadFunc, (void *)&(pa[j])); 
  }
  for (int j = 0; j < AUDIO_TEXT_NUMS; j++) {  
      pthread_join(pthreadId[j], NULL);  
  } 
  return 0;
}

int main(int argc, char* argv[]) {
  printf("Usage: ./demo <your appkey> <your AccessKey ID> <your AccessKey Secret>\n");

  std::string appkey = getenv("NLS_APPKEY_ENV");
  g_akId = getenv("NLS_AK_ENV");
  g_akSecret = getenv("NLS_SK_ENV");

  // 根據(jù)需要設(shè)置SDK輸出日志。可選。
  // 此處表示SDK日志輸出至log-synthesizer.txt。
  // LogDebug表示輸出所有級(jí)別日志,支持LogDebug、LogInfo、LogWarning、LogError。
  // 400表示單個(gè)文件400MB。50表示50個(gè)日志文件循環(huán)記錄。
  int ret = NlsClient::getInstance()->setLogConfig(
      "log-synthesizer", LogDebug, 400, 50);
  if (ret < 0) {
    printf("set log failed.\n");
    return -1;
  }

  // 設(shè)置運(yùn)行環(huán)境需要的套接口地址類型, 默認(rèn)為AF_INET
  // 必須在startWorkThread()前調(diào)用
  //AlibabaNls::NlsClient::getInstance()->setAddrInFamily("AF_INET");
    
  // 私有云部署的情況下可進(jìn)行直連IP的設(shè)置
  // 必須在startWorkThread()前調(diào)用
  //NlsClient::getInstance()->setDirectHost("106.15.83.44");

  // 存在部分設(shè)備在設(shè)置了dns后仍然無法通過SDK的dns獲取可用的IP,
  // 可調(diào)用此接口主動(dòng)啟用系統(tǒng)的getaddrinfo來解決這個(gè)問題.
  //NlsClient::getInstance()->setUseSysGetAddrInfo(true);

  // 啟動(dòng)工作線程, 在創(chuàng)建請(qǐng)求和啟動(dòng)前必須調(diào)用此函數(shù), 可理解為對(duì)NlsClient的初始化
  // 入?yún)樨?fù)時(shí), 啟動(dòng)當(dāng)前系統(tǒng)中可用的核數(shù)。
  // 200并發(fā)以下推薦入?yún)?, 更高并發(fā)入?yún)⑼扑]可看readme。
  NlsClient::getInstance()->startWorkThread(1);

  // 合成單個(gè)文本
  speechSynthesizerFile(appkey.c_str());
  // 合成單個(gè)文本
  //speechSynthesizerMultFile(appkey.c_str());

  // 所有工作完成,進(jìn)程退出前,釋放nlsClient。
  // 請(qǐng)注意releaseInstance()非線程安全, 需要確認(rèn)所有請(qǐng)求都停止工作才可釋放。
  NlsClient::releaseInstance();

  return 0;
}

常見問題

C++ SDK進(jìn)行語音合成時(shí),報(bào)錯(cuò)未設(shè)置appkey,但是代碼已經(jīng)設(shè)置該如何解決?OnSynthesisTaskFailed: status code=10000002 task id=***error message={TaskFailed":"{"task_id":"00000000000000000000000000000000","result":"","status":40000003,"message":"Gateway:PARAMETER_INVALID:appkey not set"}"}"

status為40000003指?jìng)魅氲膮?shù)有誤,請(qǐng)重新檢查傳入的參數(shù)值是否正確,例如appkeyvoiceurl等 。’

C++ 語音合成Demo,NlsCommonSdk版本20211018基于vc16.0,NlsSdkCpp3.X版本20210629基于vc14.0,Demo程序只執(zhí)行到OnSynthesisTaskFailed,返回20000000,在win10 X64 vs2015中得不到WAV的可能原因?log信息如下ERROR alibabaNlsLog: [ID:15284][AlibabaNls::ConnectNode::parseFrame:1014]Node:000001D733079F20 Result conversion failed.

NlsSdkCpp3.X-20210629里的Demo不適用于Windows版本程序,alibabacloud-nls-cpp-sdk(github的)里的才是Windows的Demo。

C++ SDK(3.0及以后版本)使用語音合成和語音識(shí)別功能,可以提高GCC5.0以上的編譯版本嗎?

可以。Linux下支持GCC 4.8.5或以上版本。目前已驗(yàn)證且順利編譯運(yùn)行的GCC版本包括4.8.5、5.5.0、8.4.0。

為什么鏈接不到framework?

framework中代碼采用Objective-C和C++混合編寫而成,所以需要使用.mm后綴文件進(jìn)行調(diào)用,同時(shí)請(qǐng)確保工程的頭文件路徑與庫(kù)文件路徑設(shè)置正確。

C++ SDK ASR請(qǐng)求有DNS解析失敗的情況導(dǎo)致異常,報(bào)錯(cuò)ali-recog-skd.log:AliSpeech_C++SDK(ERROR): GetInetAddressByHostname:252 DNS: resolved timeout.ali-recog-skd.log:AliSpeech_C++SDK(ERROR): start:76 start failed: DNS: resolved timeout..unimrcpserver_current.log: [ERROR] [[./ali/AliRecogChannel.cpp:772,onTaskFailed]]Ali Task start failed Msg :DNS: resolved timeout., start finised."如何解決?

  • 舊版(3.0及以前版本):在高并發(fā)或者電腦DNS忙碌的情況下容易出現(xiàn)以上問題,建議您更新到3.1.X版本,或進(jìn)行再次重啟請(qǐng)求。

  • 新版(3.0及以后版本):已經(jīng)對(duì)此問題進(jìn)行防御,若仍然偶現(xiàn)此問題,則為電腦DNS忙碌,需要再次重啟請(qǐng)求。

C++ SDK(新)集成到其他項(xiàng)目中時(shí),將CMakeLists.txt中的add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) 修改為add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1)后編譯不通過該如何解決?

除了CMakeLists.txt,全工程都需要修改該參數(shù),例如config/linux.thirdparty.debug.cmakeconfig/linux.thirdparty.release.cmake,請(qǐng)?jiān)谌夸浰阉?code data-tag="code" code-type="xCode" class="code">_GLIBCXX_USE_CXX11_ABI進(jìn)行修改。

C++ SDK在Windows上使用,報(bào)錯(cuò)缺少nlsCommonSdk.dll如何解決?

3.1及以后版本無nlsCommonSdk.dll。

C++ SDK舊版NlsSdkCpp2.0和新版NlsSdkCpp3.X的區(qū)別是什么?

NlsSdkCpp2.0版本的SDK每一個(gè)請(qǐng)求為一個(gè)線程,且接口為同步接口。

NlsSdkCpp3.X版本的SDK內(nèi)部由第三方庫(kù)libevent統(tǒng)一處理事件消息,并發(fā)性能更強(qiáng),且接口為異步接口。

C++版的SDK不支持實(shí)現(xiàn)C11規(guī)范嗎? 現(xiàn)在導(dǎo)致項(xiàng)目無法鏈接SDK該如何解決?

工程默認(rèn)為_GLIBCXX_USE_CXX11_ABI=0,全工程都需要修改該參數(shù),請(qǐng)?jiān)谌夸浰阉?code data-tag="code" code-type="xCode" class="code">_GLIBCXX_USE_CXX11_ABI進(jìn)行修改。

C++ SDK測(cè)試Demo成功,集成項(xiàng)目報(bào)錯(cuò),DNS解析失敗,報(bào)錯(cuò)nls-gateway-cn-shanghai.aliyuncs.com dns failed: nodename nor servname provided, or not known如何解決?

  1. SDK中會(huì)查看當(dāng)前設(shè)備開啟的所有協(xié)議族(IPv4、IPv6)進(jìn)行DNS解析請(qǐng)求,nls-gateway-cn-shanghai.aliyuncs.com不支持 IPv6,返回解析錯(cuò)誤,從而導(dǎo)致SDK DNS解析失敗退出。可禁用當(dāng)前設(shè)備的IPv6協(xié)議族,后續(xù)CppSdk產(chǎn)品改進(jìn)對(duì)這方面進(jìn)行可配置處理。

  2. 建議您升級(jí)到3.1.12及以后版本。

C++ SDK測(cè)試Demo可以成功,集成項(xiàng)目報(bào)錯(cuò),網(wǎng)絡(luò)鏈接失敗,報(bào)錯(cuò)[dnsEventCallback:465]Node:0x7f087c001030 ai_canonname: nls-gateway-cn-shanghai.aliyuncs.com.gds.alibabadns.com[dnsEventCallback:477]Node:0x7f087c001030 IpV4:106.15.XX.XX[connectProcess:1329]Node:0x7f087c001030 sockFd:41[connectProcess:1347]Node:0x7f087c001030 new Socket ip:106.15.XX.XX port:443 Fd:41.[socketConnect:1458]Node:0x7f087c001030 Connect failed:Network is unreachable. retry...如何解決?

以上現(xiàn)象為無法連接網(wǎng)絡(luò),查看日志發(fā)現(xiàn)DNS域名解析出來的IP鏈接不成功,進(jìn)一步通過Ping判斷網(wǎng)絡(luò)不通。由于本地?cái)r截DNS解析,導(dǎo)致SDK內(nèi)部libeventevdns_getaddrinfo獲得錯(cuò)誤的IP。

解決辦法:

  • 3.1.12版本以前可將evdns_getaddrinfo()手動(dòng)替換成系統(tǒng)的getaddrinfo()

  • 3.1.12版本可在CMakeLists.txt中修改add_definitions(-DNLS_USE_NATIVE_GETADDRINFO)

  • 3.1.12及以后版本增加setDirectHost()接口,您可以在SDK外部進(jìn)行DNS解析,獲取正確IP后通過該接口設(shè)入。

  • 3.1.13及以后版本已解決此問題,若運(yùn)行時(shí)仍存在上述問題,建議調(diào)用接口setUseSysGetAddrInfo(true)

C++ SDK語音合成時(shí)傳入的文本沒有采用UTF-8編碼會(huì)有什么錯(cuò)誤信息?

如果傳入的文本沒有采用UTF-8編碼,在文本中含有中文字符時(shí),語音合成SDK調(diào)用start函數(shù)會(huì)失敗,返回錯(cuò)誤信息Socket recv failed, errorCode: 0。錯(cuò)誤碼為0表示服務(wù)端已經(jīng)關(guān)閉了連接,此時(shí)應(yīng)檢查傳入的文本是否采用UTF-8編碼。

SDK報(bào)錯(cuò)“DNS resolved timeout”是什么問題?

查看/etc/resolv.conf文件中nameserver的設(shè)置,建議增加并優(yōu)先使用以下配置:nameserver 114.114.114.114