本文介绍如何使用智能语音交互一句话识别的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核数的线程数。在高并发的情况下建议选择-1。这一接口有初始化NlsClient的作用。
ReleaseInstance
3.1.9
销毁NlsClient对象实例,即释放NLS SDK。此操作需要在销毁所有请求后再调用。
CreateNlsToken
3.1.9
创建Token获取对象,用于申请获取TokenId。详见下方NlsToken相关说明。
ReleaseNlsToken
3.1.9
销毁Token获取对象。
CreateRecognizerRequest
3.1.9
创建一句话识别对象,线程安全,支持高并发请求。
ReleaseRecognizerRequest
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回调的事件信息。
result
获取云端返回的识别结果,用于获得识别结果,如ResultChanged、Completed回调的事件信息。
识别接口
SpeechRecognizerRequest:一句话识别请求对象,用于短语音识别。
接口名
功能描述
SetOnTaskFailed
设置错误回调函数。
SetOnRecognitionStarted
设置一句话识别开始回调函数。
SetOnRecognitionResultChanged
设置一句话识别中间结果回调函数。
SetOnRecognitionCompleted
设置服务端结束服务回调函数。
SetOnChannelClosed
设置通道关闭回调函数。
SetAppKey
设置Appkey。
SetToken
口令认证。所有的请求都必须通过SetToken方法认证通过,才可以使用。
SetUrl
设置服务URL地址,默认可不设置则调用公有云上海域名的服务。
SetIntermediateResult
设置是否返回中间识别结果,结果会从OnRecognitionResultChanged回调返回。
SetPunctuationPrediction
设置是否在后处理中添加标点。
SetInverseTextNormalization
设置是否在后处理中执行数字转换。
SetEnableVoiceDetection
设置是否启动自定义静音检测。
SetMaxStartSilence
允许的最大开始静音,可选,单位为毫秒。超出后服务端将会发送RecognitionCompleted事件,开始本次识别。需要先设置SetEnableVoiceDetection为true. 建议设置为2000~5000。
SetMaxEndSilence
允许的最大结束静音,可选,单位是毫秒。超出后服务端将会发送RecognitionCompleted事件,结束本次识别。需要先设置SetEnableVoiceDetection为true. 建议时间0~5000。
SetFormat
设置音频数据编码格式,Windows环境推荐用PCM格式。
SetSampleRate
音频采样率设置。
SetCustomizationId
设置定制模型,例如
("TestId_123")
。SetVocabularyId
设置泛热词,例如
("TestId_456")
。SetTimeout
设置Socket接收超时时间。
SetOutputFormat
设置输出文本的编码格式。Windows平台下默认为GBK。非中文语种情况下,请设置成UTF-8,否则会出现乱码。
SetPayloadParam
参数设置,入参为JSON格式字符串。如指定声学模型,例如
"{\"model\":\"test-regression-model\"}")
。SetContextParam
设置用户自定义参数,入参为JSON格式字符串。
AppendHttpHeaderParam
设置用户自定义ws阶段http header参数。
Start
异步接口,启动SpeechRecognizerRequest。需要等待OnRecognitionStarted回调以确保请求进入工作状态。
Stop
异步接口,会与服务端确认关闭,正常停止链接操作。需要等待OnChannelClosed回调以确保请求结束工作状态。
Cancel
不会与服务端确认关闭,直接关闭链接。
SendAudio
异步接口,发送语音数据。为保证实时性,每次发送数据不建议太长,建议一次发送100ms时长以内的音频数据,范围为640字节~16384字节。
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文件大小参数。 |
-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 | 系统错误。 | 根据系统反馈的错误信息进行处理。 |
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。
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) { // 音频数据以PCM格式,byData.Length字节进行推送。 srPtr.SendAudio(srPtr, byData, (UInt64)byData.Length, EncoderType.ENCODER_PCM); } else { /* * 音频推送完成,重新打开循环继续 */ br.Close(); fs.Dispose(); fs = new FileStream(file_name, FileMode.Open, FileAccess.Read); br = new BinaryReader(fs); } } /* * 上面推送3200字节音频数据,相当于模拟100MS的音频。 * 真实环境从录音获得音频数据,不需要调用此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) { // 开启日志系统,以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) { // 获取当前SDK的版本号 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,与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"; } } }