本文介紹如何使用阿里云智能語音服務提供的C# SDK,包括SDK的安裝方法及SDK代碼示例。
SDK下載
當前最新版本:3.1.17,該版本基于C++ SDK API 3.1.x。發布日期: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包內含相關庫文件、頭文件,無需編譯。
最新SDK包
平臺
MD5
SDK源碼
8beeaad832d4b249464f4338429c3b15
Windows
81fdd1579e103d8c93b4dab98ee0f71c
其中:
alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip為SDK源碼包。
NlsCsharpSdk_Windows_<版本號>_<github commit id>.zip為Windows平臺下開發需要的SDK包,詳見內部readme.md。
Windows平臺C#編譯運行
推薦直接使用已經編譯好的庫NlsCsharpSdk_Windows_<version>_<github commit id>.zip進行集成。若有編譯需求,請下載alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip并解壓到本地,或從GitHub獲取最新代碼,然后參考其中readme.md的編譯步驟。
關鍵接口
using nlsCsharpSdk;
基礎接口
NlsClient:語音處理客戶端,利用該客戶端可以進行一句話識別、實時語音識別和語音合成的語音處理任務。該客戶端為線程安全,建議全局僅創建一個實例。
接口名
啟用版本
功能描述
SetLogConfig
3.1.9
設置日志文件與存儲路徑。越早調用記錄的信息越詳細。
GetVersion
3.1.9
獲取SDK版本號。
CreateNlsToken
3.1.9
創建Token獲取對象,用于獲取阿里云token,詳見下方NlsToken相關表格。
ReleaseNlsToken
3.1.9
銷毀CreateNlsToken所建立的NlsToken對象。
SetDirectHost
3.1.16
跳過DNS域名解析直接設置服務器IP地址,若調用則需要在StartWorkThread之前。
StartWorkThread
3.1.9
啟動工作線程數,默認1即啟動一個線程,若-1則啟動CPU核數的線程數。在高并發的情況下建議選擇4。這一接口有初始化NlsClient的作用。
ReleaseInstance
3.1.9
銷毀NlsClient對象實例,即釋放NLS SDK。此操作需要在銷毀所有請求后再調用。
CreateNlsToken
3.1.9
創建Token獲取對象,用于申請獲取TokenId。詳見下方NlsToken相關說明。
ReleaseNlsToken
3.1.9
銷毀Token獲取對象。
CreateSynthesizerRequest
3.1.9
創建語音合成對象,線程安全,支持高并發請求。通過入參控制短文本/長文本模式,更多信息請參見接口說明。
ReleaseSynthesizerRequest
3.1.9
銷毀語音合成對象,需要在當前請求的closed事件后調用。
NlsToken:創建Token對象,用于申請獲取TokenId。申請新Token時需要先獲取有效時間戳,若超過有效時間則再申請。若在有效時間內多次申請Token會導致TokenId錯誤而無法使用。
接口名
功能描述
SetAccessKeyId
設置阿里云賬號AccessKey ID。
SetKeySecret
設置阿里云賬號AccessKey Secret。
ApplyNlsToken
申請獲取TokenId。此TokenId在有效期內對所有此阿里云賬號AccessKey ID下的所有語音請求有效,無需在每個語音請求前申請獲得。
GetToken
獲取TokenId。
GetExpireTime
獲取Token有效期時間戳(秒)。
GetErrorMsg
獲取TokenId失敗的錯誤信息。
NlsEvent:事件對象NLS_EVENT_STRUCT,通過CallbackDelegate返回。您可以從中獲取Request狀態碼、云端返回結果、失敗信息等。
接口名
功能描述
statusCode
獲取狀態碼,正常情況為0或者20000000,失敗時對應失敗的錯誤碼。
taskId
獲取任務的TaskId。
msg
獲取云端返回的response結果,用于獲得事件信息,如Started、Closed、TaskFailed、Conpleted、MetaInfo回調的事件信息。
result
獲取云端返回的識別結果,語音合成功能中此參數同msg。
識別接口
SpeechSynthesizerRequest:語音合成請求對象,用于語音合成及長文本語音合成。
接口名
功能描述
SetOnSynthesisCompleted
設置語音合成結束回調函數。
SetOnChannelClosed
設置通道關閉回調函數。
SetOnTaskFailed
設置錯誤回調函數。
SetOnBinaryDataReceived
設置語音合成二進制音頻數據接收回調函數。
SetOnMetaInfo
設置文本對應的日志信息接收回調函數。
SetAppKey
設置Appkey。
SetToken
口令認證。所有的請求都必須通過SetToken方法認證通過,才可以使用。
SetUrl
設置服務URL地址,默認可不設置則調用公有云上海域名的服務。
SetText
待合成音頻文本內容text設置,UTF-8格式。短文本語音合成模式下默認,支持一次性合成300字符以內的文字,其中1個漢字、1個英文字母或1個標點均算作1個字符,超過300個字符的內容將會報錯或者截斷。超過300個字符可考慮長文本語音合成,更多信息請參見接口說明。
SetVoice
發音人voice設置,更多信息請參見接口說明。
SetVolume
音量volume設置。范圍為0~100,可選參數,默認50。
SetFormat
輸出音頻編碼格式Format設置。
SetSampleRate
音頻采樣率設置。
SetSpeechRate
語速設置。范圍為-500~500,可選參數,默認是0。
SetPitchRate
語調設置。范圍為-500~500,可選參數,默認是0。
SetEnableSubtitle
是否開啟字幕功能。開啟后可獲得詳細的合成信息,比如每個字的時間戳,通過MetaInfo回調返回。
SetMethod
合成方法method設置,默認為0。
0:統計參數合成?;诮y計參數的語音合成,優點是能適應的韻律特征的范圍較寬,合成器比特率低,資源占用小,性能高,音質適中。
1:波形拼接合成?;诟哔|量音庫提取學習合成,資源占用相對較高,音質較好,更加貼近真實發音,但沒有參數合成穩定。
SetTimeout
設置Socket接收超時時間。
SetPayloadParam
參數設置,入參為JSON格式字符串。如指定聲學模型,例如
"{\"model\":\"test-regression-model\"}")
。SetContextParam
設置用戶自定義參數,入參為JSON格式字符串。
SetOutputFormat
設置輸出文本的編碼格式,Windows平臺下默認為GBK。非中文語種情況下,請設置成UTF-8,否則會出現亂碼。
GetOutputFormat
獲得輸出文本的編碼格式,Windows平臺下默認為GBK。
AppendHttpHeaderParam
設置用戶自定義ws階段http header參數。
Start
異步接口,啟動SpeechSynthesizerRequest。
Cancel
不會與服務端確認關閉,直接關閉語音合成過程。
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編碼器創建失敗 | 建議重新初始化。 |
-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 | 成功 |
服務端響應狀態碼
關于服務狀態碼,請參見服務狀態碼。
代碼示例
示例中使用的音頻文件為16000 Hz采樣率,管控臺設置的模型為通用模型。如果使用其他音頻,請設置為支持該音頻場景的模型。關于模型設置,請參見管理項目。
示例中使用了SDK內置的默認語音合成服務的外網訪問服務URL,如果您使用阿里云上海ECS且需要使用內網訪問URL,則在創建SpeechSynthesizerRequest的對象中設置內網訪問的URL。
SpeechSynthesizerRequest syPtr; syPtr.SetUrl(syPtr, "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 SpeechSynthesizerRequest syPtr; 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 string cur_sy_completed; static string cur_sy_closed; private void FlushLab() { while (running) { if (cur_nls_result != null && cur_nls_result.Length > 0) { nlsResult.Text = cur_nls_result; } if (cur_st_result != null && cur_st_result.Length > 0) { stResult.Text = cur_st_result; } if (cur_st_completed != null && cur_st_completed.Length > 0) { stCompleted.Text = cur_st_completed; } if (cur_st_closed != null && cur_st_closed.Length > 0) { stClosed.Text = cur_st_closed; } 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; } if (cur_sy_completed != null && cur_sy_completed.Length > 0) { syCompleted.Text = cur_sy_completed; } if (cur_sy_closed != null && cur_sy_closed.Length > 0) { syClosed.Text = cur_sy_closed; } Thread.Sleep(200); } } public nlsCsharpSdkDemo() { InitializeComponent(); System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//設置該屬性 為false nlsClient = new NlsClient(); } private void button1_Click(object sender, EventArgs e) { // 開啟日志系統,以Debug級別將名字為nlsLog.log的日志以單個400MB 10個日志文件循環的形式儲存。 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) { string version = nlsClient.GetVersion(); nlsResult.Text = version; } private void button1_Click_2(object sender, EventArgs e) { // -1則表示啟動CPU核數的事件池數量,用于進行內部事件的處理。 // 單路調用的情況下,建議入參為1,即啟動單個事件池進行處理。 // 高并發(幾百路)的情況下,入參建議4 ~ CPU核數,入參越大,處理延遲越低但是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.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 = -1; 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 SynthesizerCallback private CallbackDelegate DemoOnBinaryDataReceived = (ref NLS_EVENT_STRUCT e,ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnBinaryDataReceived uuid = {0}", uuid); System.Diagnostics.Debug.WriteLine("DemoOnBinaryDataReceived taskId = {0}", e.taskId); System.Diagnostics.Debug.WriteLine("DemoOnBinaryDataReceived dataSize = {0}", e.binaryDataSize); //cur_sy_completed = e.taskId + ", binaryDataSize : " + e.binaryDataSize; }; private CallbackDelegate DemoOnSynthesisClosed = (ref NLS_EVENT_STRUCT e, ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnSynthesisClosed user uuid = {0}", uuid); string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0'); System.Diagnostics.Debug.WriteLine("DemoOnSynthesisClosed msg = {0}", msg); cur_sy_closed = "msg : " + msg; }; private CallbackDelegate DemoOnSynthesisTaskFailed = (ref NLS_EVENT_STRUCT e, ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnSynthesisTaskFailed user uuid = {0}", uuid); string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0'); System.Diagnostics.Debug.WriteLine("DemoOnSynthesisTaskFailed msg = {0}", msg); cur_sy_completed = "msg : " + msg; }; private CallbackDelegate DemoOnSynthesisCompleted = (ref NLS_EVENT_STRUCT e, ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnSynthesisCompleted user uuid = {0}", uuid); string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0'); System.Diagnostics.Debug.WriteLine("DemoOnSynthesisCompleted msg = {0}", msg); cur_sy_completed = "result : " + msg; }; private CallbackDelegate DemoOnMetaInfo = (ref NLS_EVENT_STRUCT e, ref string uuid) => { System.Diagnostics.Debug.WriteLine("DemoOnMetaInfo user uuid = {0}", uuid); // 若識別為非中文,請設置UTF-8格式,并用UTF-8解碼,否則可能亂碼。 // string msg = System.Text.Encoding.UTF8.GetString(e.msg).TrimEnd('\0'); string msg = System.Text.Encoding.Default.GetString(e.msg).TrimEnd('\0'); System.Diagnostics.Debug.WriteLine("DemoOnMetaInfo msg = {0}", msg); cur_sy_completed = "metaInfo : " + msg; }; #endregion // create synthesizer private void button12_Click(object sender, EventArgs e) { /* * 默認為實時短文本語音合成請求, 支持一次性合成300字符以內的文字, * 其中1個漢字、1個英文字母或1個標點均算作1個字符, * 超過300個字符的內容將會報錯(或者截斷). * 一次性合成超過300字符可考慮長文本語音合成功能. */ syPtr = nlsClient.CreateSynthesizerRequest(TtsVersion.ShortTts); if (syPtr.native_request != IntPtr.Zero) { nlsResult.Text = "CreateSynthesizerRequest Success"; } else { nlsResult.Text = "CreateSynthesizerRequest Failed"; } cur_sy_closed = "null"; cur_sy_completed = "null"; } // start synthesizer private void button10_Click(object sender, EventArgs e) { int ret = -1; if (syPtr.native_request != IntPtr.Zero) { syPtr.SetAppKey(syPtr, appKey); syPtr.SetToken(syPtr, token); syPtr.SetUrl(syPtr, url); syPtr.SetText(syPtr, "今天天氣真不錯,我想去操場踢足球。"); syPtr.SetVoice(syPtr, "siqi"); syPtr.SetVolume(syPtr, 50); syPtr.SetFormat(syPtr, "wav"); syPtr.SetSampleRate(syPtr, 16000); syPtr.SetSpeechRate(syPtr, 0); syPtr.SetPitchRate(syPtr, 0); syPtr.SetEnableSubtitle(syPtr, true); // 開啟字幕 string uuid = System.Guid.NewGuid().ToString("N"); syPtr.SetOnSynthesisCompleted(syPtr, DemoOnSynthesisCompleted, uuid); syPtr.SetOnBinaryDataReceived(syPtr, DemoOnBinaryDataReceived, uuid); syPtr.SetOnTaskFailed(syPtr, DemoOnSynthesisTaskFailed, uuid); syPtr.SetOnChannelClosed(syPtr, DemoOnSynthesisClosed, uuid); syPtr.SetOnMetaInfo(syPtr, DemoOnMetaInfo, uuid); ret = syPtr.Start(syPtr); } if (ret != 0) { nlsResult.Text = "Synthesizer Start failed"; } else { nlsResult.Text = "Synthesizer Start success"; } } // cancel synthesizer private void button9_Click(object sender, EventArgs e) { int ret = -1; if (syPtr.native_request != IntPtr.Zero) ret = syPtr.Cancel(syPtr); if (ret != 0) { nlsResult.Text = "Synthesizer Cancel failed"; } else { nlsResult.Text = "Synthesizer Cancel success"; } } private void btnSYrelease_Click(object sender, EventArgs e) { if (syPtr.native_request != IntPtr.Zero) { nlsClient.ReleaseSynthesizerRequest(syPtr); syPtr.native_request = IntPtr.Zero; nlsResult.Text = "ReleaseSynthesizerRequest Success"; } else { nlsResult.Text = "ReleaseSynthesizerRequest is nullptr"; } cur_sy_closed = "null"; cur_sy_completed = "null"; } } }