优雅地识别用户的声音,无需操心授权和音频引擎。
除了自述文件之外,了解更多关于 SwiftSpeech 以及如何在像微信这样的应用中实现语音识别功能的最佳方式是查看我的新项目 SwiftSpeech Examples。目前,它包含一个微信语音消息界面模型和 SwiftSpeech 中的三个演示。
SwiftSpeech 是 Apple Speech 框架的包装器,深度集成了 SwiftUI 和 Combine。
在 Xcode 中,从 File
菜单中选择 Add Packages...
,然后输入以下软件包 URL
https://github.com/Cay-Zhang/SwiftSpeech
pod 'SwiftSpeech'
虽然 SwiftSpeech 负责处理所有繁琐的授权工作,但您仍然必须声明使用描述,并指定您希望在何处进行授权过程,然后才能开始使用它。
如果还没有,请在您的 Info.plist
中添加这两行:NSSpeechRecognitionUsageDescription
和 NSMicrophoneUsageDescription
。
这些是您的用户首次使用时将看到的提示消息,用于请求他们允许使用语音识别和访问麦克风。
这是一个例子
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app uses speech recognition to convert your speech into text.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app uses the mircrophone to record audio for speech recognition.</string>
将 SwiftSpeech.requestSpeechRecognitionAuthorization()
放置在您希望进行请求的位置。一个常见的位置是在 onAppear
修饰符内部。非常常见,以至于在 Xcode 修饰符库中有一个名为“Request Speech Recognition Authorization on Appear”的代码片段。
.onAppear {
SwiftSpeech.requestSpeechRecognitionAuthorization()
}
现在您可以使用 Xcode 预览开始尝试与框架捆绑的一些轻量级演示。单击“Preview on Device”按钮以在您的设备上尝试演示。
static var previews: some View {
// Two of the demo views below can take a `localeIdentifier: String` as an argument.
// Example locale identifiers:
// 简体中文(中国)= "zh_Hans_CN"
// English (US) = "en_US"
// 日本語(日本)= "ja_JP"
Group {
SwiftSpeech.Demos.Basic(localeIdentifier: yourLocaleString)
SwiftSpeech.Demos.Colors()
SwiftSpeech.Demos.List(localeIdentifier: yourLocaleString)
}
}
以下是您的 previews
的“预览”
了解了这个框架可以做什么之后,您现在可以开始学习 SwiftSpeech 中的概念了。
检查 SwiftSpeech.Demos.Basic
的源代码。这里唯一的新内容是这个
SwiftSpeech.RecordButton() // 1. The View Component
.swiftSpeechRecordOnHold(sessionConfiguration:animation:distanceToCancel:) // 2. The Functional Component
.onRecognizeLatest(update: $text) // 3. SwiftSpeech Modifier(s)
这里有三个部分(幸运的是,您可以自定义每一个部分!)
View
。.swiftSpeechToggleRecordingOnTap(sessionConfiguration:animation:)
。现在,您可以只使用内置的视图组件和功能组件。让我们首先探索一些 SwiftSpeech 修饰符,因为每个应用程序处理其数据的方式都不同。
重要提示:将多个或相同的 SwiftSpeech 修饰符链接在一起不会覆盖任何行为。修饰符的所有操作将按照最接近功能组件的修饰符首先执行,而最远的修饰符最后执行的顺序执行。
// 1
// All three demos use these modifiers.
// Inspect the source code of them if you want examples!
.onRecognizeLatest(
includePartialResults: Bool = true,
handleResult: (SwiftSpeech.Session, SFSpeechRecognitionResult) -> Void,
handleError: (SwiftSpeech.Session, Error) -> Void
)
.onRecognize(
includePartialResults: Bool = true,
handleResult: (SwiftSpeech.Session, SFSpeechRecognitionResult) -> Void,
handleError: (SwiftSpeech.Session, Error) -> Void
)
// This one simply assigns the recognized text to the binding in `handleResult` and ignores errors.
.onRecognizeLatest(
includePartialResults: Bool = true,
update: Binding<String>
)
// This one prints the recognized text and ignores errors.
.printRecognizedText(includePartialResults: Bool = true)
第一组修饰符封装了 SwiftSpeech 的核心价值。它为您完成所有发布者转换和订阅,并使用足够的信息调用闭包,以方便在产生识别结果时执行复杂的任务。
onRecognizeLatest
会忽略从上一个录音会话(如果有)的识别结果,而当新的会话开始时,onRecognize
会订阅每个录音会话的结果。
在 handleResult
中,第一个闭包参数是一个 SwiftSpeech.Session
,它为每个录音都有一个唯一的 id
。使用它来区分来自一个录音的识别结果和来自另一个录音的识别结果。
第二个是一个 SFSpeechRecognitionResult
,其中包含有关识别的丰富信息。不仅有识别的文本 (result.bestTranscription.formattedString
),还有一些有趣的东西,比如语速和音高!
在 handleError
中,您将处理识别过程中以及录音会话初始化期间(例如麦克风激活失败)产生的错误。
// 2
.onStartRecording(appendAction: (SwiftSpeech.Session) -> Void)
.onStopRecording(appendAction: (SwiftSpeech.Session) -> Void)
.onCancelRecording(appendAction: (SwiftSpeech.Session) -> Void)
第二组让您可以完全控制 SwiftSpeech.Session
的整个生命周期。它在录音开始/停止/取消后运行提供的闭包。在闭包内部,您可以访问相应的 SwiftSpeech.Session
,这将在 下面 讨论。
// 3
// `SwiftSpeech.ViewModifiers.OnRecognize` uses these modifiers.
// Inspect the source code of it if you want examples!
.onStartRecording(sendSessionTo: Subject)
.onStopRecording(sendSessionTo: Subject)
.onCancelRecording(sendSessionTo: Subject)
如果您喜欢响应式编程风格,那么第三组可能会很有用。这里唯一的新参数是一个 Combine.Subject
(例如 CurrentValueSubject
和 PassthroughSubject
),并且修饰符将在录音开始/停止/取消后将相应的 SwiftSpeech.Session
发送到 Subject
。
可以使用 SwiftSpeech.Session.Configuration
结构体来配置会话。配置包含诸如语言环境、任务提示、要识别的自定义短语、设备上识别的选项和音频会话配置之类的信息。检查 SwiftSpeech.Session.Configuration
以获取更多详细信息。
如果内置的 onRecognize(Latest)
修饰符不能满足您的需求,您可以通过 onStart/Stop/CancelRecording
订阅识别结果。
一个 Session
通过其 resultPublisher
发布其识别结果。它具有 SFSpeechRecognitionResult
的 Output
类型和 Error
的 Failure
类型。
当 Session
完成处理用户的声音(即 result.isFinal == true
)、发生错误或您已显式调用会话上的 cancelRecording()
时,您将收到完成事件。
一个 Session
还有一个方便的发布者,名为 stringPublisher
,它将结果映射到识别的字符串。
这是一个使用 Session
识别用户的声音并接收更新的示例。
let session = SwiftSpeech.Session(configuration: SwiftSpeech.Session.Configuration(locale: Locale(identifier: "en-US"), contextualStrings: ["SwiftSpeech"]))
try session.startRecording()
session.stringPublisher?
.sink { text in
// do something with the text
}
.store(in: &cancelBag)
有关更多信息,请参阅 SwiftSpeech.Session
的文档。
视图组件 是一个专用于设计的 View
。它不直接响应用户交互,而是响应其环境,允许开发人员只专注于视图设计,并使视图更具可组合性。用户交互由 功能组件 处理。
检查 SwiftSpeech.RecordButton
的源代码(同样,它不是一个 Button
,因为它不响应用户交互)。您会注意到它不拥有任何状态或应用任何手势。它只响应下面的两个变量。
@Environment(\.swiftSpeechState) var state: SwiftSpeech.State
@SpeechRecognitionAuthStatus var authStatus
两者都非常不言自明:第一个表示其当前的录音状态,第二个指示语音识别的授权状态。
以下是关于 SwiftSpeech.State
的更多详细信息
enum SwiftSpeech.State {
/// Indicating there is no recording in progress.
/// - Note: It's the default value for `@Environment(\.swiftSpeechState)`.
case pending
/// Indicating there is a recording in progress and the user does not intend to cancel it.
case recording
/// Indicating there is a recording in progress and the user intends to cancel it.
case cancelling
}
这里的 authStatus
是一个 SFSpeechRecognizerAuthorizationStatus
。您也可以使用 $authStatus
作为 authStatus == .authorized
的简写。
结合一个 功能组件 和一些 SwiftSpeech 修饰符,希望您现在可以构建自己的花哨录音系统!
该库提供了两个通用功能组件,它们将手势添加到它修改的视图,并为您执行语音识别
// They already support SwiftSpeech Modifiers.
func swiftSpeechRecordOnHold(
sessionConfiguration: SwiftSpeech.Session.Configuration = SwiftSpeech.Session.Configuration(),
animation: Animation = SwiftSpeech.defaultAnimation,
distanceToCancel: CGFloat = 50.0
) -> some View
func swiftSpeechToggleRecordingOnTap(
sessionConfiguration: SwiftSpeech.Session.Configuration = SwiftSpeech.Session.Configuration(),
animation: Animation = SwiftSpeech.defaultAnimation
)
如果您决定实现一个涉及除按住或点击之外的自定义手势的视图,您还可以通过添加委托并在适当的时间调用其方法来支持 SwiftSpeech 修饰符
var delegate = SwiftSpeech.FunctionalComponentDelegate()
有关如何为语音识别实现自定义视图的指南,请参阅 ViewModifiers.swift
和 SwiftSpeechExamples。真的没有那么难。
SwiftSpeech 在 MIT 许可证下可用。