- 在 2016 年的 WWDC 上,Apple 终于开放了语音识别 Speech Recognition API,那就是 Speech 框架。事实上,Siri 的语音识别正是由 Speech Kit 提供支持。超过50种语言获得支持、任何运行iOS10的设备都可用、加入用户授权使其更安全、可以转化音频文件和实时语音 。
- 现在阿里、腾讯、科大讯飞都有相关的语音识别框架、超过时长都会收费的、集成相关框架、调用相关api还是非常简单的,这里主要讲的是iOS自带语音识别框架Speech的使用。
iOS语音识别步骤
- 录音和语音识别都是用户的隐私权限,所以需要用户授权打开麦克风(实时语音)和音频识别权限,所以要在info.plist文件中添加相关key:(Privacy - Microphone Usage Description、Privacy - Speech Recognition Usage Description)
<key>NSMicrophoneUsageDescription</key>
<string>App需要您的同意,才能访问麦克风</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>App需要您的同意,才能使用语音识别技术</string>

override func viewDidLoad() {
super.viewDidLoad()
//获取用户权限
SFSpeechRecognizer.requestAuthorization { (authStatus : SFSpeechRecognizerAuthorizationStatus) in
DispatchQueue.main.async(execute: {
switch authStatus {
case .notDetermined:
self.titleL.text = "语音识别未授权"
break
case .denied:
self.titleL.text = "用户未授权使用语音识别"
break
case .restricted:
self.titleL.text = "语音识别在这台设备上受到限制"
break
case .authorized:
self.titleL.text = "可以开始录音了"
self.btnClickEnabled = true
break
}
})
}
}
本地音频文件识别
- 比如像微信支付宝一些搜索框中就是先录音,然后再识别音频文件转为文字进行搜索,这个相对用的比较多。关于录音上篇文章已经写过了,这里不再赘述。这里主要讲录音后的音频文件如何识别。
- 本地语音文件识别还是很简单的,获取音频文件路径url,通过这个url录音创建识别请求对象,音频识别对象通过该请求去执行识别任务后即可获得识别后的文字。
- 具体相关代码:
//本地语音文件识别(录音后,识别录音文件)
@IBAction func leftBtnClick(_ sender: UIButton) {
let local = NSLocale(localeIdentifier: "zh_CN")
//获取本地录音文件路劲
let url = Bundle.main.url(forResource: "recordAudio.wav", withExtension: nil)
if url == nil {
return
}
let localRecognizer = SFSpeechRecognizer(locale: local as Locale)!
let rqs = SFSpeechURLRecognitionRequest(url: url!)
// recordUrl = [NSURL URLWithString:[NSTemporaryDirectory() stringByAppendingString:@"selfRecord.pcm"]]
localRecognizer.recognitionTask(with: rqs) { (result, error) in
if (error != nil) {
print("语音识别解析失败,%@",error!);
}else{
self.titleL.text = result!.bestTranscription.formattedString
}
}
}
实时语音识别
- 实时语音识别就像Siri一样可以变说话边转文字,类似于语言同步翻译,虽然一遍的开发中用到的很少,但还是有必要了解一下。实时语音需要开启麦克风,所以需要不能用模拟器测试。
- 实时语音识别需要用到音频引擎这个关键类
AVAudioEngine
,用于生成和处理音频信号并执行音频输入和输出,功能十分强大。 - 具体相关代码:
//初始化一些成员变量
class ViewController: UIViewController {
var btnClickEnabled = false//按钮是否可以点击
var speechRecognizer : SFSpeechRecognizer?//音频识别器
var recognitionRequest : SFSpeechAudioBufferRecognitionRequest?//对象用于处理语音识别请求,为语音识别提供音频输入
var recognitionTask : SFSpeechRecognitionTask? //可以将识别请求的结果返回给你,它带来了极大的便利,必要时,可以取消或停止任务。
lazy var audioEngine = AVAudioEngine()// 音频引擎 用于进行音频输入
}
//初始化语音识别对象
override func viewDidLoad() {
super.viewDidLoad()
//用于apple语言识别的变量
speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh-CN"))
speechRecognizer?.delegate = (self as SFSpeechRecognizerDelegate);
}
//开始录音
func startRecording(){
//如果识别任务还在进行中就取消
if recognitionTask != nil {
recognitionTask?.cancel()
// recognitionTask = nil
}
//创建音频会话对象
let audioSession = AVAudioSession.sharedInstance()
do {
//设置音频类别
try audioSession.setCategory(AVAudioSessionCategoryRecord)
//设置音频模式
try audioSession.setMode(AVAudioSessionModeMeasurement)
//激活音频会话
try audioSession.setActive(true, with: .notifyOthersOnDeactivation)
}catch{
fatalError("会话创建失败")
}
//创建音频识别请求对象
recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
guard let inputNode : AVAudioInputNode = audioEngine.inputNode else {
fatalError("音频引擎 没有输入节点")
}
guard let recognitionRequest = recognitionRequest else {
fatalError("创建音频缓存失败")
}
//结果报告
recognitionRequest.shouldReportPartialResults = true
//开启授权任务
recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
var isFinal = false
guard result == nil else {
self.titleL.text = result?.bestTranscription.formattedString
//判断语言是否处理完成
isFinal = (result?.isFinal)!
return
}
guard error == nil && isFinal == false else{
// 停止声音处理器引擎
self.audioEngine.stop()
inputNode.removeTap(onBus: 0)
//停止语音识别请求进程
self.recognitionRequest?.endAudio()
self.recognitionRequest = nil
self.recognitionTask?.cancel()
self.recognitionTask = nil
//按钮可以点击
self.btnClickEnabled = true
return
}
})
// 初始化语音处理器的输入模式
let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
// 为语音识别请求对象添加一个AudioPCMBuffer,来获取声音数据
self.recognitionRequest?.append(buffer)
}
// 语音处理器准备就绪(会为一些audioEngine启动时所必须的资源开辟内存)
audioEngine.prepare()
do {
//启动识别
try audioEngine.start()
} catch {
print("audioEngine couldn't start because of an error.")
}
}
//停止录音
func endRecording(){
audioEngine.stop()
recognitionRequest?.endAudio()
}
//语音实时识别
extension UIViewController : SFSpeechRecognizerDelegate{
//当语音识别器的可用性发生更改时通知代理。如果语音识别可用,录音按钮也将被启用。
public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
if available {
btnClickEnabled = true
} else {
btnClickEnabled = false
}
}
}
//按钮点击事件控制
@IBAction func rightBtnClick(_ sender: UIButton) {
if btnClickEnabled {
if audioEngine.isRunning {//结束语言识别
endRecording()
sender.setTitle("开始语言识别", for: .normal)
} else {
self.titleL.text = ""
startRecording()
sender.setTitle("结束语言识别", for: .normal)
}
}
}
- Apple忠告:
- 确保使用语音之别之前,通过UI界面告知用户
- 在涉及密码或者敏感信息时,请勿使用
- 在你操作识别结果之前,请先把结果展示给用户
- Apple 对每台设备的识别有限制。详情未知,不过你可以尝试联系 Apple 获得更多信息
- Apple 对每个应用的识别也有限制
- 如果你总是遭遇限制,务必联系 Apple,他们或许可以解决这个问题
- 语音识别会消耗不少电量和流量
- 语音识别每次只能持续大概一分钟