C# SDK
本文介紹如何使用智能語音交互一句話識別的C# SDK,包括SDK的安裝方法及SDK代碼示例等。
SDK下載
當前最新版本:3.1.17,該版本基于C++ SDK API 3.1.x。發(fā)布日期:2023年08月28日。
此SDK是底層C++包裹了C#組成,僅支持Windows平臺,不支持跨平臺能力。
使用SDK前,請先閱讀接口說明,詳情請參見接口說明。
可通過以下兩種方法獲取SDK。
方法一:從GitHub獲取最新源碼,詳細編譯和運行方式可見下文,或查看源碼中的readme.md。
git clone --depth 1 https://github.com/aliyun/alibabacloud-nls-cpp-sdk
方法二:直接從下文表中選取需要的SDK包進行下載。其中SDK源碼包為SDK原始代碼,需要通過下文的編譯方法生成集成所需的庫文件。其他對應平臺的SDK包內(nèi)含相關庫文件、頭文件,無需編譯。
最新SDK包
平臺
MD5
SDK源碼
8beeaad832d4b249464f4338429c3b15
Windows
81fdd1579e103d8c93b4dab98ee0f71c
其中:
alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip為SDK源碼包。
NlsCsharpSdk_Windows_<版本號>_<github commit id>.zip為Windows平臺下開發(fā)需要的SDK包,詳見內(nèi)部readme.md。
Windows平臺C#編譯運行
推薦直接使用已經(jīng)編譯好的庫NlsCsharpSdk_Windows_<version>_<github commit id>.zip進行集成。若有編譯需求,請下載alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip并解壓到本地,或從GitHub獲取最新代碼,然后參考其中的readme.md的編譯步驟。
關鍵接口
using nlsCsharpSdk;
基礎接口
NlsClient:語音處理客戶端,利用該客戶端可以進行一句話識別、實時語音識別和語音合成的語音處理任務。該客戶端為線程安全,建議全局僅創(chuàng)建一個實例。
接口名
啟用版本
功能描述
SetLogConfig
3.1.9
設置日志文件與存儲路徑。越早調(diào)用記錄的信息越詳細。
GetVersion
3.1.9
獲取SDK版本號。
CreateNlsToken
3.1.9
創(chuàng)建Token獲取對象,用于獲取阿里云token,詳見下方NlsToken相關表格。
ReleaseNlsToken
3.1.9
銷毀CreateNlsToken所建立的NlsToken對象。
SetDirectHost
3.1.16
跳過DNS域名解析直接設置服務器IP地址,若調(diào)用,則需要在StartWorkThread之前。
StartWorkThread
3.1.9
啟動工作線程數(shù),默認1即啟動一個線程,若-1則啟動CPU核數(shù)的線程數(shù)。在高并發(fā)的情況下建議選擇-1。這一接口有初始化NlsClient的作用。
ReleaseInstance
3.1.9
銷毀NlsClient對象實例,即釋放NLS SDK。此操作需要在銷毀所有請求后再調(diào)用。
CreateNlsToken
3.1.9
創(chuàng)建Token獲取對象,用于申請獲取TokenId。詳見下方NlsToken相關說明。
ReleaseNlsToken
3.1.9
銷毀Token獲取對象。
CreateRecognizerRequest
3.1.9
創(chuàng)建一句話識別對象,線程安全,支持高并發(fā)請求。
ReleaseRecognizerRequest
3.1.9
銷毀一句話識別對象,需要在當前請求的closed事件后調(diào)用。
NlsToken:創(chuàng)建Token對象,用于申請獲取TokenId。申請新Token時需要先獲取有效時間戳,若超過有效時間則再申請。若在有效時間內(nèi)多次申請Token會導致TokenId錯誤而無法使用。
接口名
功能描述
SetAccessKeyId
設置阿里云賬號AccessKey ID。
SetKeySecret
設置阿里云賬號AccessKey Secret。
ApplyNlsToken
申請獲取TokenId。此TokenId在有效期內(nèi)對所有此阿里云賬號AccessKey ID下的所有語音請求有效,無需在每個語音請求前申請獲得。
GetToken
獲取TokenId
GetExpireTime
獲取Token有效期時間戳(秒)。
GetErrorMsg
獲取TokenId失敗的錯誤信息。
NlsEvent:事件對象NLS_EVENT_STRUCT,通過CallbackDelegate返回。您可以從中獲取Request狀態(tài)碼、云端返回結(jié)果、失敗信息等。
參數(shù)名
功能描述
statusCode
獲取狀態(tài)碼,正常情況為0或者20000000,失敗時對應失敗的錯誤碼。
taskId
獲取任務的TaskId。
msg
獲取云端返回的response結(jié)果,用于獲得事件信息,如Started、Closed、TaskFailed回調(diào)的事件信息。
result
獲取云端返回的識別結(jié)果,用于獲得識別結(jié)果,如ResultChanged、Completed回調(diào)的事件信息。
識別接口
SpeechRecognizerRequest:一句話識別請求對象,用于短語音識別。
接口名
功能描述
SetOnTaskFailed
設置錯誤回調(diào)函數(shù)。
SetOnRecognitionStarted
設置一句話識別開始回調(diào)函數(shù)。
SetOnRecognitionResultChanged
設置一句話識別中間結(jié)果回調(diào)函數(shù)。
SetOnRecognitionCompleted
設置服務端結(jié)束服務回調(diào)函數(shù)。
SetOnChannelClosed
設置通道關閉回調(diào)函數(shù)。
SetAppKey
設置Appkey。
SetToken
口令認證。所有的請求都必須通過SetToken方法認證通過,才可以使用。
SetUrl
設置服務URL地址,默認可不設置則調(diào)用公有云上海域名的服務。
SetIntermediateResult
設置是否返回中間識別結(jié)果,結(jié)果會從OnRecognitionResultChanged回調(diào)返回。
SetPunctuationPrediction
設置是否在后處理中添加標點。
SetInverseTextNormalization
設置是否在后處理中執(zhí)行數(shù)字轉(zhuǎn)換。
SetEnableVoiceDetection
設置是否啟動自定義靜音檢測。
SetMaxStartSilence
允許的最大開始靜音,可選,單位為毫秒。超出后服務端將會發(fā)送RecognitionCompleted事件,開始本次識別。需要先設置SetEnableVoiceDetection為true. 建議設置為2000~5000。
SetMaxEndSilence
允許的最大結(jié)束靜音,可選,單位是毫秒。超出后服務端將會發(fā)送RecognitionCompleted事件,結(jié)束本次識別。需要先設置SetEnableVoiceDetection為true. 建議時間0~5000。
SetFormat
設置音頻數(shù)據(jù)編碼格式,Windows環(huán)境推薦用PCM格式。
SetSampleRate
音頻采樣率設置。
SetCustomizationId
設置定制模型,例如
("TestId_123")
。SetVocabularyId
設置泛熱詞,例如
("TestId_456")
。SetTimeout
設置Socket接收超時時間。
SetOutputFormat
設置輸出文本的編碼格式。Windows平臺下默認為GBK。非中文語種情況下,請設置成UTF-8,否則會出現(xiàn)亂碼。
SetPayloadParam
參數(shù)設置,入?yún)镴SON格式字符串。如指定聲學模型,例如
"{\"model\":\"test-regression-model\"}")
。SetContextParam
設置用戶自定義參數(shù),入?yún)镴SON格式字符串。
AppendHttpHeaderParam
設置用戶自定義ws階段http header參數(shù)。
Start
異步接口,啟動SpeechRecognizerRequest。需要等待OnRecognitionStarted回調(diào)以確保請求進入工作狀態(tài)。
Stop
異步接口,會與服務端確認關閉,正常停止鏈接操作。需要等待OnChannelClosed回調(diào)以確保請求結(jié)束工作狀態(tài)。
Cancel
不會與服務端確認關閉,直接關閉鏈接。
SendAudio
異步接口,發(fā)送語音數(shù)據(jù)。為保證實時性,每次發(fā)送數(shù)據(jù)不建議太長,建議一次發(fā)送100ms時長以內(nèi)的音頻數(shù)據(jù),范圍為640字節(jié)~16384字節(jié)。
SDK錯誤碼
狀態(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 | 無效日志級別 | 請檢查設置的Log級別。 |
-51 | InvalidLogFileSize | 無效日志文件大小 | 請檢查設置的Log文件大小參數(shù)。 |
-100 | EncoderExistent | NLS的編碼器已存在 | 建議重新嘗試。 |
-101 | EncoderInexistent | NLS的編碼器不存在 | 建議重新初始化。 |
-102 | OpusEncoderCreateFailed | Opus編碼器創(chuàng)建失敗 | 建議重新初始化。 |
-103 | OggOpusEncoderCreateFailed | OggOpus編碼器創(chuàng)建失敗 | 建議重新初始化。 |
-150 | EventClientEmpty | 主工作線程空指針,已釋放 | 建議重新初始化,即startWorkThread()。 |
-151 | SelectThreadFailed | 工作線程選擇失敗,未初始化 | 建議重新初始化,即startWorkThread()。 |
-160 | StartCommandFailed | 發(fā)送start命令失敗 | 建議重新嘗試。 |
-161 | InvokeStartFailed | 請求狀態(tài)機不對,導致start失敗 | 請檢查當前請求是否未創(chuàng)建或者已經(jīng)完成。 |
-162 | InvokeSendAudioFailed | 請求狀態(tài)機不對,導致sendAudio失敗 | 請檢查當前請求是否已經(jīng)啟動(即收到started事件回調(diào))或者已經(jīng)完成。 |
-163 | InvalidOpusFrameSize | opus幀長無效,默認為640字節(jié) | OPU編碼模式下,sendAudio一幀只接收640字節(jié)數(shù)據(jù)。 |
-164 | InvokeStopFailed | 請求狀態(tài)機不對,導致stop失敗 | 請檢查當前請求是否未啟動(即收到started事件回調(diào))或者已經(jīng)完成。 |
-165 | InvokeCancelFailed | 請求狀態(tài)機不對,導致stop失敗 | 請檢查當前請求是否未啟動(即收到started事件回調(diào))或者已經(jīng)完成。 |
-166 | InvokeStControlFailed | 請求狀態(tài)機不對,導致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ù)是否為空。 |
-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)絡環(huán)境是否可用。 |
-404 | InvalidDnsSource | 當前設備無DNS | SDK內(nèi)部使用,請檢查當前環(huán)境的DNS是否可用。 |
-405 | ParseUrlFailed | 無效URL | 請檢查設置的URL是否有效。 |
-406 | SslHandshakeFailed | SSL握手失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-407 | SslCtxEmpty | SSL_CTX未空 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-408 | SslNewFailed | SSL_new失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-409 | SslSetFailed | SSL設置參數(shù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-410 | SslConnectFailed | SSL_connect失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-411 | SslWriteFailed | SSL發(fā)送數(shù)據(jù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-412 | SslReadSysError | SSL接收數(shù)據(jù)收到SYSCALL錯誤 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-413 | SslReadFailed | SSL接收數(shù)據(jù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-414 | SocketFailed | 創(chuàng)建socket失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-415 | SetSocketoptFailed | 設置socket參數(shù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-416 | SocketConnectFailed | 進行socket鏈接失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-417 | SocketWriteFailed | socket發(fā)送數(shù)據(jù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-418 | SocketReadFailed | socket接收數(shù)據(jù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-430 | NlsReceiveFailed | NLS接收幀數(shù)據(jù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-431 | NlsReceiveEmpty | NLS接收幀數(shù)據(jù)為空 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-432 | ReadFailed | 接收數(shù)據(jù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(huán)境是否可用,并再次嘗試。 |
-433 | NlsSendFailed | NLS發(fā)送數(shù)據(jù)失敗 | SDK內(nèi)部使用,請檢查當前網(wǎng)絡環(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 | EvutilSocketFailed | evutil設置參數(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無效 | 請檢查輸入的RegionId是否為空。 |
-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)消息 | 原因 | 解決方案 |
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)反饋的錯誤信息進行處理。 |
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)絡后重試。 |
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)中是否有耗時任務,或并發(fā)過大導致無法及時處理事件。 |
10000102 | EvRecvTimeout | Recv timeout. socket error: | libevent接收event超時,請檢查回調(diào)中是否有耗時任務,或并發(fā)過大導致無法及時處理事件。 |
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 | utf8轉(zhuǎn)碼失敗,常為系統(tǒng)問題,建議重新嘗試。 |
20000000 | SuccessStatusCode | 成功 |
服務端響應狀態(tài)碼
關于服務狀態(tài)碼,請參見服務狀態(tài)碼。
代碼示例?
示例中使用的音頻文件為16000Hz采樣率,管控臺設置的模型為通用模型。如果使用其他音頻,請設置為支持該音頻場景的模型。關于模型設置,請參見管理項目。
示例中使用了SDK內(nèi)置的默認一句話識別服務的外網(wǎng)訪問服務URL,如果您使用阿里云上海ECS且需要使用內(nèi)網(wǎng)訪問URL,則在創(chuàng)建SpeechRecognizerRequest的對象中設置內(nèi)網(wǎng)訪問的URL。
SpeechRecognizerRequest srPtr; srPtr.SetUrl(srPtr, "ws://nls-gateway.cn-shanghai-internal.aliyuncs.com/ws/v1")
以下為簡要示例,完整示例請參見SDK壓縮包中demo目錄的nlsCsharpSdkDemo.cs文件。
using System; using System.IO; using System.Threading; using System.Windows.Forms; using nlsCsharpSdk; namespace nlsCsharpSdkDemo { public partial class nlsCsharpSdkDemo : Form { private NlsClient nlsClient; private SpeechRecognizerRequest srPtr; private NlsToken tokenPtr; private UInt64 expireTime; private string appKey; private string akId; private string akSecret; private string token; private string url; static bool running; static string cur_nls_result; static bool sr_send_audio_flag = false; static bool sr_audio_loop_flag = false; static Thread sr_send_audio; static string cur_sr_result; static string cur_sr_completed; static string cur_sr_closed; private void FlushLab() { while (running) { if (cur_sr_result != null && cur_sr_result.Length > 0) { srResult.Text = cur_sr_result; } if (cur_sr_completed != null && cur_sr_completed.Length > 0) { srCompleted.Text = cur_sr_completed; } if (cur_sr_closed != null && cur_sr_closed.Length > 0) { srClosed.Text = cur_sr_closed; } Thread.Sleep(200); } } private void SRAudioLab() { string file_name = System.Environment.CurrentDirectory + @"\audio_files\test3.wav"; System.Diagnostics.Debug.WriteLine("sr audio file_name = {0}", file_name); FileStream fs = new FileStream(file_name, FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fs); while (sr_audio_loop_flag) { if (sr_send_audio_flag) { byte[] byData = br.ReadBytes((int)3200); if (byData.Length > 0) { // 音頻數(shù)據(jù)以PCM格式,byData.Length字節(jié)進行推送。 srPtr.SendAudio(srPtr, byData, (UInt64)byData.Length, EncoderType.ENCODER_PCM); } else { /* * 音頻推送完成,重新打開循環(huán)繼續(xù) */ br.Close(); fs.Dispose(); fs = new FileStream(file_name, FileMode.Open, FileAccess.Read); br = new BinaryReader(fs); } } /* * 上面推送3200字節(jié)音頻數(shù)據(jù),相當于模擬100MS的音頻。 * 真實環(huán)境從錄音獲得音頻數(shù)據(jù),不需要調(diào)用此Sleep。 */ Thread.Sleep(100); } br.Close(); fs.Dispose(); } public nlsCsharpSdkDemo() { InitializeComponent(); System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; nlsClient = new NlsClient(); } private void button1_Click(object sender, EventArgs e) { // 開啟日志系統(tǒng),以Debug級別將名字為nlsLog.log的日志以單個400MB 10個日志文件循環(huán)的形式儲存。 int ret = nlsClient.SetLogConfig("nlsLog", LogLevel.LogDebug, 400, 10); if (ret == 0) nlsResult.Text = "OpenLog Success"; else nlsResult.Text = "OpenLog Failed"; } private void button1_Click_1(object sender, EventArgs e) { // 獲取當前SDK的版本號 string version = nlsClient.GetVersion(); nlsResult.Text = version; } private void button1_Click_2(object sender, EventArgs e) { // -1則表示啟動CPU核數(shù)的事件池數(shù)量,用于進行內(nèi)部事件的處理。 // 單路調(diào)用的情況下,建議入?yún)?,即啟動單個事件池進行處理。 // 高并發(fā)(幾百路)的情況下,入?yún)⒔ㄗh4 ~ CPU核數(shù),入?yún)⒃酱螅幚硌舆t越低但是CPU占用越高。 nlsClient.StartWorkThread(1); nlsResult.Text = "StartWorkThread and init NLS success."; running = true; Thread t = new Thread(FlushLab); t.Start(); } private void button1_Click_3(object sender, EventArgs e) { // 釋放NlsClient,與StartWorkThread互為反操作 nlsClient.ReleaseInstance(); nlsResult.Text = "Release NLS success."; } #region Info private void textBox1_TextChanged(object sender, EventArgs e) { akId = tAkId.Text; } private void tAppKey_TextChanged(object sender, EventArgs e) { appKey = tAppKey.Text; } private void tAkSecret_TextChanged(object sender, EventArgs e) { akSecret = tAkSecret.Text; } private void tToken_TextChanged(object sender, EventArgs e) { token = tToken.Text; } private void tUrl_TextChanged(object sender, EventArgs e) { url = tUrl.Text; } #endregion #region TokenButton // create token private void button3_Click_1(object sender, EventArgs e) { int ret = 0; tokenPtr = nlsClient.CreateNlsToken(); if (tokenPtr.native_token != IntPtr.Zero) { if (akId != null && akSecret != null & akId.Length > 0 && akSecret.Length > 0) { tokenPtr.SetAccessKeyId(tokenPtr, akId); tokenPtr.SetKeySecret(tokenPtr, akSecret); ret = tokenPtr.ApplyNlsToken(tokenPtr); if (ret < 0) { System.Diagnostics.Debug.WriteLine("ApplyNlsToken failed"); nlsResult.Text = tokenPtr.GetErrorMsg(tokenPtr); } else { System.Diagnostics.Debug.WriteLine("ApplyNlsToken success"); token = tokenPtr.GetToken(tokenPtr); tToken.Text = token; expireTime = tokenPtr.GetExpireTime(tokenPtr); nlsResult.Text = "ExpireTime:" + expireTime.ToString(); } } else { nlsResult.Text = "CreateToken Failed, akId or Secret is null"; } } else { nlsResult.Text = "CreateToken Failed"; } } // release token private void button4_Click(object sender, EventArgs e) { if (tokenPtr.native_token != IntPtr.Zero) { nlsClient.ReleaseNlsToken(tokenPtr); tokenPtr.native_token = IntPtr.Zero; nlsResult.Text = "ReleaseNlsToken Success"; } else { nlsResult.Text = "ReleaseNlsToken is nullptr"; } } #endregion #region RecognizerCallback private CallbackDelegate DemoOnRecognitionStarted = (ref NLS_EVENT_STRUCT e, ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnRecognitionStarted user uuid = {0}", uuid); string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0'); System.Diagnostics.Debug.WriteLine("DemoOnRecognitionStarted msg = {0}", msg); cur_sr_completed = "msg : " + msg; sr_send_audio_flag = true; }; private CallbackDelegate DemoOnRecognitionClosed = (ref NLS_EVENT_STRUCT e, ref string uuid) => { string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0'); System.Diagnostics.Debug.WriteLine("DemoOnRecognitionClosed = {0}", msg); cur_sr_closed = "msg : " + msg; }; private CallbackDelegate DemoOnRecognitionTaskFailed = (ref NLS_EVENT_STRUCT e, ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnRecognitionTaskFailed user uuid = {0}", uuid); string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0'); System.Diagnostics.Debug.WriteLine("DemoOnRecognitionTaskFailed = {0}", msg); cur_sr_completed = "msg : " + msg; sr_send_audio_flag = false; sr_audio_loop_flag = false; }; private CallbackDelegate DemoOnRecognitionResultChanged = (ref NLS_EVENT_STRUCT e, ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnRecognitionResultChanged user uuid = {0}", uuid); // 若識別為非中文,請設置UTF-8格式,并用UTF-8解碼,否則可能亂碼。 // string result = System.Text.Encoding.UTF8.GetString(e.result).TrimEnd('\0'); string result = System.Text.Encoding.Default.GetString(e.result).TrimEnd('\0'); cur_sr_result = "middle result : " + result; }; private CallbackDelegate DemoOnRecognitionCompleted = (ref NLS_EVENT_STRUCT e, ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnRecognitionCompleted user uuid = {0}", uuid); // 若識別為非中文,請設置UTF-8格式,并用UTF-8解碼,否則可能亂碼。 // string result = System.Text.Encoding.UTF8.GetString(e.result).TrimEnd('\0'); string result = System.Text.Encoding.Default.GetString(e.result).TrimEnd('\0'); cur_sr_completed = "final result : " + result; }; #endregion // create recognizer private void button8_Click(object sender, EventArgs e) { srPtr = nlsClient.CreateRecognizerRequest(); if (srPtr.native_request != IntPtr.Zero) { nlsResult.Text = "CreateRecognizerRequest Success"; } else { nlsResult.Text = "CreateRecognizerRequest Failed"; } cur_sr_result = "null"; cur_sr_closed = "null"; cur_sr_completed = "null"; } // start recognizer private void button6_Click(object sender, EventArgs e) { int ret = -1; if (srPtr.native_request != IntPtr.Zero) { srPtr.SetAppKey(srPtr, appKey); srPtr.SetToken(srPtr, token); srPtr.SetUrl(srPtr, url); srPtr.SetFormat(srPtr, "pcm"); srPtr.SetSampleRate(srPtr, 16000); srPtr.SetIntermediateResult(srPtr, true); srPtr.SetPunctuationPrediction(srPtr, true); srPtr.SetInverseTextNormalization(srPtr, true); string uuid = System.Guid.NewGuid().ToString("N"); srPtr.SetOnRecognitionStarted(srPtr, DemoOnRecognitionStarted, uuid); srPtr.SetOnChannelClosed(srPtr, DemoOnRecognitionClosed, uuid); srPtr.SetOnTaskFailed(srPtr, DemoOnRecognitionTaskFailed, uuid); srPtr.SetOnRecognitionResultChanged(srPtr, DemoOnRecognitionResultChanged, uuid); srPtr.SetOnRecognitionCompleted(srPtr, DemoOnRecognitionCompleted, uuid); ret = srPtr.Start(srPtr); if (sr_audio_loop_flag == false) { sr_audio_loop_flag = true; sr_send_audio = new Thread(SRAudioLab); sr_send_audio.Start(); } } if (ret != 0) { nlsResult.Text = "Recognizer Start failed"; } else { nlsResult.Text = "Recognizer Start success"; } } // stop recognizer private void button5_Click(object sender, EventArgs e) { int ret = -1; if (srPtr.native_request != IntPtr.Zero) ret = srPtr.Stop(srPtr); sr_send_audio_flag = false; sr_audio_loop_flag = false; if (ret != 0) { nlsResult.Text = "Recognizer Stop failed"; } else { nlsResult.Text = "Recognizer Stop success"; } } // release recognizer private void button7_Click(object sender, EventArgs e) { if (srPtr.native_request != IntPtr.Zero) { nlsClient.ReleaseRecognizerRequest(srPtr); srPtr.native_request = IntPtr.Zero; nlsResult.Text = "ReleaseRecognizerRequest Success"; } else { nlsResult.Text = "ReleaseRecognizerRequest is nullptr"; } cur_sr_result = "null"; cur_sr_closed = "null"; cur_sr_completed = "null"; } } }