IOS语音识别功能

Categories: IOS

语音识别现在有很多在做的,百度、迅飞等。我本来想用百度的语音识别,后来发现它的SDK不提供swift,用它的OC版本的SDK老是编译有问题。后来想反正现在苹果自带就有这个API,就是要求最低需要IOS10版本,现在10以下的应该也不多了,就打算用苹果自带的API开发一个。

权限

这个是前提,声明权限:


Privacy - Microphone Usage Description 

Privacy - Speech Recognition Usage Description 

代码中可以检查语音识别的权限:


SFSpeechRecognizer.requestAuthorization { (status) in 

//... 

} 

SFSpeechAudioBufferRecognitionRequest

  1. 首先定义需要用到的变量:

// 这个bus是类似tag或者端口号的效果,下面Task需要用到 

let recognizeBus = 1024 

var recognizer: SFSpeechRecognizer! 

var recAudioEngine: AVAudioEngine! 

var recAudioInputNode: AVAudioInputNode! 

// 

var recRequest: SFSpeechAudioBufferRecognitionRequest? 

var recTask: SFSpeechRecognitionTask? 

并且在开始的时候初始化,语音识别引擎。


recognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh_CN")) 

recAudioEngine = AVAudioEngine() 

recAudioInputNode = recAudioEngine.inputNode 

  1. 创建请求:

recRequest = SFSpeechAudioBufferRecognitionRequest() 

// 说话的时候每个片段都返回 还是最后结束的时候返回 

recRequest!.shouldReportPartialResults = true 

  1. 建立任务,然后开始执行任务:

这个是Task的block模式,在block中处理识别的返回结果。


recTask = recognizer.recognitionTask(with: recRequest!, resultHandler: { (result, error) in 

if result != nil { 

if let best = result?.bestTranscription.formattedString { 

self.showLabel.text = "最佳结果:\(best)" 

} 

} 

if error != nil { 

DDLogError("识别错误。。。。。\(error!.localizedDescription)") 

} 

}) 

// 监听一个标识位并拼接流文件 

let format = self.recAudioInputNode.outputFormat(forBus: self.recognizeBus) 

self.recAudioInputNode.installTap(onBus: self.recognizeBus, bufferSize: 1024, format: format) { (pcmBuffer, time) in 

self.recRequest?.append(pcmBuffer) 

} 

// 准备并启动引擎 

self.recAudioEngine.prepare() 

do { 

try self.recAudioEngine.start() 

}catch { 

DDLogError("录音 识别 异常") 

} 

self.showLabel.text = "等待命令中....." 

也可以用代理模式:


recTask = recognizer.recognitionTask(with: recRequest!, delegate: self) 

  1. 最后结束任务,回收资源:

self.recAudioEngine.stop() 

self.recAudioInputNode.removeTap(onBus: self.recognizeBus) 

self.recRequest?.endAudio() 

self.recRequest = nil 

self.recTask = nil 

PS: 开发的时候遇到个问题,一直没有识别到我的声音,也没有输出,最后总是说没有识别到结果,Timeout。

后来加了这个就行了:


// 录音session 

let audioSession = AVAudioSession.sharedInstance() 

do { 

try audioSession.setCategory(AVAudioSessionCategoryRecord) 

try audioSession.setMode(AVAudioSessionModeMeasurement) 

// 这句话很重要,一定要,不然识别不到你的声音 

try audioSession.setActive(true, with: .notifyOthersOnDeactivation) 

} catch { 

DDLogError("audioSession set failed.") 

} 

这个代码加在创建识别请求和任务开始之前就行了。