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
- 首先定义需要用到的变量:
// 这个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
- 创建请求:
recRequest = SFSpeechAudioBufferRecognitionRequest()
// 说话的时候每个片段都返回 还是最后结束的时候返回
recRequest!.shouldReportPartialResults = true
- 建立任务,然后开始执行任务:
这个是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)
- 最后结束任务,回收资源:
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.")
}
这个代码加在创建识别请求和任务开始之前就行了。