iOS10语音识别框架Speech详解
一 、前言
语音识别技术已经成为人工智能应用的一个重点,通过语音控制设备简单方便,在各个领域兴起了研究应用的热潮。
目前语音识别在智能家居、智能车载、智能客服机器人方面有广泛的应用,未来将会深入到学习、生活、工作的各个环节。国内外许多大公司都在倾力研究此技术,并不断推出实际产品。
说起语音识别功能,不得不提的就是最为经典的苹果iPhone 4S,以及由这部里程碑式的作品开启的siri语音助手。也正是由此,语音识别的智能技术在市场上开始被越来越多的用户了解、接受,赢得了很多用户的喜爱。
在移动产品的应用上也越来越广,各种第三方语音识别SDK也是层出不穷,例如科大讯飞、百度语音等。很多国产手机搭载的语音智能识别助手,都使用了科大讯飞的技术支持。2017年,小米首次也搭上了AI交互、语音识别的车,推出了"小爱同学"。
本篇博客将主要探讨iOS10中新引入的SpeechFramework框架。有了这个框架,iOS开发者可以十分容易的为自己的App添加语音识别功能,不需要再依赖于其他第三方的语音识别服务,并且,Apple的Siri应用的强大也证明了Apple的语音服务是足够强大的,不通过第三方,也大大增强了用户的安全性。
SpeechFramework的文档地址: https://developer.apple.com/documentation/speech
demo地址:https://github.com/Xcoder1011/SpeechTest
二 、Speech
简介
Perform speech recognition on live or prerecorded audio, and receive transcriptions, alternative interpretations, and confidence levels of the results.
对现场或预先录制的音频执行语音识别,并接收结果的转录,可替代的解释和置信度。
使用语音框架识别录制或现场音频中的语音。键盘的听写支持使用语音识别将音频内容翻译成文本; 这个框架提供了类似的行为,当然,您可以使用语音识别来处理识别口头命令或处理应用程序其他部分的文本口述。
您可以使用多种语言执行语音识别,但每个对象都使用一种语言。某些语言可以使用设备语音识别,但该框架还依赖于Apple的语音识别服务器。始终假设执行语音识别需要网络连接。SFSpeechRecognizer
要启动语音识别过程,请执行以下操作:
-
请求授权使用语音识别。
-
创建一个识别器。
SFSpeechRecognizer
-
使用语音识别器对象的属性验证服务的可用性。
-
准备您的音频内容。
-
创建一个识别请求对象。
SFSpeechRecognitionRequest
- 创建的识别请求对象的类型取决于您是处理现有音频文件还是传入音频流。
- 对于音频文件:
SFSpeechURLRecognitionRequest
- 对于音频流:
SFSpeechAudioBufferRecognitionRequest
- 调用recognitionTask(with:delegate:)方法或者recognitionTask(with:resultHandler:)方法 开始识别。
初识一些类的概念
SFSpeechRecognizer:这个类是语音识别的操作类,用于语音识别用户权限的申请,语言环境的设置,语音模式的设置以及向Apple服务发送语音识别的请求。
SFSpeechRecognitionTask:这个类是语音识别服务请求任务类,每一个语音识别请求都可以抽象为一个SFSpeechRecognitionTask实例,其中SFSpeechRecognitionTaskDelegate协议中约定了许多请求任务过程中的监听方法。
SFSpeechRecognitionRequest:语音识别请求类,需要通过其子类来进行实例化。
SFSpeechURLRecognitionRequest:通过音频URL来创建语音识别请求。
SFSpeechAudioBufferRecognitionRequest:通过音频流来创建语音识别请求。
SFSpeechRecognitionResult:语音识别请求结果类。
SFTranscription:语音转换后的信息类,已识别语音的文本表示。
SFTranscriptionSegment:整个假设转录的一部分,语音转换中的音频节点类。
必需步骤
1.请求语音识别权限
- 请求用户允许使用Apple的服务器执行语音识别。
语音识别过程涉及捕获用户语音的音频并将该数据发送到Apple的服务器进行处理。您捕获的音频构成敏感的用户数据,您必须尽一切努力保护它。在将数据通过网络发送到Apple的服务器之前,您还必须获得用户的许可。您使用Speech框架的API请求授权。
- 将隐私密钥添加到Info.plist文件中
In Xcode, add the “Privacy - Speech Recognition Usage Description” key to your app’s Info.plist file.
description: "The application uses speech recognition to help you chat easily."
- 首次申请授权
在使用Speech框架的API之前,必须调用该对象。该方法异步执行并将结果传递给您提供的块。使用该块确定用户是授予还是拒绝您的请求。
注意: 如果您不打算立即使用该功能,请勿请求访问语音识别。相反,请延迟请求,直到用户与使用此类功能的应用部分进行交互。
func requestAuthorization() {
SFSpeechRecognizer.requestAuthorization { (status) in
OperationQueue.main.addOperation {
var isSpeakBtnEnabled = false
switch status {
case .authorized :
isSpeakBtnEnabled = true
case .notDetermined :
isSpeakBtnEnabled = false
self.speakBtn.setTitle("语音识别还没有经授权", for: .disabled)
case .denied :
isSpeakBtnEnabled = false
self.speakBtn.setTitle("用户拒绝访问语音识别", for: .disabled)
case .restricted :
isSpeakBtnEnabled = false
self.speakBtn.setTitle("语音识别不支持此设备", for: .disabled)
}
self.speakBtn.isEnabled = isSpeakBtnEnabled
}
}
}
2. 创建语音识别器:SFSpeechRecognizer
用于检查语音识别服务的可用性以及启动语音识别过程的对象。
是一种用于管理语音识别过程中的中心对象。使用此对象:SFSpeechRecognizer
SFSpeechRecognizer:这个类是语音识别的操作类,用于语音识别用户权限的申请,语言环境的设置,语音模式的设置以及向Apple服务发送语音识别的请求。
1) 创建支持语音识别的语言环境的识别器。
let recognizer = SFSpeechRecognizer.init(locale: Locale.init(identifier: "zh-CN"))
Local:
语音识别器的语言环境。
SFSpeechRecognizer.supportedLocales()
可支持的语言列表:
for value in SFSpeechRecognizer.supportedLocales() {
print(value.description)
}
/////
th-TH (fixed)
ca-ES (fixed)
fr-BE (fixed)
de-CH (fixed)
sk-SK (fixed)
en-ZA (fixed)
es-CL (fixed)
hi-IN (fixed)
zh-CN (fixed)
zh-TW (fixed)
da-DK (fixed)
hi-IN-translit (fixed)
el-GR (fixed)
he-IL (fixed)
pt-BR (fixed)
en-AE (fixed)
pt-PT (fixed)
fr-CH (fixed)
ro-RO (fixed)
vi-VN (fixed)
en-SA (fixed)
pl-PL (fixed)
es-US (fixed)
hi-Latn (fixed)
en-SG (fixed)
tr-TR (fixed)
hr-HR (fixed)
ko-KR (fixed)
uk-UA (fixed)
it-CH (fixed)
ar-SA (fixed)
id-ID (fixed)
en-IN (fixed)
es-ES (fixed)
de-AT (fixed)
en-IE (fixed)
cs-CZ (fixed)
es-CO (fixed)
zh-HK (fixed)
sv-SE (fixed)
en-PH (fixed)
en-ID (fixed)
en-CA (fixed)
nl-NL (fixed)
yue-CN (fixed)
en-NZ (fixed)
en-GB (fixed)
ja-JP (fixed)
it-IT (fixed)
ru-RU (fixed)
en-US (fixed)
ms-MY (fixed)
es-MX (fixed)
hu-HU (fixed)
fr-CA (fixed)
wuu-CN (fixed)
de-DE (fixed)
fr-FR (fixed)
fi-FI (fixed)
nb-NO (fixed)
nl-BE (fixed)
en-AU (fixed)
2)监控语音识别服务的可用性:SFSpeechRecognizerDelegate
设置识别器的代理,isAvailable: 指示语音识别器当前是否可用。
//MARK: SFSpeechRecognizerDelegate
// 监控语音识别的可用性
func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
print("availabilityDidChange = \(available)")
if available { //available: 指示语音识别器当前是否可用。
self.speakBtn.isEnabled = true
} else {
self.speakBtn.isEnabled = false
}
}
3)api解释:
// 查看可支持的语言环境
open class func supportedLocales() -> Set<Locale>
// 返回您应用的当前授权以执行语音识别状态
open class func authorizationStatus() -> SFSpeechRecognizerAuthorizationStatus
// 请求语音识别权限
open class func requestAuthorization(_ handler: @escaping (SFSpeechRecognizerAuthorizationStatus) -> Swift.Void)
// 如果不支持语言环境,则返回nil
public convenience init?()
// 表示所请求的语音识别的类型
// 如果SFSpeechRecognitionRequest对象中也进行了设置 则会覆盖这里的值
open var defaultTaskHint: SFSpeechRecognitionTaskHint
// 通过请求识别语音话语
// 执行语音识别请求并将结果传递到指定的处理程序块。
open func recognitionTask(with request: SFSpeechRecognitionRequest, resultHandler: @escaping (SFSpeechRecognitionResult?, Error?) -> Swift.Void) -> SFSpeechRecognitionTask
// 高级API:识别与指定请求关联的音频源的语音,使用指定的委托来管理结果
open func recognitionTask(with request: SFSpeechRecognitionRequest, delegate: SFSpeechRecognitionTaskDelegate) -> SFSpeechRecognitionTask
// 要在其上执行识别任务处理程序和委托方法的队列
// 默认为主队列
open var queue: OperationQueue
3. 创建语音识别请求:SFSpeechRecognitionRequest
SFSpeechAudioBufferRecognitionRequest:
使用该对象在实时音频或一组现有音频缓冲区上执行语音识别。例如,使用此请求对象将音频从设备的麦克风路由到语音识别器。SFSpeechAudioBufferRecognitionRequest
请求对象最初不包含音频。在捕获音频时,调用append(_:)
或将音频样本添加到请求对象,语音识别器会持续分析您附加的音频,仅在您调用方法时停止。
@available(iOS 10.0, *)
open class SFSpeechRecognitionRequest : NSObject {
// 表示正在执行的语音识别类型的值。
open var taskHint: SFSpeechRecognitionTaskHint
// 如果为true,将报告每个话语的部分(非最终)结果
// 指示是否要为每个话语返回中间结果。
open var shouldReportPartialResults: Bool
// 应该识别的一组短语,即使它们不在系统词汇表中
open var contextualStrings: [String]
// 识别请求: 可用于由开发人员识别接收者的字符串
// 用于描述与语音识别请求关联的交互类型的标识符字符串。
open var interactionIdentifier: String?
}
// 请求识别录制的音频文件中的语音。
@available(iOS 10.0, *)
open class SFSpeechURLRecognitionRequest : SFSpeechRecognitionRequest {
// 请求从给定URL的音频文件中转录语音。
public init(url URL: URL)
open var url: URL { get }
}
// 从捕获的音频内容识别语音的请求,例如来自设备麦克风的音频。
@available(iOS 10.0, *)
open class SFSpeechAudioBufferRecognitionRequest : SFSpeechRecognitionRequest {
// 获取最佳语音识别的首选音频格式。
open var nativeAudioFormat: AVAudioFormat { get }
// 将PCM格式的音频添加到识别请求的末尾。
open func append(_ audioPCMBuffer: AVAudioPCMBuffer)
// 将音频附加到识别请求的末尾。
open func appendAudioSampleBuffer(_ sampleBuffer: CMSampleBuffer)
// 标记识别请求的音频输入结束。
open func endAudio()
}
4. 语音识别任务:SFSpeechRecognitionTask
用于监视语音识别进度的任务对象。
使用对象确定语音识别任务的状态,取消正在进行的任务或发出任务结束的信号。
open class SFSpeechRecognitionTask : NSObject {
// 语音识别任务的当前状态
open var state: SFSpeechRecognitionTaskState { get }
// 指示任务停止接受新音频(例如停止录音),但对已经缓冲的音频进行完整处理。
// 这对基于URL的识别请求没有影响,这会立即有效地缓冲整个文件。
open func finish()
// 取消当前的语音识别任务。
open func cancel()
// 指定语音识别任务期间发生的错误。
open var error: Error? { get }
}
- SFSpeechRecognitionTaskDelegate:
该协议的方法为您提供了对语音识别过程的细粒度控制。具体来说,如果您想了解以下内容,请使用此协议:
当第一个语音发音在音频中时。
当语音识别器停止接受音频时。
语音识别过程结束或取消时。
当语音识别器产生潜在的转录时。
public protocol SFSpeechRecognitionTaskDelegate : NSObjectProtocol {
// 当任务首次检测到源音频中的语音时
optional public func speechRecognitionDidDetectSpeech(_ task: SFSpeechRecognitionTask)
// 告诉代表可以使用假设的转录。
optional public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didHypothesizeTranscription transcription: SFTranscription)
// 仅为最终识别话语而调用。将不再报道关于话语的事件
optional public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishRecognition recognitionResult: SFSpeechRecognitionResult)
// 当任务不再接受新的音频输入时,即使最终处理正在进行,也告诉代理
optional public func speechRecognitionTaskFinishedReadingAudio(_ task: SFSpeechRecognitionTask)
// 告诉代理该任务已被取消。
optional public func speechRecognitionTaskWasCancelled(_ task: SFSpeechRecognitionTask)
// 完成对所有请求的话语的识别。
optional public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishSuccessfully successfully: Bool)
}
5. 语音识别结果:SFSpeechRecognitionResult
语音识别结果对象包含transcriptions
当前话语中的一个或多个。每个转录都有一个置信度,表明它是正确的可能性。(您也可以直接获得最高评级的转录。)bestTranscription
bestTranscription
:具有最高置信水平的转录
transcriptions
:一系列潜在的转录,按置信度的降序排序。
isFinal
:指示语音识别是否完整以及转录是否为最终。
- SFTranscription
公认演讲的文字表示。
formattedString
:整个话语,格式化为单个用户可显示的字符串。
segments
:一系列转录片段,代表假设转录的部分
- SFTranscriptionSegment
整个假设转录的一部分.
open class SFTranscriptionSegment : NSObject, NSCopying, NSSecureCoding {
// 该转录片段中话语的字符串表示。
open var substring: String { get }
// 该转录片段子串的范围信息
open var substringRange: NSRange { get }
// 处理的音频流中段的开始时间
open var timestamp: TimeInterval { get }
// 用户说出段所代表的单词所花费的秒数,从话语的开头开始计算
open var duration: TimeInterval { get }
// 对该转录片段的识别准确性的置信水平 (0~1.0)
open var confidence: Float { get }
// 该转录片段中话语的一系列替代解释
open var alternativeSubstrings: [String] { get }
}
三、Tips
- Category:
- 只有简单音乐播放功能: AVAudioSessionCategoryPlayback
- 只是播放音乐,而不需要独占锁屏界面时,
try audioSession.setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
- 常规录音: AVAudioSessionCategoryRecord
- 录音和播放同时进行时 : AVAudioSessionCategoryPlayAndRecord
-
AVAudioEngine:
• 管理所有的音频节点(audio nodes)
• 连接所有的音频节点使其运作形成链条(active chains)
• 动态的获取(attach)和配置所有音频的节点。
• 开启和停止API
- 有多种node,负责实现不同的功能,而AVAudioEngine在运行中可以自由组合、拆卸node,node经由它们各自的输入被连接到下一级的输出,从而可以灵活实现想要的效果
- AVAudioEngine实例化后默认有三个node,分别为inputNode、outputNode,这两个node不可以被detach,还有一个可选的mainMixerNode(混音)。
- inputNode、outputNode分别对应硬件的麦克风和扬声器,需要检查其采样率和声道数,若采样率为0,则不可用。
-
图灵机器人:
官网: http://www.turingapi.com/
TuringApi: https://www.kancloud.cn/turing/www-tuling123-com/718218
四 、总结
- 处理由语音识别限制引起的故障:语音识别是基于网络的服务,单个设备可能在每天可以执行的识别数量方面受到限制,并且每个应用程序可能会根据其每天发出的请求数量进行全局限制。
- 一分钟的音频持续时间限制:语音识别对电池寿命和网络使用造成相对较高的负担。为了最大限度地减轻这种负担,该框架会停止持续时间超过一分钟的语音识别任务 此限制类似于与键盘相关的听写限制。
- 不要对私人或敏感信息进行语音识别:不要发送密码,健康或财务数据以及其他敏感语音进行识别。