SwiftSpeech

语音识别,化繁为简

A few lines of code to do this!

优雅地识别用户的声音,无需操心授权和音频引擎。

SwiftSpeech 示例

除了自述文件之外,了解更多关于 SwiftSpeech 以及如何在像微信这样的应用中实现语音识别功能的最佳方式是查看我的新项目 SwiftSpeech Examples。目前,它包含一个微信语音消息界面模型和 SwiftSpeech 中的三个演示。

WeChat

特性

SwiftSpeech 是 Apple Speech 框架的包装器,深度集成了 SwiftUICombine

安装

Swift Package Manager (推荐)

在 Xcode 中,从 File 菜单中选择 Add Packages...,然后输入以下软件包 URL

https://github.com/Cay-Zhang/SwiftSpeech

CocoaPods

pod 'SwiftSpeech'

入门指南

1. 授权

虽然 SwiftSpeech 负责处理所有繁琐的授权工作,但您仍然必须声明使用描述,并指定您希望在何处进行授权过程,然后才能开始使用它。

Info.plist 中的使用描述

如果还没有,请在您的 Info.plist 中添加这两行:NSSpeechRecognitionUsageDescriptionNSMicrophoneUsageDescription

这些是您的用户首次使用时将看到的提示消息,用于请求他们允许使用语音识别和访问麦克风。

这是一个例子

<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()
}

2. 尝试一些演示

现在您可以使用 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 的“预览”

Demos

3. 自己构建

了解了这个框架可以做什么之后,您现在可以开始学习 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)

这里有三个部分(幸运的是,您可以自定义每一个部分!)

  1. 视图组件:一个仅负责 UI 的 View
  2. 功能组件:一个处理用户交互并提供语音识别基本功能的组件。在内置组件中,前两个参数允许您指定录音会话的配置(语言环境等)以及用户与视图组件交互时使用的动画。第三个参数设置用户向上滑动以取消录音的距离。该框架还提供了另一个功能组件.swiftSpeechToggleRecordingOnTap(sessionConfiguration:animation:)
  3. SwiftSpeech 修饰符:一个或多个组件,允许您接收和操作识别结果。它们可以堆叠在一起以创建强大的效果。

现在,您可以只使用内置的视图组件和功能组件。让我们首先探索一些 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(例如 CurrentValueSubjectPassthroughSubject),并且修饰符将在录音开始/停止/取消后将相应的 SwiftSpeech.Session 发送到 Subject

SwiftSpeech.Session

配置

可以使用 SwiftSpeech.Session.Configuration 结构体来配置会话。配置包含诸如语言环境、任务提示、要识别的自定义短语、设备上识别的选项和音频会话配置之类的信息。检查 SwiftSpeech.Session.Configuration 以获取更多详细信息。

自定义订阅识别结果

如果内置的 onRecognize(Latest) 修饰符不能满足您的需求,您可以通过 onStart/Stop/CancelRecording 订阅识别结果。

一个 Session 通过其 resultPublisher 发布其识别结果。它具有 SFSpeechRecognitionResultOutput 类型和 ErrorFailure 类型。

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 修饰符,希望您现在可以构建自己的花哨录音系统!

支持 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 许可证下可用。