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

C++ SDK

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

SDK下載

說明
  • 當前最新版本:3.1.17,支持Linux、Windows平臺。發布日期:2023年08月09日。

  • 使用SDK前,請先閱讀接口說明,詳情請參見接口說明

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

您可通過以下兩種方法獲取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

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

SDK包文件說明

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

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

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

  • 文件名

    描述

    speechRecognizerDemo.cpp

    一句話識別示例。

    speechSynthesizerDemo.cpp

    語音合成示例。

    speechTranscriberDemo.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

    實時音頻流識別。

    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(語音對話)。

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

      cd build/demo 
      ./srDemo 

Windows平臺編譯

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

關鍵接口

  • 基礎接口

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

      接口名

      啟用版本

      功能描述

      getInstance

      2.x

      獲?。▌摻ǎ㎞lsClient實例。

      setLogConfig

      2.x

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

      setDirectHost

      3.x

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

      setAddrInFamily

      3.1.12

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

      setUseSysGetAddrInfo

      3.1.13

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

      setSyncCallTimeout

      3.1.17

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

      startWorkThread

      3.x

      啟動工作線程數,默認1即啟動一個線程,若-1則啟動CPU核數的線程數。在高并發的情況下建議選擇-1??梢岳斫鉃镹lsClient實例初始化,必須調用。

      releaseInstance

      3.x

      銷毀NlsClient對象實例。

      getVersion

      2.x

      獲取SDK版本號。

      createRecognizerRequest

      2.x

      創建一句話識別對象,線程安全,支持高并發請求。

      releaseRecognizerRequest

      2.x

      銷毀一句話識別對象,需要在當前請求的closed事件后調用。

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

      接口名

      功能描述

      setAccessKeyId

      設置阿里云賬號AccessKey ID。

      setKeySecret

      設置阿里云賬號AccessKey Secret。

      setDomain

      設置域名,非必填。

      setServerVersion

      設置API版本,非必填。

      setServerResourcePath

      設置服務路徑,非必填。

      setRegionId

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

      setAction

      設置功能,非必填。

      applyNlsToken

      申請獲取TokenId。

      getToken

      獲取TokenId。

      getExpireTime

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

      getErrorMsg

      獲得錯誤信息。

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

      接口名

      功能描述

      getStatusCode

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

      getErrorMessage

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

      getTaskId

      獲取任務的TaskId。

      getAllResponse

      獲取云端返回的識別結果。

      getResult

      獲取中間識別結果和最終結果。

  • 識別接口

    SpeechRecognizerRequest:一句話識別請求對象,用于短語音識別。接口說明以speechRecognizerRequest.h內容為準。

    接口名

    啟用版本

    功能描述

    setOnTaskFailed

    2.x

    設置錯誤回調函數。

    setOnRecognitionStarted

    2.x

    設置一句話識別開始回調函數。

    setOnRecognitionResultChanged

    2.x

    設置一句話識別中間結果回調函數。

    setOnRecognitionCompleted

    2.x

    設置服務端結束服務回調函數。

    setOnChannelClosed

    2.x

    設置通道關閉回調函數。

    setOnMessage

    3.1.16

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

    setAppKey

    2.x

    設置AppKey。

    setToken

    2.x

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

    setUrl

    2.x

    設置服務URL地址。

    setIntermediateResult

    2.x

    設置是否返回中間識別結果。

    setPunctuationPrediction

    2.x

    設置是否在后處理中添加標點。

    setInverseTextNormalization

    2.x

    設置是否在后處理中執行數字轉換。

    setEnableVoiceDetection

    2.x

    設置是否啟動自定義靜音檢測。

    setMaxStartSilence

    2.x

    超出后(即開始識別后多長時間沒有檢測到聲音)服務端將會發送TaskFailed事件,結束本次識別。

    setMaxEndSilence

    2.x

    超出時長服務端會發送RecognitionCompleted事件,結束本次識別(需要注意后續的語音將不會進行識別)。

    setFormat

    2.x

    設置音頻數據編碼格式(PCM、OPUS、OPU,默認是PCM,推薦OPUS)。

    setSampleRate

    2.x

    音頻采樣率設置。

    setCustomizationId

    2.x

    設置定制模型。

    setVocabularyId

    2.x

    設置泛熱詞。

    setTimeout

    2.x

    設置Socket接收超時時間。

    setOutputFormat

    2.x

    設置輸出文本的編碼格式,編碼格式UTF-8 or GBK。

    setPayloadParam

    2.x

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

    setContextParam

    2.x

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

    AppendHttpHeaderParam

    2.x

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

    setAudioAddress

    3.1.13

    實驗接口??赏ㄟ^公網訪問的音頻文件下載鏈接,音頻文件下載鏈接,推薦使用阿里云OSS。

    setSendTimeout

    3.1.14

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

    setRecvTimeout

    3.1.14

    設置接收超時時間, 默認15000ms,需setEnableRecvTimeout開啟后生效。

    setEnableRecvTimeout

    3.1.16

    設置開啟接收超時時間,默認false,即默認關閉接收超時時間,開啟后長時間未收服務端則報錯。

    getOutputFormat

    3.1.16

    獲得設置的輸出文本的編碼格式。

    setEnableOnMessage

    3.1.16

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

    getTaskId

    3.1.17

    獲得當前請求的task_id。

    start

    2.x

    啟動SpeechRecognizerRequest。

    stop

    2.x

    會與服務端確認關閉,正常停止鏈接操作。

    cancel

    2.x

    不會與服務端確認關閉,直接關閉鏈接。

    sendAudio

    2.x

    發送語音數據。建議一次發送音頻數據640~16384字節。

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

EvutilSocketFailed

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無效

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

-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

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

20000000

SuccessStatusCode

成功

服務端響應狀態碼

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

代碼示例

說明
  • 示例中使用的音頻文件為16000Hz采樣率,管控臺設置的模型為通用模型。如果使用其他音頻,請設置為支持該音頻場景的模型。關于模型設置,請參見管理項目。

  • 示例中使用了SDK內置的默認一句話識別服務的外網訪問服務URL,如果您使用阿里云上海ECS且需要使用內網訪問URL,則在創建SpeechRecognizerRequest的對象中設置內網訪問的URL。

    request->setUrl("ws://nls-gateway-cn-shanghai-internal.aliyuncs.com/ws/v1")
  • 完整示例,參見SDK壓縮包中demo目錄的speechRecognizerDemo.cpp文件。

  • 調用接口前,需配置環境變量,通過環境變量讀取訪問憑證。智能語音交互的AccessKey ID、AccessKey Secret和AppKey的環境變量名:NLS_AK_ENV、NLS_SK_ENV、NLS_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 "speechRecognizerRequest.h"

#define FRAME_SIZE 3200
#define SAMPLE_RATE 16000

using namespace AlibabaNlsCommon; 
using AlibabaNls::NlsClient; 
using AlibabaNls::NlsEvent; 
using AlibabaNls::LogDebug; 
using AlibabaNls::LogInfo; 
using AlibabaNls::LogError;
using AlibabaNls::SpeechRecognizerRequest;

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

  int userId;
  char userInfo[8];
  pthread_mutex_t mtxWord;
  pthread_cond_t cvWord;
};

/**
 * 全局維護一個服務鑒權token和其對應的有效期時間戳,
 * 每次調用服務之前,首先判斷token是否已經過期,
 * 如果已經過期,則根據AccessKey ID和AccessKey Secret重新生成一個token,
 * 并更新這個全局的token和其有效期時間戳。
 *
 * 獲取Token具體操作,請參見:http://bestwisewords.com/document_detail/450514.html
 *
 * 注意:不要每次調用服務之前都重新生成新token,
 * 只需在token即將過期時重新生成即可。所有的服務并發可共用一個token。
 */
std::string g_akId = "";
std::string g_akSecret = "";
std::string g_token = "";
long g_expireTime = -1;
int g_sync_timeout = 0;
struct timeval tv;
struct timeval tv1;

//根據AccessKey ID和AccessKey Secret重新生成一個token,并獲取其有效期時間戳
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 獲取sendAudio發送延時時間
 * @param dataSize 待發送數據大小
 * @param sampleRate 采樣率 16k/8K
 * @param compressRate 數據壓縮率,例如壓縮比為10:1的16k opus編碼,此時為10;
                       非壓縮數據則為1
 * @return 返回sendAudio之后需要sleep的時間
 * @note 對于8k pcm 編碼數據, 16位采樣,建議每發送1600字節 sleep 100 ms.
         對于16k pcm 編碼數據, 16位采樣,建議每發送3200字節 sleep 100 ms.
         對于其它編碼格式(OPUS)的數據, 由于解碼后傳遞給SDK的仍然是PCM編碼數據,
         按照SDK OPUS/OPU 數據長度限制, 需要每次發送640字節 sleep 20ms.
 */
unsigned int getSendAudioSleepTime(int dataSize,
                                   int sampleRate,
                                   int compressRate) { 
  // 僅支持16位采樣
  const int sampleBytes = 16;     // 僅支持單通道
  const int soundChannel = 1;     // 當前采樣率,采樣位數下每秒采樣數據的大小。
  int bytes = (sampleRate * sampleBytes * soundChannel) / 8;     // 當前采樣率,采樣位數下每毫秒采樣數據的大小。
  int bytesMs = bytes / 1000;     // 待發送數據大小除以每毫秒采樣數據大小,以獲取sleep時間。
  int sleepMs = (dataSize * compressRate) / bytesMs;
  return sleepMs; 
}

/**
 * @brief 調用start(), 成功與云端建立連接, sdk內部線程上報started事件
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void OnRecognitionStarted(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  // 演示如何打印/使用用戶自定義參數。
  printf("OnRecognitionStarted: %d, %s\n", tmpParam->userId, tmpParam->userInfo);
  // 獲取消息的狀態碼,成功為0或者20000000,失敗時對應失敗的錯誤碼。
  // 當前任務的task id,方便定位問題,作為和服務端交互的唯一標識建議輸出。
  printf("OnRecognitionStarted: status code=%d, task id=%s\n", cbEvent->getStatusCode(), cbEvent->getTaskId()); 
  // 獲取服務端返回的全部信息
  //printf("OnRecognitionStarted: all response=%s\n", cbEvent->getAllResponse());

  // 通知發送線程start()成功, 可以繼續發送數據
  pthread_mutex_lock(&(tmpParam->mtxWord));
  pthread_cond_signal(&(tmpParam->cvWord));
  pthread_mutex_unlock(&(tmpParam->mtxWord));
} 

/**
 * @brief 設置允許返回中間結果參數, sdk在接收到云端返回到中間結果時,
 *        sdk內部線程上報ResultChanged事件
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void OnRecognitionResultChanged(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  // 演示如何打印/使用用戶自定義參數。
  printf("OnRecognitionResultChanged: %d, %s\n", tmpParam->userId, tmpParam->userInfo);         // 當前任務的task id,方便定位問題,作為和服務端交互的唯一標識建議輸出。
  printf("OnRecognitionResultChanged: status code=%d, task id=%s, result=%s\n", cbEvent->getStatusCode(), cbEvent->getTaskId(), cbEvent->getResult());
  // 獲取服務端返回的全部信息
  //printf("OnRecognitionResultChanged: response=%s\n", cbEvent->getAllResponse());
}

/**
 * @brief sdk在接收到云端返回識別結束消息時, sdk內部線程上報Completed事件
 * @note 上報Completed事件之后, SDK內部會關閉識別連接通道. 
 *       此時調用sendAudio會返回負值, 請停止發送.
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
*/
void OnRecognitionCompleted(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  // 演示如何打印/使用用戶自定義參數。
  printf("OnRecognitionCompleted: %d, %s\n", tmpParam->userId, tmpParam->userInfo);
  // 當前任務的task id,方便定位問題,作為和服務端交互的唯一標識建議輸出。
  printf("OnRecognitionCompleted: status code=%d, task id=%s, result=%s\n", cbEvent->getStatusCode(), cbEvent->getTaskId(), cbEvent->getResult());
  // 獲取服務端返回的全部信息。
  //printf("OnRecognitionCompleted: response=%s\n", cbEvent->getAllResponse());
}

/**
 * @brief 識別過程發生異常時, sdk內部線程上報TaskFailed事件
 * @note 上報TaskFailed事件之后, SDK內部會關閉識別連接通道. 
 *       此時調用sendAudio會返回負值, 請停止發送.
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void OnRecognitionTaskFailed(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  // 演示如何打印/使用用戶自定義參數。
  printf("OnRecognitionTaskFailed: %d, %s\n", tmpParam->userId, tmpParam->userInfo);
  // 當前任務的task id,方便定位問題,作為和服務端交互的唯一標識建議輸出。
  printf("OnRecognitionTaskFailed: status code=%d, task id=%s, error message=%s\n", cbEvent->getStatusCode(), cbEvent->getTaskId(), cbEvent->getErrorMessage());
  // 獲取服務端返回的全部信息。
  //printf("OnRecognitionTaskFailed: response=%s\n", cbEvent->getAllResponse());
}

/**
 * @brief 識別結束或發生異常時,會關閉連接通道,
 *        sdk內部線程上報ChannelCloseed事件
 * @param cbEvent 回調事件結構, 詳見nlsEvent.h
 * @param cbParam 回調自定義參數,默認為NULL, 可以根據需求自定義參數
 * @return
 */
void OnRecognitionChannelClosed(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  // 演示如何打印/使用用戶自定義參數。
  printf("OnRecognitionChannelClosed: %d, %s\n", tmpParam->userId, tmpParam->userInfo);         // 獲取服務端返回的全部信息。
  printf("OnRecognitionChannelClosed: response=%s\n", cbEvent->getAllResponse());

  //通知發送線程, 最終識別結果已經返回, 可以調用stop()
  pthread_mutex_lock(&(tmpParam->mtxWord));
  pthread_cond_signal(&(tmpParam->cvWord));
  pthread_mutex_unlock(&(tmpParam->mtxWord));
}

/**
 * @brief 短鏈接模式下工作線程
 *        以 createRecognizerRequest           <----|
 *                   |                              |
 *           request->start()                       |
 *                   |                              |
 *           request->sendAudio()                   |
 *                   |                              |
 *           request->stop()                        |
 *                   |                              |
 *           收到OnRecognitionChannelClosed回調     |
 *                   |                              |
 *           releaseRecognizerRequest(request)  ----|
 *        進行循環。
 */
void* pthreadFunction(void* arg) {
  int sleepMs = 0;
  int ret = 0;
  ParamCallBack *cbParam = NULL;

  //初始化自定義回調參數,以下兩變量僅作為示例表示參數傳遞,在示例中不起任何作用。
  //回調參數在堆中分配之后,請在退出線程前釋放。
  cbParam = new ParamCallBack();
  cbParam->userId = rand() % 100;
  strcpy(cbParam->userInfo, "User.");
  // 0:從自定義線程參數中獲取token,配置文件等參數。
  ParamStruct *tst = (ParamStruct *) arg; 
  if (tst == NULL) {
    printf("arg is not valid\n"); 
    delete cbParam;
    return NULL;
  } 
  // 打開音頻文件,獲取數據。
  std::ifstream fs;
  fs.open(tst->fileName.c_str(), std::ios::binary | std::ios::in);
  if (!fs) {
    printf("%s isn't exist..\n", tst->fileName.c_str());
    return NULL;
  }
  //1: 創建一句話識別SpeechRecognizerRequest對象。
  SpeechRecognizerRequest *request =
      NlsClient::getInstance()->createRecognizerRequest();
  if (request == NULL) {
    printf("createRecognizerRequest failed\n");
    delete cbParam;
    return NULL;
  }

  // 設置start()成功回調函數
  request->setOnRecognitionStarted(OnRecognitionStarted, cbParam);
  // 設置異常識別回調函數
  request->setOnTaskFailed(OnRecognitionTaskFailed, cbParam);
  // 設置識別通道關閉回調函數
  request->setOnChannelClosed(OnRecognitionChannelClosed, cbParam);
  // 設置中間結果回調函數
  request->setOnRecognitionResultChanged(OnRecognitionResultChanged, cbParam);
  // 設置識別結束回調函數
  request->setOnRecognitionCompleted(OnRecognitionCompleted, cbParam);

  // 設置appKey。必填參數。
  request->setAppKey(tst->appkey.c_str());
  // 設置賬號校驗token, 必填參數
  request->setToken(tst->token.c_str());

  // 設置音頻數據編碼格式??蛇x參數,目前支持PCM/OPUS,默認為PCM。
  request->setFormat("opus");
  // 設置音頻數據采樣率??蛇x參數,目前支持16000/8000。默認為16000。
  request->setSampleRate(SAMPLE_RATE);
  // 設置是否返回中間識別結果。可選參數,默認false。
  request->setIntermediateResult(true);
  // 設置是否在后處理中添加標點??蛇x參數,默認false。
  request->setPunctuationPrediction(true);
  // 設置是否在后處理中執行ITN??蛇x參數,默認false。
  request->setInverseTextNormalization(true);
  // 是否啟動語音檢測??蛇x,默認為False。
  //request->setEnableVoiceDetection(true);
  // 允許的最大開始靜音, 可選, 單位是毫秒,
  // 超出后服務端將會發送RecognitionCompleted事件, 結束本次識別.
  // 注意: 需要先設置enable_voice_detection為true
  //request->setMaxStartSilence(800);
  // 允許的最大結束靜音, 可選, 單位是毫秒,
  // 超出后服務端將會發送RecognitionCompleted事件, 結束本次識別.
  // 注意: 需要先設置enable_voice_detection為true
  //request->setMaxEndSilence(800);
  // 定制語言模型id,可選。
  //request->setCustomizationId("TestId_123");
  // 定制泛熱詞id,可選。
  //request->setVocabularyId("TestId_456");
  // 用于傳遞某些定制化、高級參數設置,參數格式為JSON格式:{"key": "value"}。
  //request->setPayloadParam("{\"vad_model\": \"farfield\"}");

  struct timespec outtime;
  struct timeval now;
  /*
   * 2. start()為同步/異步兩種操作,默認異步。由于異步模式通過回調判斷request是否成功運行有修改門檻,且部分舊版本為同步接口。
   *    為了能較為平滑的更新升級SDK,提供了同步/異步兩種調用方式。
   *    異步情況:默認未調用setSyncCallTimeout()的時候,start()調用立即返回,
   *            且返回值并不代表request成功開始工作,需要等待返回started事件表示成功啟動,或返回TaskFailed事件表示失敗。
   *    同步情況:調用setSyncCallTimeout()設置同步接口的超時時間,并啟動同步模式。start()調用后不會立即返回,
   *            直到內部得到成功(同時也會觸發started事件回調)或失敗(同時也會觸發TaskFailed事件回調)后返回。
   *            此方法方便舊版本SDK
   */
  ret = request->start();
  if (ret < 0) {
    printf("start() failed. may be can not connect server. please check network or firewalld\n");
    NlsClient::getInstance()->releaseRecognizerRequest(request); // start()失敗,釋放request對象。
    delete cbParam;
    return NULL;
  } else {
    if (g_sync_timeout == 0) {
      /*
       * 2.1. g_sync_timeout等于0,即默認未調用setSyncCallTimeout(),異步方式調用start()
       *      需要等待返回started事件表示成功啟動,或返回TaskFailed事件表示失敗。
       * 
       * 等待started事件返回表示start()成功, 然后再發送音頻數據。
       * 語音服務器存在來不及處理當前請求的情況, 10s內不返回任何回調的問題,
       * 然后在10s后返回一個TaskFailed回調, 所以需要設置一個超時機制。
       */
      printf("wait started callback.\n");

      // 語音服務器存在來不及處理當前請求, 10s內不返回任何回調的問題,
      // 然后在10s后返回一個TaskFailed回調, 所以需要設置一個超時機制.
      gettimeofday(&now, NULL);
      outtime.tv_sec = now.tv_sec + 5;
      outtime.tv_nsec = now.tv_usec * 1000;
      pthread_mutex_lock(&(cbParam->mtxWord));
      if (ETIMEDOUT == pthread_cond_timedwait(&(cbParam->cvWord), &(cbParam->mtxWord), &outtime)) {
        printf("start timeout.\n");
        pthread_mutex_unlock(&(cbParam->mtxWord));
        request->cancel();
        NlsClient::getInstance()->releaseRecognizerRequest(request);
        delete cbParam;
        return NULL;
      }
      pthread_mutex_unlock(&(cbParam->mtxWord));
    } else {
       /*
        * 2.2. g_sync_timeout大于0,即調用了setSyncCallTimeout(),同步方式調用start()
        *      返回值0即表示啟動成功。
        */ 
    }
  }

  /*
   * 3. 從文件取音頻數據循環發送音頻
   */
  while (!fs.eof()) {
    uint8_t data[FRAME_SIZE] = {0};
    fs.read((char *) data, sizeof(uint8_t) * FRAME_SIZE); 
    size_t nlen = fs.gcount();
    if (nlen <= 0) {
      continue;
    }

    /*
     * 3.1. 發送音頻數據: sendAudio為異步操作, 返回負值表示發送失敗, 需要停止發送;
     *      返回大于0 為成功. 
     *      若希望用省流量的opus格式上傳音頻數據, 則第三參數傳入ENCODER_OPU/ENCODER_OPUS
     *
     * ENCODER_OPU/ENCODER_OPUS模式時, 會占用一定的CPU進行音頻壓縮
     */
    ret = request->sendAudio(data, nlen, ENCODER_OPUS); 
    if (ret < 0) {
      // 發送失敗,退出循環數據發送。
      printf("send data fail.\n"); 
      break;
    } 

    /*
     * 實際使用中, 語音數據是實時的, 不用sleep控制速率, 直接發送即可.
     * 此處是用語音數據來自文件的方式進行模擬, 故發送時需要控制速率來模擬真實錄音場景.
     */
    sleepMs = getSendAudioSleepTime(nlen, SAMPLE_RATE, 1); // 根據發送數據大小、采樣率、數據壓縮比來獲取sleep時間。
    /*
     * 語音數據發送延時控制, 實際使用中無需sleep.
     */
    usleep(sleepMs * 1000);
  } // while

  printf("sendAudio done.\n");
  //5: 關閉音頻文件
  fs.close();
  
  /*
   * 4. 通知云端數據發送結束.
   *    stop()為同步/異步兩種操作,默認異步。由于異步模式通過回調判斷request是否成功運行有修改門檻,且部分舊版本為同步接口。
   *    為了能較為平滑的更新升級SDK,提供了同步/異步兩種調用方式。
   *    異步情況:默認未調用setSyncCallTimeout()的時候,stop()調用立即返回,
   *            且返回值并不代表request成功結束,需要等待返回closed事件表示結束。
   *    同步情況:調用setSyncCallTimeout()設置同步接口的超時時間,并啟動同步模式。stop()調用后不會立即返回,
   *            直到內部完成工作,并觸發closed事件回調后返回。
   *            此方法方便舊版本SDK。
   */
  ret = request->stop();
  if (ret == 0) {
    if (g_sync_timeout == 0) {
      /*
       * 4.1. g_sync_timeout等于0,即默認未調用setSyncCallTimeout(),異步方式調用stop()
       *      需要等待返回closed事件表示成功停止,或返回TaskFailed事件表示失敗。
       * 
       * 等待closed事件返回表示stop()成功, 然后才可釋放。
       * 語音服務器存在來不及處理當前請求的情況, 10s內不返回任何回調的問題,
       * 然后在10s后返回一個TaskFailed回調, 所以需要設置一個超時機制。
       */
      // 等待closed事件后再進行釋放, 否則會出現崩潰
      // 若調用了setSyncCallTimeout()啟動了同步調用模式, 則可以不等待closed事件。
      std::cout << "wait closed callback." << std::endl;
        
      printf("wait closed callback.\n");
    
      // 語音服務器存在來不及處理當前請求, 10s內不返回任何回調的問題,
      // 然后在10s后返回一個TaskFailed回調, 錯誤信息為:
      // "Gateway:IDLE_TIMEOUT:Websocket session is idle for too long time, the last directive is 'StopRecognition'!"
      // 所以需要設置一個超時機制.
      gettimeofday(&now, NULL);
      outtime.tv_sec = now.tv_sec + 5;
      outtime.tv_nsec = now.tv_usec * 1000;
      // 等待closed事件后再進行釋放
      pthread_mutex_lock(&(cbParam->mtxWord));
      if (ETIMEDOUT == pthread_cond_timedwait(&(cbParam->cvWord), &(cbParam->mtxWord), &outtime)) {
        printf("stop timeout\n");
        pthread_mutex_unlock(&(cbParam->mtxWord));
        NlsClient::getInstance()->releaseRecognizerRequest(request);
        delete cbParam;
        return NULL;
      }
      pthread_mutex_unlock(&(cbParam->mtxWord));
    } else {
      /*
       * 4.2. g_sync_timeout大于0,即調用了setSyncCallTimeout(),同步方式調用stop()
       *      返回值0即表示啟動成功。
       */
    }
  } else {
    printf("stop ret is %d\n", ret);
  }

  /*
   * 5. 完成所有工作后釋放當前請求。
   *    請在closed事件(確定完成所有工作)后再釋放, 否則容易破壞內部狀態機, 會強制卸載正在運行的請求。
   */
  NlsClient::getInstance()->releaseRecognizerRequest(request);
  delete cbParam;
  return NULL;
}

// 識別單個音頻數據
int speechRecognizerFile(const char* appkey) {
  //獲取當前系統時間戳,判斷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.fileName = "test0.wav";

  // 啟動一個工作線程,用于單次識別。
  pthread_t pthreadId;
  pthread_create(&pthreadId, NULL, &pthreadFunction, (void *)&pa);
  pthread_join(pthreadId, NULL);
  return 0;
}

//識別多個音頻數據
//SDK多線程指一個音頻數據源對應一個線程,非一個音頻數據對應多個線程。
//示例代碼為同時開啟2個線程識別2個文件。
//免費用戶并發連接不能超過2個。
#define AUDIO_FILE_NUMS 2
#define AUDIO_FILE_NAME_LENGTH 32
int speechRecognizerMultFile(const char* appkey) {
  //獲取當前系統時間戳判斷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;
    }
  }

  char audioFileNames[AUDIO_FILE_NUMS][AUDIO_FILE_NAME_LENGTH] = {
      "test0.wav", 
      "test1.wav"
  };
  ParamStruct pa[AUDIO_FILE_NUMS];
  for (int i = 0; i < AUDIO_FILE_NUMS; i ++) {
    pa[i].token = g_token; 
    pa[i].appkey = appkey;
    pa[i].fileName = audioFileNames[i]; 
  } 

  // 啟動2個工作線程,同時識別2個音頻文件。
  std::vector<pthread_t> pthreadId(AUDIO_FILE_NUMS);
  for (int j = 0; j < AUDIO_FILE_NUMS; j++) {
    pthread_create(&pthreadId[j], NULL, &pthreadFunction, (void *)&(pa[j]));
  }
  for (int j = 0; j < AUDIO_FILE_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");

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

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

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

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

  // g_sync_timeout等于0,即默認未調用setSyncCallTimeout()
  // 異步方式調用
  //   start(): 需要等待返回started事件表示成功啟動,或返回TaskFailed事件表示失敗。
  //   stop(): 需要等待返回closed事件則表示完成此次交互。
  // 同步方式調用
  //   start()/stop() 調用返回即表示交互啟動/結束。
  if (g_sync_timeout > 0) {
    NlsClient::getInstance()->setSyncCallTimeout(g_sync_timeout);
  }
    
  // 啟動工作線程, 在創建請求和啟動前必須調用此函數, 可理解為對NlsClient的初始化
  // 入參為負時, 啟動當前系統中可用的核數。
  // 200并發以下推薦入參為1, 更高并發入參推薦可看readme。
  NlsClient::getInstance()->startWorkThread(1);

  // 識別單個音頻數據
  speechRecognizerFile(appkey.c_str());
  // 并發識別多個音頻數據
  //speechRecognizerMultFile(appkey.c_str());

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

  return 0;
}

常見問題

C++ SDK中的speechRecognizerDemo.cpp中的g_akid和g_akSecret在哪里獲取?

請參見準備賬號。

C++ SDK一句話識別調用stop后,返回錯誤回調狀態碼40000004該如何解決?提示“{"header":{"namespace":"Default","name":"TaskFailed","status":40000004,"message_id":"xxxxxxxxxxxxxxxxxxxxxxxxx","task_id":"xxxxxxxxxxxxxxxxxxxxxxxxx","status_text":"Gateway:IDLE_TIMEOUT:Websocket session is idle for too long time, the last directive is 'StopRecognition'!"}}”

可能是服務端瞬間收到大量請求導致的單個實例無法及時處理,建議重試。

為什么連接不到framework?

framework中代碼采用Objective-C和C++混合編寫而成,所以需要使用.mm后綴文件進行調用,同時請確保工程的頭文件路徑與庫文件路徑設置正確。

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

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

C++ SDK ASR請求有DNS解析失敗的情況導致異常,報錯“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及以前版本):在高并發或者電腦DNS忙碌的情況下容易出現以上問題,建議您更新到3.1.X版本,或進行再次重啟請求。

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

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

除了CMakeLists.txt,全工程都需要修改該參數,例如config/linux.thirdparty.debug.cmakeconfig/linux.thirdparty.release.cmake,請在全目錄搜索_GLIBCXX_USE_CXX11_ABI進行修改。

C++ SDK在Windows上使用,報錯缺少nlsCommonSdk.dll如何解決?

3.1及以后版本無nlsCommonSdk.dll。

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

NlsSdkCpp2.0版本的SDK每一個請求為一個線程,且接口為同步接口。

NlsSdkCpp3.X版本的SDK內部由第三方庫libevent統一處理事件消息,并發性能更強,且接口為異步接口。

C++版的SDK不支持實現C11規范嗎? 現在導致項目無法鏈接SDK該如何解決?

工程默認為_GLIBCXX_USE_CXX11_ABI=0,全工程都需要修改該參數,請在全目錄搜索_GLIBCXX_USE_CXX11_ABI進行修改。

C++ SDK測試Demo成功,集成項目報錯,DNS解析失敗,報錯“nls-gateway-cn-shanghai.aliyuncs.com dns failed: nodename nor servname provided, or not known”如何解決?

  1. SDK中會查看當前設備開啟的所有協議族(IPv4、IPv6)進行DNS解析請求,nls-gateway-cn-shanghai.aliyuncs.com不支持 IPv6,返回解析錯誤,從而導致SDK DNS解析失敗退出??山卯斍霸O備的IPv6協議族,后續CppSdk產品改進對這方面進行可配置處理。

  2. 建議您升級到3.1.12及以后版本。

C++ SDK測試Demo可以成功,集成項目報錯,網絡鏈接失敗,報錯“[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...”如何解決?

以上現象為無法連接網絡,查看日志發現DNS域名解析出來的IP鏈接不成功,進一步通過Ping判斷網絡不通。由于本地攔截DNS解析,導致SDK內部libeventevdns_getaddrinfo獲得錯誤的IP。

解決辦法:

  • 3.1.12版本以前可將evdns_getaddrinfo()手動替換成系統的getaddrinfo()。

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

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

  • 3.1.13及以后版本已解決此問題,若運行時仍存在上述問題,建議調用接口setUseSysGetAddrInfo(true)。

C++ SDK語音合成時傳入的文本沒有采用UTF-8編碼會有什么錯誤信息?

如果傳入的文本沒有采用UTF-8編碼,在文本中含有中文字符時,語音合成SDK調用start函數會失敗,返回錯誤信息Socket recv failed, errorCode: 0。錯誤碼為0表示服務端已經關閉了連接,此時應檢查傳入的文本是否采用UTF-8編碼。