本文介绍如何使用阿里云智能语音服务提供的iOS NUI SDK,包括SDK下载安装、关键接口及代码示例。
前提条件
下载安装
-
说明
请下载后在样例初始化代码中替换您的阿里云账号信息、Appkey和Token才可运行。为方便集成,2.5.14版本后iOS接口使用纯Object-C接口,不再使用C++混合接口。
类别
兼容范围
系统
最低支持iOS9。
架构
arm64,x86_64
此SDK还包含如下功能,若未支持您想要的功能,请前往对应文档获取SDK。
功能
是否支持
一句话识别
是
实时语音识别
是
语音合成
是
实时长文本语音合成
是
离线语音合成
否
录音文件识别极速版
是
唤醒及命令词
否
-
解压ZIP包,将zip包中的nuisdk.framework添加到您的工程中,并在工程Build Phases的Link Binary With Libraries中添加nuisdk.framework。
-
使用Xcode打开此工程,工程中提供了参考代码以及一些直接可使用的工具类,例如音频播放录制和文件操作,您可以直接复制源码到您的实际工程进行使用。其中一句话识别示例代码为SpeechRecognizerViewController。替换Appkey和Token后可直接运行。
SDK关键接口
-
nui_initialize :初始化SDK。
/** * 初始化SDK,SDK为单例,请先释放后再次进行初始化。请勿在UI线程调用,可能引起阻塞。 * @param parameters: 初始化参数,参见接口说明文档 * @param level: log打印级别,值越小打印越多 * @param save_log: 是否保存log为文件,存储目录为parameter中的debug_path字段值 * @return 参见错误码 -(NuiResultCode) nui_initialize:(const char *)parameters logLevel:(NuiSdkLogLevel)level saveLog:(BOOL)save_log;
-
nui_set_params :以JSON格式设置SDK参数。
/** * 以JSON格式设置参数 * @param params: 参数信息请参见接口说明文档 * @return 参见错误码 -(NuiResultCode) nui_set_params:(const char *)params;
-
nui_dialog_start :开始识别。
/** * 开始识别 * @param vad_mode: 多种模式,对于识别场景,请使用P2T * @param dialog_params: 设置识别参数,可不设置 * @return 参见错误码 -(NuiResultCode) nui_dialog_start:(NuiVadMode)vad_mode dialogParam:(const char *)dialog_params;
-
nui_dialog_cancel :结束识别。
/** * 结束识别,调用该接口后,服务端将返回最终识别结果并结束任务 * @param force: 是否强制结束而忽略最终结果,false或NO表示停止但是等待完整结果返回 * @return 参见错误码 -(NuiResultCode) nui_dialog_cancel:(BOOL)force;
-
nui_release :释放SDK。
/** * 释放SDK资源 * @return 参见错误码 -(NuiResultCode) nui_release;
-
NeoNuiSdkDelegate: 事件代理
onNuiEventCallback:SDK事件回调。
/** * SDK主要事件回调 * @param event: 回调事件,参见如下事件列表 * @param dialog: 会话编号,暂不使用 * @param wuw: 语音唤醒功能使用(暂不支持) * @param asr_result: 语音识别结果 * @param finish: 本轮识别是否结束标志 * @param resultCode: 参见错误码,在出现EVENT_ASR_ERROR事件时有效 -(void) onNuiEventCallback:(NuiCallbackEvent)nuiEvent dialog:(long)dialog kwsResult:(const char *)wuw asrResult:(const char *)asr_result ifFinish:(BOOL)finish retCode:(int)code;
NuiCallbackEvent事件列表:
名称
说明
EVENT_VAD_START
检测到人声起点。
EVENT_VAD_END
检测到人声尾点。
EVENT_ASR_PARTIAL_RESULT
语音识别中间结果。
EVENT_ASR_RESULT
语音识别最终结果。
EVENT_ASR_ERROR
根据错误码信息判断出错原因。
EVENT_MIC_EEROR
录音错误,表示SDK连续2秒未收到任何音频,可检查录音系统是否正常。
onNuiNeedAudioData:获取音频
/** * 开始识别时,此回调被连续调用,App需要在回调中进行语音数据填充 * @param audioData: 填充语音的存储区 * @param len: 需要填充语音的字节数 * @return 实际填充的字节数 -(int) onNuiNeedAudioData:(char *)audioData length:(int)len;
onNuiAudioStateChanged:根据音频状态进行录音功能的开关。
/** * 当start/stop/cancel等接口调用时,SDK通过此回调通知App进行录音的开关操作 * @param state:录音需要的状态(打开/关闭) -(void) onNuiAudioStateChanged:(NuiAudioState)state;
onNuiRmsChanged:音频能量事件。
/** * SDK主要事件回调 * @param rms: 语音能量值,范围为-160至0 -(void) onNuiRmsChanged:(float) rms;
调用步骤
-
初始化SDK、录音实例。
-
根据业务需求配置参数。
-
调用nui_dialog_start开始识别。
-
根据音频状态回调onNuiAudioStateChanged,打开录音机。
-
在onNuiNeedAudioData回调中提供录音数据。
-
在EVENT_ASR_PARTIAL_RESULT事件回调中获取识别结果。
-
调用nui_dialog_cancel结束识别。
-
结束调用,使用release接口释放SDK资源。
代码示例
接口默认采用get_instance方式获得单例,您如果有多例需求,也可以直接alloc对象进行使用。
NUI SDK初始化
NSString * initParam = [self genInitParams];
[_nui nui_initialize:[initParam UTF8String] logLevel:LOG_LEVEL_VERBOSE saveLog:save_log];
其中,genInitParams生成为String JSON字符串,包含资源目录和用户信息。其中用户信息包含如下字段,获取方式请参见 接口说明 。
//账号和项目创建
// ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
[dictM setObject:@"<您申请创建的app_key>" forKey:@"app_key"]; // 必填
//获取token方式:
//方法1:
// 首先ak_id ak_secret app_key如何获得,请查看https://help.aliyun.com/document_detail/72138.html
// 然后请看 https://help.aliyun.com/document_detail/466615.html 使用其中方案一获取临时凭证
// 此方案简介: 远端服务器使用以下方法获得有效时限的临时凭证, 下发给移动端进行使用, 保证账号信息ak_id和ak_secret不被泄露
// 获得Token方法(运行在APP服务端): https://help.aliyun.com/document_detail/450255.html?spm=a2c4g.72153.0.0.79176297EyBj4k
[dictM setObject:@"<服务器生成的具有时效性的临时凭证>" forKey:@"token"]; // 必填
//方法2:
// STS获取临时凭证方法暂不支持
// 推荐填入具有唯一性的id, 方便定位问题
[dictM setObject:id_string forKey:@"device_id"]; // 必填
参数设置
以JSON字符串形式进行设置。
-(NSString*) genParams {
NSMutableDictionary *nls_config = [NSMutableDictionary dictionary];
[nls_config setValue:@YES forKey:@"enable_intermediate_result"];
//参数可根据实际业务进行配置 https://help.aliyun.com/document_detail/173298.html?spm=a2c4g.173528.0.0.47f05398HEpSxW
// 若要使用VAD模式,则需要设置nls_config参数启动在线VAD模式
//[nls_config setValue:@YES forKey:@"enable_voice_detection"];
//[nls_config setValue:@10000 forKey:@"max_start_silence"];
//[nls_config setValue:@800 forKey:@"max_end_silence"];
NSMutableDictionary *dictM = [NSMutableDictionary dictionary];
[dictM setObject:nls_config forKey:@"nls_config"];
[dictM setValue:@(SERVICE_TYPE_ASR) forKey:@"service_type"]; // 必填
NSData *data = [NSJSONSerialization dataWithJSONObject:dictM options:NSJSONWritingPrettyPrinted error:nil];
NSString * jsonStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
return jsonStr;
NSString * parameters = [self genParams];
[_nui nui_set_params:[parameters UTF8String]];
开始识别
通过nui_dialog_start接口开启监听。
//若要使用VAD模式,则需要设置nls_config参数启动在线VAD模式(见genParams())
[_nui nui_dialog_start:MODE_P2T dialogParam:[param_string UTF8String]];
回调处理
-
onNuiAudioStateChanged :录音状态回调,SDK内部维护录音状态,调用时根据该状态的回调进行录音机的开关操作。
-(void)onNuiAudioStateChanged:(NuiAudioState)state{ TLog(@"onNuiAudioStateChanged state=%u", state); if (state == STATE_CLOSE || state == STATE_PAUSE) { [_voiceRecorder stop:YES]; } else if (state == STATE_OPEN){ self.recordedVoiceData = [NSMutableData data]; [_voiceRecorder start]; }
-
onNuiNeedAudioData :录音数据回调,在该回调中填充录音数据。
-(int)onNuiNeedAudioData:(char *)audioData length:(int)len { static int emptyCount = 0; @autoreleasepool { @synchronized(_recordedVoiceData){ if (_recordedVoiceData.length > 0) { int recorder_len = 0; if (_recordedVoiceData.length > len) recorder_len = len; recorder_len = _recordedVoiceData.length; NSData *tempData = [_recordedVoiceData subdataWithRange:NSMakeRange(0, recorder_len)]; [tempData getBytes:audioData length:recorder_len]; tempData = nil; NSInteger remainLength = _recordedVoiceData.length - recorder_len; NSRange range = NSMakeRange(recorder_len, remainLength); [_recordedVoiceData setData:[_recordedVoiceData subdataWithRange:range]]; emptyCount = 0; return recorder_len; } else { if (emptyCount++ >= 50) { TLog(@"_recordedVoiceData length = %lu! empty 50times.", (unsigned long)_recordedVoiceData.length); emptyCount = 0; return 0; return 0; }
-
onNuiEventCallback :NUI SDK事件回调,请勿在事件回调中调用SDK的接口,可能引起死锁。
-(void)onNuiEventCallback:(NuiCallbackEvent)nuiEvent dialog:(long)dialog kwsResult:(const char *)wuw asrResult:(const char *)asr_result ifFinish:(bool)finish retCode:(int)code { TLog(@"onNuiEventCallback event %d finish %d", nuiEvent, finish); if (nuiEvent == EVENT_ASR_PARTIAL_RESULT || nuiEvent == EVENT_ASR_RESULT) { TLog(@"ASR RESULT %s finish %d", asr_result, finish); NSString *result = [NSString stringWithUTF8String:asr_result]; [myself showAsrResult:result]; } else if (nuiEvent == EVENT_ASR_ERROR) { TLog(@"EVENT_ASR_ERROR error[%d]", code); } else if (nuiEvent == EVENT_MIC_ERROR) { TLog(@"MIC ERROR"); [_voiceRecorder stop:YES]; [_voiceRecorder start]; if (finish) { [myself showStart]; return; }
结束识别
[_nui nui_dialog_cancel:NO];