【iOS开发】---- 语音识别

        最近iOS项目中需要用到语音识别技术(也被称为自动语音识别,英语:Automatic Speech Recognition, ASR)。去google搜索了一下,发现语音识别做的不错的有谷歌,微软和科大讯飞。但是微软的语音识别只能在window平台,科大讯飞的语音识别现在主要是中文和英文,而谷歌的语音识别是可以支持多国语言的,考虑到项目以后可能会有多种语言,所以我选择用谷歌的语音识别。
        这里有一篇文章,比较详细的对比了三种语音识别:Google,微软,科大讯飞的语音识别引擎对比。
        语音识别的流程包括两个步骤:1.语音录入; 2.语音识别.


语音录入

        

        语音录入的方法我使用了两种:

1.参照官方文档例子SpeakHere(使用了OC,C++混编,后来发现有些OC方法,在iOS 7中已经不建议使用了

2.使用AVAudioRecorder来录音(建议使用第二种方法)

        注意:从查得的资料来看,使用谷歌语音搜索的音频编码暂时可用的有flac,speex,wav三种。网上说flac在iOS上获得比较复杂,speex暂不清楚,wav是可以得到的。获取wav编码格式的设置方式如下:

#pragma mark - 
#pragma mark 录音设置

- (NSString *) audioRecordingPath
{
    return [NSTemporaryDirectory() stringByAppendingFormat:@"voice.wav"];
}

- (NSDictionary *) audioRecordingSettings{
    NSDictionary *result = nil;
    /* Let's prepare the audio recorder options in the dictionary.
     Later we will use this dictionary to instantiate an audio
     recorder of type AVAudioRecorder */
    NSMutableDictionary *settings = [[NSMutableDictionary alloc] init];
    
    [settings setValue:[NSNumber numberWithInteger:kAudioFormatLinearPCM]
                forKey:AVFormatIDKey];
    
    [settings setValue:[NSNumber numberWithFloat:16000]
                forKey:AVSampleRateKey];
    
    [settings setValue:[NSNumber numberWithInteger:1]
                forKey:AVNumberOfChannelsKey];
    
    [settings setValue:[NSNumber numberWithInteger:AVAudioQualityLow]
                forKey:AVEncoderAudioQualityKey];
    
    result = [NSDictionary dictionaryWithDictionary:settings];
    return result;
}


        录音完成之后,将音频文件保存,然后进行语音识别。

语音识别

  • 基本流程:

一、从音频输入设备获取原始数据。
二、对原始数据进行包装、编码。
三、将编码后的音频POST至接口地址。
四、分析处理接口返回的JSON并得出结果。
  • 请求接口

xjerr

错误标准

client

客户端类型

lang

待识别语言类型,en-US是英文,中文为zh-CN其余语言代码参考:http://msdn.microsoft.com/en-us/library/ms533052(v=vs.85).aspx

maxresults

最大返回识别结果数量,多个结果在hypotheses列表中保存

请求方式:HTTP POST
头部信息:Content-Type: audio/x-flac; rate=16000   (注:Content-Type根据所使用的编码格式不同而不同,详见文章底部。rate为音频采样率。)
请求数据:编码后的音频数据

  • 音频编码格式

FLAC或WAV或SPEEX


        iOS语音识别请求实现代码:

- (void)beginRecognition
{
    NSURL *url = [NSURL URLWithString:@"http://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=en"];
    ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];
    [request setRequestMethod:@"POST"];

    NSString *filePath_voice = [self audioRecordingPath];
    [request appendPostDataFromFile:filePath_voice];
    [request addRequestHeader:@"Content-Type" value:@"audio/L16; rate=16000"];
    [request setDidFailSelector:@selector(recognitionFailed:)];
    [request setDidFinishSelector:@selector(recognitionFinished:)];
    request.delegate=self;
    [request startAsynchronous];
}

        返回结果:

{
    "status":0,//返回状态
    "id":"",
    "hypotheses"://结果列表
    [
     {
         "utterance":"hello", //语音所转换的文字
         "confidence":0.8394497 //识别信心度
     }
     ]
}

        因为项目中语音是用来做搜索用,基本输入几个词汇就行,不需要大篇幅如短信一般。所以,我希望能在我说完话后,自动停止录音。这样,我们需要自动识别什么时候录入完毕了。


自动识别语音录入完毕

        

        基本流程:

  • 录音开始,添加一个定时器,不停地检测话筒是否有接收到声音;
  • 一旦检测到有声音,说明开始有说话(期间定时器仍然在检测);
  • 再次检测到没有声音,说明录入完毕,然后停止定时器刷新,停止录音。

        定时器检测实现方法以及相关注释:

-(void)refresh:(id)sender
{
    //发送updateMeters消息来刷新平均和峰值功率
    [audioRecorder updateMeters];
    
    //此计数是以对数刻度计量的,-160表示完全安静,0表示最大输入值。
    //为方便,我们将其转换为0-1,0代表完全安静,1代表最大音量。
    float peakPowerForChannel = pow(10, 0.05*[audioRecorder peakPowerForChannel:0]);
    float averagePowerForChannel = pow(10, 0.05*[audioRecorder averagePowerForChannel:0]);
    
    NSLog(@"Average input: %f Peak input: %f", peakPowerForChannel,averagePowerForChannel);
    
    lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
    averagePassResults = ALPHA * averagePowerForChannel + (1.0 - ALPHA) * averagePassResults;
    
    indicateHigh.alpha = averagePassResults;
    
    if (lowPassResults > 0.55f)
    {//此时mic接收到震动
        blowDetected = YES;
    }
    else
    {
        if (blowDetected)
        {
            blowDetected = NO;
            [self stopRecord];
            NSLog(@"录音完成");
        }
    }
}

        噪声/声音是由低频声音组成的。我们将使用low pass filter(低频滤波) 来降低来自麦克的高频声音;当滤波信号的电平等级突然增大时,我们就知道有人向麦克说话了。

        blowDetected是一个bool值,因为一开始录音和完成录音都是电频等级较低的时候,所以需要一个开关来区分,否则录音没刚始就结束了。

        indicateHigh是个view,时刻改变透明度以告诉用户有人在说话,你也可以用其他方式来指示。

        lowPassResults通过低频滤波算法得到,有兴趣的可以研究一下。其中ALPHA这里值为0.05.


        好了,到这里语音识别需要的东西基本就完成了。

        其实这篇文章只能算是一个汇总吧,把我需要的东西都记在这里,非常感谢网络上那些乐于分享的同学。


参考:

Iphone开发之音频101:

点击打开链接

检测用户向麦克吹气:

点击打开链接

自动识别语音录入完毕:

点击打开链接

"Unknown type name 'class'; did you mean 'Class'?"(OC与C++混编发生的问题):
点击打开链接

CADebugPrintf.h file not found:
点击打开链接

Google,微软,科大讯飞的语音识别引擎对比:
点击打开链接

uni-app本身没有提供原生的语音识别插件,但你可以通过uni-app的原生插件扩展功能来实现语音识别。具体的步骤如下: 1. 首先,确定你想要使用的语音识别插件。在uni-app中,你可以选择使用第三方语音识别插件,例如科大讯飞、百度语音等。你需要根据插件的文档进行相应的配置和集成。 2. 在uni-app项目中创建一个原生插件的目录。你可以在项目根目录下的`uni_modules`目录中创建一个新的目录,例如`uni-plugin-voice`。 3. 在插件目录中创建一个`manifest.json`文件,用于配置插件信息。在`manifest.json`中,你需要指定插件的名称、版本号、依赖等信息。具体的配置可以参考uni-app插件开发文档。 4. 在插件目录中创建一个原生代码的目录,例如`ios`和`android`。 5. 在原生代码目录中,根据平台分别实现对应的语音识别功能。你可以使用iOS和Android各自的语音识别API,或者调用第三方语音识别SDK来实现功能。具体的实现方式会因为使用的语音识别插件而有所不同,你需要参考对应插件的文档进行具体操作。 6. 编译和集成原生插件。根据插件的要求,进行相应的编译和集成操作。对于iOS平台,你需要将插件目录添加到Xcode项目中,并配置相应的依赖关系。对于Android平台,你需要将插件目录添加到Android Studio项目中,并配置相应的依赖关系。 7. 在uni-app的页面中使用语音识别功能。你可以在表单输入框的组件中添加一个触发语音识别的按钮或图标,并在对应的事件处理函数中调用原生插件提供的接口进行语音识别。 请注意,以上步骤是一个大致的流程,具体的实现方式和步骤可能会因为你选择的语音识别插件而有所不同。在实际操作中,你需要根据所用插件的文档和示例代码进行相应的调整和修改。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值