最近公司需要开发机器人聊天带语音的功能 ,通过一些筛选,最终选择了百度UNIT交互已经百度本身的语音集成到程序里,这里做下记录,方便以后学习,也希望可以帮助到需要的人(测试时候必须真机测试 否则会报错)
模拟器运行报错
首先到百度语音平台下载对应的SDK 选择UNIT iOS SDK下载 如下截图
下载完成之后得到文件 运行Unitdemo演示程序
运行成功如截图
运行正常然后按照演的demo脱文件UnitSDK和文件libs文件到需要集成的APP中
这里需要注意 libs文件中的BDSClientResources文件需要拖入是取消第一个选择
填入对应的Framwork文件 截图取至百度云语音集成平台
如果Xcode版本可以自动添加.m文件 手动去Build Phases删除AudioDataQueue文件 否则会报C++错误 删除.mm文件 否则会报错
接下来上具体集成代码
// 按需求引入头文件
#import "AIPUnitSDK.h"
// 内置识别控件
#import "BDRecognizerViewController.h"
// 识别相关
#import "BDSEventManager.h"
#import "BDSASRDefines.h"
#import "BDSASRParameters.h"
// 唤醒相关
#import "BDSWakeupDefines.h"
#import "BDSWakeupParameters.h"
// 引入代理协议BDRecognizerViewDelegate
-(void)viewdidload{
inputview = [[UITextField alloc]initWithFrame:CGRectMake(20, 5, kScreenWidth-40, 40)];
inputview.layer.cornerRadius = 10;
inputview.layer.masksToBounds = YES;
inputview.layer.borderWidth = 1;
inputview.layer.borderColor = [[UIColor lightGrayColor] CGColor];
inputview.returnKeyType = UIReturnKeySend; //(如上图的send ,在真机上会显示发送二字的)
inputview.delegate = self;
// [_inputTextViewBkView addSubview:_inputTextView];
[textviwe addSubview:inputview];
[self.view addSubview:textviwe];
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 30, 30);
[button addTarget:self action:@selector(sdkUIRecognitionAction:) forControlEvents:UIControlEventTouchUpInside];
[button setImage:[UIImage imageNamed:@"speaker"] forState:UIControlStateNormal];
inputview.rightView = button;
inputview.rightViewMode = UITextFieldViewModeAlways;
[SVProgressHUD setDefaultMaskType:SVProgressHUDMaskTypeGradient];
[SVProgressHUD show];
// API_KEY SECRET_KEY 必须去百度语音官网创建应用程序获得 要和程序boundleID保持一致 具体过程百度语音官网上很详细
[[AIPUnitSDK sharedInstance] getAccessTokenWithAK:API_KEY SK:SECRET_KEY completion:^{
[SVProgressHUD dismiss];
}];
[[AIPUnitSDK sharedInstance] setSceneID:3087];
// self.titleLabel.text = @"选股机器人";
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if ([AIPUnitSDK sharedInstance].accessToken != nil) {
[weakSelf askWord:@"你好"];
} else {
weakSelf.waitTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(waitAccessToken) userInfo:nil repeats:YES];
}
});
// 配置语音
self.asrEventManager = [BDSEventManager createEventManagerWithName:BDS_ASR_NAME];
//设置DEBUG_LOG的级别
[self.asrEventManager setParameter:@(EVRDebugLogLevelTrace) forKey:BDS_ASR_DEBUG_LOG_LEVEL];
//配置API_KEY 和 SECRET_KEY
[self.asrEventManager setParameter:@[API_KEY2, SECRET_KEY2] forKey:BDS_ASR_API_SECRET_KEYS];
[self.asrEventManager setParameter:APPID2 forKey:BDS_ASR_OFFLINE_APP_CODE];
//配置端点检测
NSString *modelVAD_filepath = [[NSBundle mainBundle] pathForResource:@"bds_easr_basic_model" ofType:@"dat"];
[self.asrEventManager setParameter:modelVAD_filepath forKey:BDS_ASR_MODEL_VAD_DAT_FILE];
[self.asrEventManager setParameter:@(YES) forKey:BDS_ASR_ENABLE_MODEL_VAD];
}
- (void)waitAccessToken {
if ([AIPUnitSDK sharedInstance].accessToken != nil) {
[self.waitTimer invalidate];
self.waitTimer = nil;
[self askWord:@"你好"];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[inputview resignFirstResponder];
}
#pragma mark - Button Action
- (void)hint:(UIButton *)sender {
[inputview resignFirstResponder];
if (sender.currentTitle.length == 0) {
return;
}
[_mainArray addObject:@{@"chat":sender.currentTitle,@"type":@(1)}];
self.bottomLayoutConstraint.constant = 0;
[self askWord:sender.currentTitle];
}
- (void)sdkUIRecognitionAction:(UIButton *)button
{
[inputview resignFirstResponder];
[self.asrEventManager setParameter:@"" forKey:BDS_ASR_AUDIO_FILE_PATH];
[self configFileHandler];
[self configRecognizerViewController];
[self.recognizerViewController startVoiceRecognition];
}
- (void)configRecognizerViewController {
BDRecognizerViewParamsObject *paramsObject = [[BDRecognizerViewParamsObject alloc] init];
paramsObject.isShowTipAfterSilence = YES;
paramsObject.isShowHelpButtonWhenSilence = NO;
paramsObject.tipsTitle = @"您可以这样问";
paramsObject.tipsList = [NSArray arrayWithObjects:@"我要吃饭", @"我要买电影票", @"我要订酒店", nil];
paramsObject.waitTime2ShowTip = 0.5;
paramsObject.isHidePleaseSpeakSection = YES;
paramsObject.disableCarousel = NO;
self.recognizerViewController = [[BDRecognizerViewController alloc] initRecognizerViewControllerWithOrigin:CGPointMake((self.view.bounds.size.width - 300)/2.0f, 100)
theme:nil
enableFullScreen:NO
paramsObject:paramsObject
delegate:self];
// [self.view addSubview:self.recognizerViewController.view];
// self.recognizerViewController.view.backgroundColor = [UIColor redColor];
speekView = [[UIView alloc]initWithFrame:CGRectMake(20, 30, kScreenWidth-40, 220)];
// speekView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.recognizerViewController.view.bounds.size.width, self.recognizerViewController.view.bounds.size.height)];
speekView.backgroundColor = [UIColor whiteColor];
speekView.alpha = 0.6;
speekView.layer.cornerRadius = 15;
speekView.layer.masksToBounds = YES;
speekView.layer.borderWidth = 1;
speekView.layer.borderColor = [[UIColor lightGrayColor] CGColor];
[self.view addSubview:speekView];
}
- (void)configFileHandler {
self.fileHandler = [self createFileHandleWithName:@"recoder.pcm" isAppend:NO];
}
#pragma mark - BDRecognizerViewDelegate
- (void)onEndWithViews:(BDRecognizerViewController *)aBDRecognizerViewController withResult:(id)aObj {
if ([aObj isKindOfClass:[NSDictionary class]]) {
NSDictionary* dict = (NSDictionary *)aObj;
inputview.text = dict[@"results_recognition"][0];
[self textFieldShouldReturn:inputview];
}
}
#pragma mark - MVoiceRecognitionClientDelegate
- (void)VoiceRecognitionClientWorkStatus:(int)workStatus obj:(id)aObj {
// NSLog(@"调用语音");
switch (workStatus) {
case EVoiceRecognitionClientWorkStatusNewRecordData: {
NSLog(@"EVoiceRecognitionClientWorkStatusNewRecordData");
//[self.fileHandler writeData:(NSData *)aObj];
break;
}
case EVoiceRecognitionClientWorkStatusStartWorkIng: {
NSDictionary *logDic = [self parseLogToDic:aObj];
[self printLogTextView:[NSString stringWithFormat:@"CALLBACK: start vr, log: %@\n", logDic]];
[self onStartWorking];
break;
}
case EVoiceRecognitionClientWorkStatusStart: {
[self printLogTextView:@"CALLBACK: detect voice start point.\n"];
break;
}
case EVoiceRecognitionClientWorkStatusEnd: {
[self printLogTextView:@"CALLBACK: detect voice end point.\n"];
break;
}
case EVoiceRecognitionClientWorkStatusFlushData: {
[self printLogTextView:[NSString stringWithFormat:@"CALLBACK: partial result - %@.\n\n", [self getDescriptionForDic:aObj]]];
break;
}
case EVoiceRecognitionClientWorkStatusFinish: {
[self printLogTextView:[NSString stringWithFormat:@"CALLBACK: final result - %@.\n\n", [self getDescriptionForDic:aObj]]];
if ([aObj isKindOfClass:[NSDictionary class]]) {
NSDictionary* dict = (NSDictionary *)aObj;
inputview.text = dict[@"results_recognition"][0];
[self textFieldShouldReturn:inputview];
}
[self onEnd];
break;
}
case EVoiceRecognitionClientWorkStatusMeterLevel: {
break;
}
case EVoiceRecognitionClientWorkStatusCancel: {
[self printLogTextView:@"CALLBACK: user press cancel.\n"];
[self onEnd];
break;
}
case EVoiceRecognitionClientWorkStatusError: {
[self printLogTextView:[NSString stringWithFormat:@"CALLBACK: encount error - %@.\n", (NSError *)aObj]];
[self onEnd];
break;
}
case EVoiceRecognitionClientWorkStatusLoaded: {
[self printLogTextView:@"CALLBACK: offline engine loaded.\n"];
break;
}
case EVoiceRecognitionClientWorkStatusUnLoaded: {
[self printLogTextView:@"CALLBACK: offline engine unLoaded.\n"];
break;
}
case EVoiceRecognitionClientWorkStatusChunkThirdData: {
[self printLogTextView:[NSString stringWithFormat:@"CALLBACK: Chunk 3-party data length: %lu\n", (unsigned long)[(NSData *)aObj length]]];
break;
}
case EVoiceRecognitionClientWorkStatusChunkNlu: {
NSString *nlu = [[NSString alloc] initWithData:(NSData *)aObj encoding:NSUTF8StringEncoding];
[self printLogTextView:[NSString stringWithFormat:@"CALLBACK: Chunk NLU data: %@\n", nlu]];
break;
}
case EVoiceRecognitionClientWorkStatusChunkEnd: {
[self printLogTextView:[NSString stringWithFormat:@"CALLBACK: Chunk end, sn: %@.\n", aObj]];
// if (!self.longSpeechFlag) {
[self onEnd];
// }
break;
}
case EVoiceRecognitionClientWorkStatusFeedback: {
NSDictionary *logDic = [self parseLogToDic:aObj];
[self printLogTextView:[NSString stringWithFormat:@"CALLBACK Feedback: %@\n", logDic]];
break;
}
case EVoiceRecognitionClientWorkStatusRecorderEnd: {
[self printLogTextView:@"CALLBACK: recorder closed.\n"];
break;
}
case EVoiceRecognitionClientWorkStatusLongSpeechEnd: {
[self printLogTextView:@"CALLBACK: Long Speech end.\n"];
[self onEnd];
break;
}
default:
break;
}
}
- (NSString *)getFilePath:(NSString *)fileName {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if (paths && [paths count]) {
return [[paths objectAtIndex:0] stringByAppendingPathComponent:fileName];
} else {
return nil;
}
}
- (NSFileHandle *)createFileHandleWithName:(NSString *)aFileName isAppend:(BOOL)isAppend {
NSFileHandle *fileHandle = nil;
NSString *fileName = [self getFilePath:aFileName];
int fd = -1;
if (fileName) {
if ([[NSFileManager defaultManager] fileExistsAtPath:fileName]&& !isAppend) {
[[NSFileManager defaultManager] removeItemAtPath:fileName error:nil];
}
int flags = O_WRONLY | O_APPEND | O_CREAT;
fd = open([fileName fileSystemRepresentation], flags, 0644);
}
if (fd != -1) {
fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
}
return fileHandle;
}
- (void)voiceRecogButtonHelper
{
// [self configFileHandler];
[self.asrEventManager setDelegate:self];
[self.asrEventManager setParameter:nil forKey:BDS_ASR_AUDIO_FILE_PATH];
[self.asrEventManager setParameter:nil forKey:BDS_ASR_AUDIO_INPUT_STREAM];
[self.asrEventManager sendCommand:BDS_ASR_CMD_START];
[self onInitializing];
}
- (void)printLogTextView:(NSString *)logString
{
NSLog(@"logString = %@",logString);
}
- (NSString *)getDescriptionForDic:(NSDictionary *)dic {
if (dic) {
return [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:dic
options:NSJSONWritingPrettyPrinted
error:nil] encoding:NSUTF8StringEncoding];
}
return nil;
}
- (NSDictionary *)parseLogToDic:(NSString *)logString
{
NSArray *tmp = NULL;
NSMutableDictionary *logDic = [[NSMutableDictionary alloc] initWithCapacity:3];
NSArray *items = [logString componentsSeparatedByString:@"&"];
for (NSString *item in items) {
tmp = [item componentsSeparatedByString:@"="];
if (tmp.count == 2) {
[logDic setObject:tmp.lastObject forKey:tmp.firstObject];
}
}
return logDic;
}
- (void)onInitializing
{
self.voiceRecogButton.enabled = NO;
[self.voiceRecogButton setTitle:@"Initializing..." forState:UIControlStateNormal];
}
- (void)onStartWorking
{
// self.finishButton.enabled = YES;
// self.cancelButton.enabled = YES;
[self.voiceRecogButton setTitle:@"Speaking..." forState:UIControlStateNormal];
}
- (void)onEnd
{
// self.longSpeechFlag = NO;
// self.finishButton.enabled = NO;
// self.cancelButton.enabled = NO;
self.voiceRecogButton.enabled = YES;
[self.voiceRecogButton setTitle:@"语音识别" forState:UIControlStateNormal];
}
#pragma mark - UIKeyboard Notification
-(void)KeyboardWillHide:(NSNotification*)notification
{
self.bottomLayoutConstraint.constant = 0;
}
-(void)KeyboardWillShow:(NSNotification*)notification
{
CGRect rect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
self.bottomLayoutConstraint.constant = rect.size.height;
[self.view layoutIfNeeded];
// [inputview resignFirstResponder];
}
#pragma mark - UITextFieldDelegate
- (void)askWord:(NSString *)word {
__weak typeof(self) weakSelf = self;
[SVProgressHUD setDefaultMaskType:SVProgressHUDMaskTypeGradient];
[SVProgressHUD show];
[[AIPUnitSDK sharedInstance] askWord:word completion:^(NSError *error, NSDictionary* resultDict) {
[SVProgressHUD dismiss];
NSLog(@"%@",resultDict[@"action_list"]);
for (NSDictionary* dict in resultDict[@"action_list"]) {
dispatch_async(dispatch_get_main_queue(), ^{
int i = 0;
NSMutableArray* action = [[NSMutableArray alloc] init];
for (; i < [dict[@"hint_list"] count] && i<3; i++) {
NSDictionary* item = dict[@"hint_list"][i];
[action addObject:item[@"hint_query"]];
}
// NSLog(@"%d",page);
if (page == 0) {
[weakSelf.mainArray addObject:@{@"chat":dict[@"say"],@"type":@(0),@"action":action,@"isShowImg":@(0)}];
[AIVoiceTable reloadData];
[AIVoiceTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.mainArray.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
inputview.text = @"";
}else{
actionArray = action;
// [weakSelf.mainArray addObject:@{@"chat":gpName,@"type":@(0),@"action":action}];
[self getyuqingZS];
}
// NSLog(@"%lu",(unsigned long)_mainArray.count);
// [weakSelf.mainTableView reloadData];
});
if ([dict[@"action_id"] isEqualToString:@"start_work_satisfy"]) {
NSLog(@"开始扫地");
} else if ([dict[@"action_id"] isEqualToString:@"stop_work_satisfy"]) {
NSLog(@"停止工作");
} else if ([dict[@"action_id"] isEqualToString:@"move_action_satisfy"]) {
NSLog(@"移动");
} else if ([dict[@"action_id"] isEqualToString:@"timed_charge_satisfy"]) {
NSLog(@"定时充电");
} else if ([dict[@"action_id"] isEqualToString:@"timed_task_satisfy"]) {
NSLog(@"定时扫地");
} else if ([dict[@"action_id"] isEqualToString:@"sing_song_satisfy"]) {
NSLog(@"唱歌");
}
}
}];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
return YES;
}
// 语音调用方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
if (textField.text.length > 0) {
[speekView removeFromSuperview];
[_mainArray addObject:@{@"chat":textField.text,@"type":@(1),@"isShowImg":@(0)}];
[AIVoiceTable reloadData];
[self askWord:textField.text];
// [self getyuqingZS];
gpName = textField.text;
// [yqDataArray addObject:textField.text];
page ++;
[inputview resignFirstResponder];
}
return YES;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textFiel{
return YES;
}
上边的代码是集成了百度语音SDK的代理方法 以及UNIT交互的一些方法
以上就是集成百度语音SDK以及UNIT交互的具体过程 关于UNIT交互页面局部使用XIB写的 这块儿就不在记录 直接按照演示demo完成就可以