参考: Building a Speech-to-Text App Using Speech Framework in iOS 10
在WWDC 2016时,Apple介绍了Speech framework,这是一个很有用的声音识别框架。实际上这是利用Siri进行声音识别。
初始化项目
- 新建SpeechToTextDemo,模板是Single View Application。
-
添加简单的UI
- 分别定义
UITextView
和UIButton
的两个outlet,为textView
和microphoneButton
。 - 再为
UIButton
添加一个action:
@IBAction func microphoneTapped(_ sender: AnyObject) {
}
使用Speech Framework
import Speech
- 实现
SFSpeechRecognizerDelegate
协议
用户授权
获取声音数据是要获得用户的授权的。
- 在
ViewController
类中定义一个变量,作为语音识别器。参数identifier
是识别的语种,可参考这个列表,中文是“ zh_Hans_CN”。
private let speechRecognizer = SFSpeechRecognizer(locale: Locale.init(identifier: "zh_Hans_CN"))
- 在
viewDidLoad()
中:
override func viewDidLoad() {
super.viewDidLoad()
// 1
microphoneButton.isEnabled = false
speechRecognizer?.delegate = self
// 2
SFSpeechRecognizer.requestAuthorization{
(authStatus) in
var isButtionEnabled = false
switch authStatus {
case .authorized:
isButtionEnabled = true
case .denied:
isButtionEnabled = false
print("用户拒绝接受语音识别")
case .notDetermined:
isButtionEnabled = false
print("语音识别功能没有经过认可")
case .restricted:
isButtionEnabled = false
print("当前设备不能语音识别")
}
self.microphoneButton.isEnabled = isButtionEnabled
}
startRecording()
}
- 1 默认按钮设成不可用
- 2 授权结果回调
- Apple需要每个app如要用户授权时,都应该定制一个反馈信息(info.plist)。
在info.plist中添加两个key,分别是麦克风和语音识别的授权,Privacy - Microphone Usage Description
和Privacy - Speech Recognition Usage Description
。
处理语音识别
- 在
ViewController
类中添加三个变量
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? //识别请求
private var recognitionTask: SFSpeechRecognitionTask? // 提供识别请求的结果
private let audioEngine = AVAudioEngine() //
-
SFSpeechAudioBufferRecognitionRequest
对象处理语音识别的请求,代表语音进入语音识别器。 -
SFSpeechRecognitionTask
识别任务,用于操作识别器的停止和开始 -
AVAudioEngine
语音引擎,提供语音输出
- 创建新函数
startRecording()
,这个函数在点击button后调用,也就是microphoneTapped(:)
中最后调用
func startRecording() {
// 1
if recognitionTask != nil {
recognitionTask?.cancel()
recognitionTask = nil
}
// 2
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSessionCategoryRecord)
try audioSession.setMode(AVAudioSessionModeMeasurement)
try audioSession.setActive(true, with: .notifyOthersOnDeactivation)
} catch {
print("audioSession的属性设置失败")
}
// 3
recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
// 4
guard let inputNode = audioEngine.inputNode else {
fatalError("Audio engine has no input node")
}
// 5
guard let recognitionRequest = recognitionRequest else {
fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
}
// 6
recognitionRequest.shouldReportPartialResults = true
// 7
recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: {
(result, error) in
var isFinal = false
if result != nil {
self.textView.text = result?.bestTranscription.formattedString
isFinal = (result?.isFinal)!
}
if error != nil || isFinal {
self.audioEngine.stop()
inputNode.removeTap(onBus: 0)
self.recognitionRequest = nil
self.recognitionTask = nil
self.microphoneButton.isEnabled = true
}
})
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
self.recognitionRequest?.append(buffer)
}
audioEngine.prepare()
do {
try audioEngine.start()
} catch {
print("audioEngine couldn't start beacause of an error.")
}
textView.text = "Say something, I'm listening!"
}
- 1 开始录音时的初始化
- 2
AVAudioSession
提供语音录音,设置一些参数 - 3 初始化
SFSpeechAudioBufferRecognitionRequest
- 4 核查
audioEngine
是否可用 - 5 核查
recognitionRequest
- 7 检测的音频后的回调方法,也就是开始录音后,有音频进入后都调用
语音识别的开关
- 实现代理方法
speechRecognizer(_:availabilityDidChange:)
。这个方法在语音识别器可用性发生变化时被调用。
func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
if available {
microphoneButton.isEnabled = true
} else {
microphoneButton.isEnabled = false
}
}
- 点击button时的操作:
@IBAction func microphoneTapped(_ sender: AnyObject) {
if audioEngine.isRunning {
audioEngine.stop()
recognitionRequest?.endAudio()
microphoneButton.isEnabled = false
microphoneButton.setTitle("Start Recording", for: .normal)
} else {
startRecording()
microphoneButton.setTitle("Stop Recording", for: .normal)
}
}
总结
语音识别在iPhone的自带键盘中有这个功能,中文识别率很高,如果不高兴或不方便打字,很方便使用。