本文介绍如何使用阿里云智能语音服务提供的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:统计参数合成。基于统计参数的语音合成,优点是能适应的韵律特征的范围较宽,合成器比特率低,资源占用小,性能高,音质适中。
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"; } } }