• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

iOS应用程序的辅助功能:语音识别

开发人员一直在努力使他们的应用程序更先进,但它们真的可供所有人使用吗?对于大多数应用程序来说,答案是否定的。为了覆盖最大的受众,让我们了解如何让我们的应用程序更易于访问。 

在联合国 国际残疾人日之后,让我们来看看如何让我们的 ios 应用程序更易于访问。

在本教程中,我们将使用 AV音频引擎来转录语音并将其作为文本显示给用户(就像siri在您的iphone上所做的那样)。

本教程假设您精通 swift,并且熟悉使用xcode进行 iOS 开发。 

项目设置

接下来,您可以在 Xcode 中创建一个新项目或下载此应用程序的示例项目。 

如果您在新项目中工作,请将以下行添加 到ViewController.swift 文件的顶部, 以便导入 Speech api

import Speech

开始之前必须采取的另一个步骤是使 ViewController()类符合 SFSpeechRecognizerDelegate. 

完成后,您就可以开始本教程了。 

1. 请求许可

由于 Apple 非常重视隐私,因此他们要求开发人员在使用设备麦克风之前征得用户许可是有道理的,特别是因为数据被发送到 Apple 的服务器进行分析。

在语音识别的情况下,需要许可,因为数据会传输并临时存储在 Apple 的服务器上以提高识别的准确性。— Apple 文档

在您的 Xcode 项目中,您需要打开Info.plist 文件并添加两个键值对。以下是您可以粘贴的键:

  • NSMicrophoneUsageDescription

  • NSSpeechRecognitionUsageDescription

对于这些值,您可以输入准确描述所需权限以及为什么需要它们的任何字符串。这是添加后的样子:

iOS应用程序的辅助功能:语音识别  第1张iOS应用程序的辅助功能:语音识别  第2张iOS应用程序的辅助功能:语音识别  第3张

现在,我们需要真正请求用户的许可,然后才能继续。为此,我们可以简单地调用一个方法,方便地称为 requestAuthorization().

但在我们这样做之前,在您的 viewDidLoad() 方法中,添加以下代码行:

microphoneButton.isEnabled = false

默认情况下,这将使按钮被禁用,这样用户就不可能在应用程序有机会与用户核对之前按下按钮。 

接下来,您需要添加以下方法调用:

SFSpeechRecognizer.requestAuthorization { (status) in
    OperationQueue.main.addOperation {
        // Your code goes here
    }
}

在此方法的完成处理程序中,我们接收授权状态,然后将其设置为名为 的常量 status。之后,我们有一个异步调用,它将块内的代码添加到主线程(因为必须在主线程中更改按钮的状态)。

在addOperation块内部,您需要添加以下 switch语句来检查授权状态的实际情况:

switch status {

  case .authorized: dictationButton.isEnabled = true
    promptLabel.text = "Tap the button to begin dictation..."

  default: dictationButton.isEnabled = false
    promptLabel.text = "Dictation not authorized..."
    
}

我们正在打开 authorizationStatus() 函数的返回值。如果该操作被授权 ( status is .authorized),则启用听写按钮并 显示点击按钮开始听写...。否则,听写按钮被禁用,并  显示听写未授权...。

2. 设计用户界面

接下来,我们需要设计一个用户界面,以便能够做两件事:开始或停止听写并显示解释的文本。为此,请前往Main.storyboard文件。

以下是继续本教程所需的三个界面构建器元素:

  • UILabel

  • UITextView

  • UIButton

由于在这个应用程序中放置不是关键,我不会详细介绍放置所有东西的位置和方式,所以在放置用户界面元素时只需遵循这个基本的线框:

iOS应用程序的辅助功能:语音识别  第4张

作为参考,这是我的故事板此时的样子:

iOS应用程序的辅助功能:语音识别  第5张同样,如果您的布局看起来不同也没关系,但只需确保您在线框中具有相同的三个基本元素。现在,将以下代码行粘贴到类的顶部 ViewController():

@IBOutlet var promptLabel: UILabel!
@IBOutlet var transcribedTextView: UITextView!
@IBOutlet var dictationButton: UIButton!

在类的底部 ViewController(),只需添加以下功能即可在点击听写按钮时触发:

@IBAction func dictationButtonTapped() {
    // 你的代码在这里
    }

剩下要做的最后一件事是打开助手编辑器 并将界面构建器连接连接到您的Main.storyboard 文件。出现在它们旁边的点现在应该显示为已填充,您现在可以分别以变量和方法的形式访问所有这些元素。

3. 添加变量

现在,我们终于准备好开始语音识别了。第一步是创建适当的变量和常量,我们将在整个过程中使用它们。在您的界面构建器出口下方,添加以下代码行:

let audioEngine = AVAudioEngine()
let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))!

var request: SFSpeechAudioBufferRecognitionRequest?
var task: SFSpeechRecognitionTask?

下面是对变量和常量作用的描述:

  • audioEngine是 AVAudioEngine()类的一个实例。这个类,简单来说就是一系列的音频节点。音频节点用于对音频执行各种操作,例如生成和处理音频。

  • speechRecognizer是 SFSpeechRecognizer()类的一个实例。除了指定的语言(在本例中为美国英语)之外,此类不识别任何内容。

  • request是 类型 的可选变量, SFSpeechAudioBufferRecognitionRequest当前正在初始化为 nil。在本教程的后面部分,我们将实际创建其中一个,并在需要使用它时设置它的值。这将用于识别来自设备麦克风的输入数据。

  • task是另一个可选变量,这次是 SFSpeechRecognition. 稍后,我们将使用此变量来监控语音识别的进度。

添加变量后,您就拥有了深入语音识别过程所需的一切。

4. 声明听写方法

现在,我们将为我们的语音识别算法制作主要方法。在方法下方 viewDidLoad(),声明以下函数:

func startDictation() {
    // 你的代码在这里
    }

由于我们不知道 的当前状态 task,我们需要取消当前任务,然后,我们需要将其设置回nil(以防它还没有)。这可以通过在您的方法中添加以下两行代码来完成:

task?.cancel()
task = nil

伟大的!现在我们知道没有任务已经在运行。当您使用在方法范围之外声明的变量时,这是一个重要的步骤。需要注意的一件事是,我们使用可选链接来 调用cancel(). task这是一种简洁的书写方式,我们只想调用cancel() iftask不是 nil。

5. 初始化变量

现在,我们必须初始化我们在本教程前面创建的变量。要继续,请将这些代码行添加到 startDictation()上一步中的方法中:

request = SFSpeechAudioBufferRecognitionRequest()

let audioSession = AVAudioSession.sharedInstance()

let inputnode = audioEngine.inputNode

guard let request = request else { return }
request.shouldReportPartialResults = true

try? audioSession.setCategory(AVAudioSessionCategoryRecord)
try? audioSession.setMode(AVAudioSessionModeMeasurement)
try? audioSession.setActive(true, with: .notifyOthersOnDeactivation)

让我们分解一下。还记得 request我们之前创建的变量吗?第一行代码用类的实例初始化该变量 SFSpeechAudioBufferRecognitionRequest。 

接下来,我们将共享音频会话实例分配给一个名为 的常量 audioSession。音频会话的行为类似于应用程序和设备本身(以及音频组件)之间的中间人。

之后,我们将输入节点设置为一个名为 inputNode. 要开始录制,我们稍后将 tap在此节点上创建一个。

接下来,我们使用一个守卫来解开 request我们之前初始化的变量。这只是为了避免以后在应用程序中需要解包。然后我们将启用不完整结果的显示。这与 iPhone 上的听写类似——如果您曾经使用过听写,您就会知道系统会输入它所想的任何内容,然后使用上下文线索,在必要时进行调整。 

最后,最后三行代码尝试设置音频会话的各种属性。这些操作可能会抛出错误,因此必须使用 try?关键字对其进行标记。为了节省时间,我们将忽略发生的任何错误。 

现在我们已经初始化了大部分之前处于 nil 状态的变量。最后一个要初始化的变量是 task变量。我们将在下一步中这样做。

6. 初始化任务变量

此变量的初始化将需要完成处理程序。将以下代码粘贴到startDictation() 方法的底部:

task = speechRecognizer.recognitionTask(with: request, resultHandler: { (result, error) in
    
    guard let result = result else { return }
    self.transcribedTextView.text = result.bestTranscription.formattedString
    
    if error != nil || result.isFinal {
        self.audioEngine.stop()
        self.request = nil
        self.task = nil
        
        inputNode.removeTap(onBus: 0)
    }
})

首先,我们 recognitionTask以 request 为参数创建一个。第二个参数是定义结果处理程序的闭包。参数是的result一个实例 SFSpeechRecognitionResult。在这个完成处理程序中,我们需要再次解开结果变量。 

接下来,我们将文本视图的文本设置为算法可以提供的最佳转录。这不一定是完美的,但它是算法认为最符合它所听到的。

最后,在这个 if 语句中,我们首先检查是否有错误,或者结果是否已经确定。如果其中任何一个为真,音频引擎和其他相关进程将停止,我们将删除 tap. 不用担心,您将在下一步中了解水龙头!

7. 启动音频引擎

终于,你一直在等待的那一刻!我们终于可以启动我们花了这么长时间创建的引擎。我们将通过安装“水龙头”来做到这一点。task在初始化下方添加以下代码 :

let recordingFormat = inputNode.outputFormat(forBus: 0)
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
    self.request?.append(buffer)
}

在这段代码中,我们将输入节点的输出格式设置为一个名为 recordingFormat. 这用于下一步tap在输入节点上安装音频以录制和监控音频。在完成处理程序内部,我们将 bufferPCM 格式添加到识别请求的末尾。要启动引擎,只需添加以下两行代码:

audioEngine.prepare()
try? audioEngine.start()

这只是准备然后尝试启动音频引擎。现在,我们需要从我们的按钮调用这个方法,所以让我们在下一步中这样做。

8. 禁用和启用按钮

我们不希望用户能够激活语音识别,除非它可以使用——否则,应用程序可能会崩溃。startDictation()我们可以通过委托方法来做到这一点,所以在方法声明下面添加以下几行代码 :

func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
    if available {
        dictationButton.isEnabled = true
    } else {
        dictationButton.isEnabled = false
    }
}

这将在语音识别器在不可用后变为可用或在可用后不可用时调用。在其中,我们将简单地使用 if 语句根据可用性状态启用或禁用按钮。

当按钮被禁用时,用户不会看到任何东西,但按钮不会响应点击。这是一种保护用户不要太快按下按钮的安全网。

9. 响应按钮点击

剩下要做的最后一件事是在用户点击按钮时做出响应。在这里,我们还可以更改按钮的内容,并告诉用户他们需要做什么。为了刷新您的记忆,这是 @IBAction我们之前制作的:

@IBAction func dictationButtonTapped() {
    // Your code goes here
}

在此函数内部,添加以下 if 语句:

if audioEngine.isRunning {
    dictationButton.setTitle("Start Recording", for: .normal)
    promptLabel.text = "Tap the button to dictate..."
    
    request?.endAudio()
    audioEngine.stop()
} else {
    dictationButton.setTitle("Stop Recording", for: .normal)
    promptLabel.text = "Go ahead. I'm listening..."
    
    startDictation()
}

如果音频引擎已经在运行,我们希望停止语音识别并向用户显示适当的提示。如果它没有运行,我们需要启动识别和显示选项让用户停止听写。

结论

而已!您已经创建了一个可以识别您的声音并进行转录的应用程序。这可用于各种应用程序,以帮助无法以其他方式与您的应用程序交互的用户。如果您喜欢本教程,请务必查看本系列中的其他教程!


文章目录
  • 项目设置
  • 1. 请求许可
  • 2. 设计用户界面
  • 3. 添加变量
  • 4. 声明听写方法
  • 5. 初始化变量
  • 6. 初始化任务变量
  • 7. 启动音频引擎
  • 8. 禁用和启用按钮
  • 9. 响应按钮点击
  • 结论