语音转文本的三种方案
手机语音功能越来越实用,也越来越多人实用,虽然小菜鸟本人不喜欢使用语音功能,但是语音功能越来越受到追捧,也预研究了一下语音转文本的功能,这次主要尝试了使用科大讯飞语音识别、百度语音识别、系统原生的的语音识别。
1.科大讯飞的语音识别
1.1 使用科大讯飞的SDK必须先要到科大的官网上注册应用,并开通语音听写功能服务,获取APPID,并下载SDK。
获取APPID.png
1.2 下载完SDK后,解压缩后里面有文档(Doc),Framework(lib),版本信息(release.txt),Demo(sample)。这方面科大还是做的比较好的,很多东西都一目了然的,初次使用的话可以研究一下Demo。
SDK文件内容.png
1.3 导入Framework,把文件夹下的lib中的iflyMSC.framework导入工程中,并添加iflyMSC.framework所依赖的其他库,主要的依赖库有以下这些,其中官网中的CoreTelephoney.framework应该修改成CoreTelephony.framework
库名称 | 是否必要 | 功能 |
---|---|---|
libz.tbd | 必要 | 用于压缩、加密算法。 |
AVFoundation.framework | 必要 | 用于系统录音和播放 。 |
SystemConfiguration.framework | 系统库 | 用于系统设置。 |
Foundation.framework | 必要 | 基本库。 |
CoreTelephony.framework | 必要 | 用于电话相关操作。 |
AudioToolbox.framework | 必要 | 用于系统录音和播放。 |
UIKit.framework | 必要 | 用于界面显示。 |
CoreLocation.framework | 必要 | 用于定位。 |
Contacts.framework | 必要 | 用于联系人。 |
AddressBook.framework | 必要 | 用于联系人。 |
QuartzCore.framework | 必要 | 用于界面显示。 |
CoreGraphics.framework | 必要 | 用于界面显示。 |
libc++.tbd | 必要 | 用于支持C++。 |
Libicucore.tbd | Aiui必要 | 系统正则库。 |
1.4 关闭bitcode,如果没有关闭bitcode则会出现You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE)错误.
bitcoe错误.pngbitcode 设置方式为 Targets -> Build Settings,搜索bitcode,设置为NO。
bitcode设置.png
1.5 在info.plist添加权限说明
<key>NSMicrophoneUsageDescription</key>
<string></string>
<key>NSLocationUsageDescription</key>
<string></string>
<key>NSLocationAlwaysUsageDescription</key>
<string></string>
<key>NSContactsUsageDescription</key>
<string></string>
1.6 使用科大讯飞要先注册服务,
NSString *initString = [[NSString alloc] initWithFormat:@"appid=%@",APPID];
[IFlySpeechUtility createUtility:initString];
1.7 语音识别实现
//创建语音识别对象
_iFlySpeechRecognizer = [IFlySpeechRecognizer sharedInstance];
_iFlySpeechRecognizer.delegate = self;
//设置为听写模式
[_iFlySpeechRecognizer setParameter: @"iat" forKey: [IFlySpeechConstant IFLY_DOMAIN]];
//asr_audio_path 是录音文件名,设置value为nil或者为空取消保存,默认保存目录在Library/cache下。
[_iFlySpeechRecognizer setParameter:nil forKey:[IFlySpeechConstant ASR_AUDIO_PATH]];
//设置语音输入等待时长
[_iFlySpeechRecognizer setParameter:@"10000" forKey: [IFlySpeechConstant VAD_BOS]];
[_iFlySpeechRecognizer setParameter:@"10000" forKey: [IFlySpeechConstant VAD_EOS]];
1.8 启动语音识别
//启动识别服务
_iFlySpeechRecognizer.delegate = self;
[_iFlySpeechRecognizer startListening];
1.9 语音识别结果回调
- (void)onResults:(NSArray *)results isLast:(BOOL)isLast{
NSLog(@"%@",results);
}
1.10 语音识别完成回调,该回调在语音识别完成或中断了会调用,如果errorCode.errorCode为0,则是录音完成。
- (void)onCompleted:(IFlySpeechError *)errorCode {
}
科大讯飞整个的使用流程基本就这样了,科大的SDK用起来还是比较舒服的,SDK的注释跟文档也是很清晰的,开发使用起来还是很简单的。
2.百度的语音识别
2.1 同样的使用百度语音识别要到百度开发者中心创建应用,勾选语音识别项,获取到AppID,API Key,Secret Key。
BD应用管理.png
2.2 创建完应用后下载SDK,下载完后可以看到文件夹中有头文件(BDSClientHeaders),.a文件(BDSClientLib),Demo资源(BDSClientResource),Demo工程(BDSClientSample),
BDDemo.png这里的Demo是不能直接使用的,你得先对工程的AppID,API Key,Secret Key进行赋值
BDAppID配置.png
2.3 导入.a库,把文件夹下的BDSClientLib中的libBaiduSpeechSDK.a导入工程中,再把BDSClientHeaders的头文件也导入工程中,并添加libBaiduSpeechSDK.a所依赖的其他库,主要的依赖库有以下这些
库名称 | 功能 |
---|---|
libc++.tbd | 提供对C/C++特性支持 |
libz.1.2.5.tbd | 提供gzip支持 |
AudioToolbox | 提供录音和播放支持 |
AVFoundation | 提供录音和播放支持 |
CFNetwork | 提供对网络访问的支持 |
CoreLocation | 提供对获取设备地理位置的支持,以提高识别准确度 |
CoreTelephony | 提供对移动网络类型判断的支持 |
SystemConfiguration | 提供对网络状态检测的支持 |
GLKit | 内置识别控件所需 |
2.4 关闭bitcode,这里的设置跟1.4是一样的。
2.5 在info.plist添加权限说明
<key>NSMicrophoneUsageDescription</key>
<string></string>
<key>NSLocationUsageDescription</key>
<string></string>
<key>NSLocationAlwaysUsageDescription</key>
<string></string>
<key>NSContactsUsageDescription</key>
<string></string>
2.6 百度语音识别同样要注册服务,
//初始化录音对象
self.asrEventManager = [BDSEventManager createEventManagerWithName:BDS_ASR_NAME];
//配置key
[self.asrEventManager setParameter:@[API_KEY, SECRET_KEY] forKey:BDS_ASR_API_SECRET_KEYS];
[self.asrEventManager setParameter:APP_ID forKey:BDS_ASR_OFFLINE_APP_CODE];
//这里BDS_ASR_ENABLE_LOCAL_VAD不设置为NO,则会报错
[self.asrEventManager setParameter:@(NO) forKey:BDS_ASR_ENABLE_LOCAL_VAD];
2.7 启动语音识别
- (void)beginListen:(void (^)(NSString *, BOOL, NSError *))block {
self.block = block;
//这里不得不吐槽一下,这代理都没说要遵守哪些协议的。。。。
[self.asrEventManager setDelegate:self];
[self.asrEventManager sendCommand:BDS_ASR_CMD_START];
}
百度的SDK这里有个吐槽点,要遵守协议,但是居然没有说明是哪个协议,去Demo看了才知道是哪哪个协议.....
BD头文件.png
2.8 语音识别结果回调,同样的这里的回调结果状态居然用的是int类型,其实是有定义了枚举的,百度这样的大厂写这样的代码有点。。。。。。
- (void)VoiceRecognitionClientWorkStatus:(int)workStatus obj:(id)aObj {
//百度这个做的真不怎么样,都定义了枚举,结果还用int,这写都还的去看demo才知道。。。。。
switch (workStatus) {
case EVoiceRecognitionClientWorkStatusFinish: {
NSString *text = [self fetchTextWithObj:aObj];
if (self.block) {
self.block(text, YES, nil);
}
break;
}
case EVoiceRecognitionClientWorkStatusCancel: {
if (self.block) {
self.block(@"", YES, nil);
}
}
break;
case EVoiceRecognitionClientWorkStatusError: {
NSError *error = nil;
if ([aObj isKindOfClass:[NSError class]]) {
error = (NSError *)aObj;
} else {
error = [NSError errorWithDomain:@"未知错误" code:1000 userInfo:nil];
}
if (self.block) {
self.block(@"", YES, error);
}
}
break;
}
}
整体来说,百度的语音识别使用期来是不难的,但是百度这个SDK的注释跟代码有点不敢恭维,特别是遵守什么协议也没说明白,状态类型定义了枚举,协议中居然用的int类型,具体的使用还得去看Demo才能找到。。。。。
3.原生的语音识别
3.1 原生的语音识别功能是iOS10之后的才有的功能
3.2 在info.plist中添加一下权限
<key>NSMicrophoneUsageDescription</key>
<string></string>
<key>NSSpeechRecognitionUsageDescription</key>
<string></string>
3.3 引入语音识别头文件
#import <Speech/Speech.h>
3.4 创建语音识别对象
@property (nonatomic, strong) SFSpeechRecognizer *recognizer; ///< 语音识别
@property (nonatomic, strong) AVAudioEngine * audioEngine; ///< 语音输入
@property (nonatomic, strong) SFSpeechAudioBufferRecognitionRequest * recognitionRequest; ///< 语音识别请求
@property (nonatomic, strong) SFSpeechRecognitionTask * recognitionTask ; ///< 语音识别任务
3.4 判断是否有语音是被权限
if (@available(iOS 10.0, *)) {
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
switch (status) {
case SFSpeechRecognizerAuthorizationStatusAuthorized:{
//可以使用
self.canListen = YES;
}
break;
case SFSpeechRecognizerAuthorizationStatusNotDetermined:{
self.errorDomain = @"用户还没选择是否允许录音";
self.canListen = NO;
}
break;
case SFSpeechRecognizerAuthorizationStatusRestricted: {
self.errorDomain = @"该设备不支持录音";
self.canListen = NO;
}
break;
case SFSpeechRecognizerAuthorizationStatusDenied: {
self.errorDomain = @"用户拒绝了录音";
self.canListen = NO;
}
break;
}
}];
}
3.5 初始化语音输入对象,系统的有语言识别限制,你必须先设置你识别的语言环境。
//语音识别为中文@"zh_CN"
self.recognizer = [[SFSpeechRecognizer alloc] initWithLocale:[NSLocale localeWithLocaleIdentifier:@"zh_CN"]];
self.recognizer.delegate = self;
self.audioEngine = [[AVAudioEngine alloc] init];
[self.audioEngine.inputNode installTapOnBus:0 bufferSize:1024 format: [self.audioEngine.inputNode outputFormatForBus:0] block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
[self.recognitionRequest appendAudioPCMBuffer:buffer];
}];
3.6 启动语音识别&语音识别回调
- (void)beginListen:(void (^)(NSString *, BOOL, NSError *))block {
if (@available(iOS 10.0, *)) {
if (!self.canListen) {
if (block) {
block(@"", YES, [NSError errorWithDomain:self.errorDomain code:1000 userInfo:nil]);
}
return;
}
self.block = block;
self.recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc]init];
__weak typeof(self) weakSelf = self;
if (@available(iOS 10.0, *)) {
self.recognitionTask = [self.recognizer recognitionTaskWithRequest:self.recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {//这里为语音识别回调
typeof(weakSelf) self = weakSelf; if (!self) return;
if (self.block) {
self.text = result.bestTranscription.formattedString;
self.block(self.text, NO, error);
}
}];
} else {
// Fallback on earlier versions
}
[self.audioEngine prepare];
NSError *error = nil;
[self.audioEngine startAndReturnError:&error];
}
}
相对来说,使用系统原生的,步骤相对复杂,需要自己控制语音输入,判断系统权限等;
4.三种语音转文本的对比
语音识别方案 | 支持系统 | 离线 | 使用复杂度 |
---|---|---|---|
科大讯飞 | 8.0以上 | 收费支持 | 低 |
百度 | 8.0以上 | 收费支持 | 中 |
原生 | 10.0以上 | 支持 | 高 |
5 Demo
本来有Demo,但是在上传github的时候操作出错,把Demo的文件都给删。。。。。。
欲哭无泪.png
网友评论