半夜起来给小朋友冲奶粉,于是忽然想到了那个在机柜里落灰的树莓派。当时用百度的语音识别和合成用python实现了一些功能。但是并没有实现语音唤醒,于是要想实现语音唤醒就只能不断的轮询接口,然后发送到百度云进行识别。但是觉得这种方式太坑了,什么都上传了,感觉随时在被监听一样。今天又看了下百度的sdk发现支持语音唤醒了。还能自定义唤醒词。
1 . 支持设置10个唤醒词,包含指令唤醒词和自定义唤醒词,指令唤醒词不支持自定义;10个唤醒词中,最多可以设置3个自定义唤醒词,最多可以包含3个两字指令唤醒词(如播放、暂停、拍照等)
2 . 已经支持的指令唤醒词有:
相机类:拍照、茄子
音乐类:增大音量、减小音量、播放、停止、暂停、上一首、下一首、
电灯类:打开电灯、关闭电灯、增大亮度、减小亮度
手电筒类:打开手电筒、关闭手电筒3 . 自定义唤醒词可根据应用的个性化需求来免费定制,例如您的应用希望通过“你好百度”启动应用,则就可以设置“你好百度”为唤醒词;
4 . 建议每个自定义唤醒词在3至5个字之间(这里的1个字是指1个汉字、或1个英文字母),4个字最佳;一个唤醒词可以包含最多2个(含)英文字母;唤醒词中暂时不支持纯英文单词,如california;
5 . 唤醒词定制的温馨提示:请勿选择太常用的词作为唤醒词,例如”吃饭吧”,在生活中经常会用到,容易误唤醒;为保证唤醒效果,不同意义的唤醒词,请考虑唤醒词之间的差异,尽量保证唤醒词之间不易混淆;唤醒词过短会导致唤醒错误率较高,请不要选择太多短唤醒词(包括指令唤醒词);
6 . 唤醒词的音节覆盖尽量多,长度最少为4个音节;相邻音节请尽可能规避,字要发音清晰响度大;生僻字请尽量规避;零声母字请尽量规避;请避免使用叠词;例如:质量较高的唤醒词:“百度外卖”,音节覆盖多差异大;质量较差的唤醒词:“语音识别”,“语音”两个字均为零声母字,不是一个质量高的唤醒词;
于是下载了百度的demo,在实际测试的时候却提示wakeup:no license。这是tm什么鬼,配置了appid和相关的属性发现效果并不明显。还是同样的错误。搜索了一下发现了这个帖子:
https://www.cnblogs.com/wantnon/p/4915028.html
需对demo进行如下修改:
- (void)configOfflineClient {
// 离线可识别自定义语法规则下的词,
NSString* gramm_filepath = [[NSBundle mainBundle] pathForResource:@"bds_easr_gramm" ofType:@"dat"];;
NSString* lm_filepath = [[NSBundle mainBundle] pathForResource:@"bds_easr_basic_model" ofType:@"dat"];;
NSString* wakeup_words_filepath = [[NSBundle mainBundle] pathForResource:@"bds_easr_wakeup_words" ofType:@"dat"];;
NSString* licenseFilePath = [[NSBundle mainBundle] pathForResource:@"temp_license_2017-11-25" ofType:@""];
[self.asrEventManager setDelegate:self];
[self.asrEventManager setParameter:lm_filepath forKey:BDS_ASR_OFFLINE_ENGINE_DAT_FILE_PATH];
[self.asrEventManager setParameter:licenseFilePath forKey:BDS_ASR_OFFLINE_LICENSE_FILE_PATH];
// 请在 (官网)[http://speech.baidu.com/asr] 参考模板定义语法,下载语法文件后,替换BDS_ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH参数
[self.asrEventManager setParameter:gramm_filepath forKey:BDS_ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH];
[self.asrEventManager setParameter:wakeup_words_filepath forKey:BDS_ASR_OFFLINE_ENGINE_WAKEUP_WORDS_FILE_PATH];
}
1,我下载了一个临时授权文件temp_license_2015-10-27,把它拖到xcode工程里。
2,然后在BDVRViewController.m中的loadOfflineEngine前加一句:
NSString* licenseFilePath = [[NSBundle mainBundle] pathForResource:@”temp_license_2015-10-27″ ofType:@””];
再把loadOfflineEngine的第二个参数license由nil改成licenseFilePath。
3,把BDVRSConfig.m中的
_recognitionProperty = [[NSNumber numberWithInt: EVoiceRecognitionPropertySearch] retain];
改成
_recognitionProperty = [[NSNumber numberWithInt: EVoiceRecognitionPropertyInput] retain];
然后就可以离线识别了。
参考:http://yuyin.baidu.com/bbs/q/552
—-补充:
关于百度语音离线识别(引自http://yuyin.baidu.com/bbs/q/538):离线只是作为在线识别的补充,不支持纯离线识别。授权成功后,会每隔一段时间不定期的再次进行认证授权的。
发现ok了,但是有个问题,那就是那个临时授权文件:
只有三十天的有效期?这tm长期运行不蛋疼了,还得一个月更新一次授权文件?于是搜索了一下这个属性:BDS_ASR_OFFLINE_ENGINE_DAT_FILE_PATH 找到了这么一段说明(https://cloud.baidu.com/doc/SPEECH/ASR-iOS-SDK/3F.5C.E6.9C.8D.E5.8A.A1.E7.AB.AF.E9.85.8D.E7.BD.AE.E7.9B.B8.E5.85.B3.html):
在线引擎身份验证
参数名称 | 说明 |
---|---|
BDS_ASR_API_SECRET_KEYS | 开放平台设置API_KEY and SECRET_KEY |
BDS_ASR_PRODUCT_ID | 内部产品设置产品ID |
离线引擎身份验证
参数名称 | 说明 |
---|---|
BDS_ASR_OFFLINE_LICENSE_FILE_PATH | 离线授权文件路径 |
BDS_ASR_OFFLINE_APP_CODE | 离线授权所需APPCODE(APPID), 如使用该方式进行正式授权,请移除临时授权文件 |
看起来像是那么一回事,但是问题是实例代码里面写的就是appid,为啥不行?问题是还有一点。这个应用包名是干嘛的?没用?看意思这个东西是校验授权的。于是果断的把appid换成应用包名,去掉授权文件,再次运行ok了。
[self.asrEventManager setParameter:@"com.mars.homeai" forKey:BDS_ASR_OFFLINE_APP_CODE];
对百度的文档能力深表同情,以前用python根据rest api写的代码就踩了无数坑(那时候还没有python sdk)。现在他们依然这么坑!