专栏名称: Cocoa开发者社区
CocoaChina苹果开发中文社区官方微信,提供教程资源、app推广营销、招聘、外包及培训信息、各类沙龙交流活动以及更多开发者服务。
目录
相关文章推荐
51好读  ›  专栏  ›  Cocoa开发者社区

iOS 10中如何搭建一个语音转文字框架

Cocoa开发者社区  · 公众号  · ios  · 2016-10-25 08:28

正文

▲点击上方“ CocoaChina ”关注即可免费学习iOS开发


原文: Building a Speech-to-Text App Using Speech Framework in iOS 10

作者: Sahand Edrisian

译者:王跃


在2016WWDC大会上,Apple公司介绍了一个很好的语音识别的API,那就是Speech framework。事实上,这个Speech Kit就是Siri用来做语音识别的框架。如今已经有一些可用的语音识别框架,但是它们要么太贵要么不好。在今天的教程里面,我会教你怎样创建一个使用Speech Kit来进行语音转文字的类似Siri的app。


设计App UI


前提:你需要Xcode 8 beta版本和一个运行iOS 10 beta系统版本的iOS 设备。


先从创建一个新的命名为SpeechToTextDemo的单视图工程开始。接下来,到 Main.storyboard 中添加一个 UILabel,一个 UITextView, 和一个 UIButton,你的storyboard应该看起来如下图:



接下来在 ViewController.swift文件中为UITextView 和UIButton 定义outlet变量。在这个demo当中,我设置UITextView 的名称为“textView”,UIButton的名称为“microphoneButton”。然后创建一个当microphone按钮被点击时会触发的空的按钮执行方法。


@IBAction func microphoneTapped(_ sender: AnyObject) {

}


如果你不想从创建最原始工程开始,你可以在 在这里下载原始工程 然后继续下面的教学指导。


使用Speech Framework


为了能使用Speech framework, 你必须首先导入它然后遵循 SFSpeechRecognizerDelegate 协议。因此让我们导入这个框架,然后在 ViewController 文件中加上它的协议。现在你的 ViewController.swift 文件应该如下所示:


import UIKit

import Speech

class ViewController: UIViewController, SFSpeechRecognizerDelegate {

@IBOutlet weak var textView: UITextView!

@IBOutlet weak var microphoneButton: UIButton!

override func viewDidLoad() {

super.viewDidLoad()

}

@IBAction func microphoneTapped(_ sender: AnyObject) {

}

}


用户授权


在使用speech framework做语音识别之前,你必须首先得到用户的允许,因为不仅仅只有本地的ios设备会进行识别,苹果的服务器也会识别。所有的语音数据都会被传递到苹果的后台进行处理。因此,获取用户授权是强制必须的。


让我们在 viewDidLoad 方法里授权语音识别。用户必须允许app使用话筒和语音识别。首先,声明一个speechRecognizer变量:


private let speechRecognizer = SFSpeechRecognizer(locale: Locale.init(identifier: "en-US"))  //1


然后按如下更新 viewDidLoad 方法:


override func viewDidLoad() {

super.viewDidLoad()

microphoneButton.isEnabled = false  //2

speechRecognizer.delegate = self  //3

SFSpeechRecognizer.requestAuthorization { (authStatus) in  //4

var isButtonEnabled = false

switch authStatus {  //5

case .authorized:

isButtonEnabled = true

case .denied:

isButtonEnabled = false

print("User denied access to speech recognition")

case .restricted:

isButtonEnabled = false

print("Speech recognition restricted on this device")

case .notDetermined:

isButtonEnabled = false

print("Speech recognition not yet authorized")

}

OperationQueue.main.addOperation() {

self.microphoneButton.isEnabled = isButtonEnabled

}

}

}


  1. 首先,我们创建一个带有标识符en-US 的 SFSpeechRecognizer实例,这样语音识别API就能知道用户说的是哪一种语言。这个实例就是处理语音识别的对象。

  2. 我们默认让microphone按钮失效直到语音识别功能被激活。

  3. 接下来,把语音识别的代理设置为 self 也就是我们的ViewController.

  4. 之后,我们必须通过调用SFSpeechRecognizer.requestAuthorization方法来请求语音识别的授权。

  5. 最后,检查验证的状态。如果被授权了,让microphone按钮有效。如果没有,打印错误信息然后让microphone按钮失效。


现在如果你认为app跑起来之后你会看到一个授权弹出窗口,那你就错了。如果运行,app会崩溃。好吧,既然知道结果为什么还要问呢?(别打我),看看下面解决方法。


提供授权消息


苹果要求app里所有的授权都要一个自定义的信息。例如语音授权,我们必须请求2个授权:


  1. 麦克风使用权。

  2. 语音识别。


为了自定义信息,你必须在info.plist 配置文件里提供这些自定义消息。


让我们打开 info.plist配置文件的源代码。首先,右键点击 info.plist。然后选择Open As > Source Code。最后,拷贝下面的XML代码然后在 标记前插入这段代码。



现在你已经在info.plist文件里添加了两个键值:


  • NSMicrophoneUsageDescription -为获取麦克风语音输入授权的自定义消息。注意这个语音输入授权仅仅只会在用户点击microphone按钮时发生。

  • NSSpeechRecognitionUsageDescription – 语音识别授权的自定义信息


可以自行更改这些消息的内容。现在点击Run按钮,你应该可以编译和成功运行app了,不会报任何错误。



注意: 如果稍后在工程运行完成时还没有看到语音输入授权框,那是因为你是在模拟器上运行的程序。iOS模拟器没有权限进入你Mac电脑的麦克风。


处理语音识别


现在我们已经实现了用户授权,我们现在去实现语音识别功能。先从在 ViewController里定义下面的对象开始:


private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?

private var recognitionTask: SFSpeechRecognitionTask?

private let audioEngine = AVAudioEngine()


  1. recognitionRequest对象处理了语音识别请求。它给语音识别提供了语音输入。

  2. reconition task对象告诉你语音识别对象的结果。拥有这个对象很方便因为你可以用它删除或者中断任务。

  3. audioEngine是你的语音引擎。它负责提供你的语音输入。


接下来,创建一个新的方法名叫 startRecording()。


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 {

print("audioSession properties weren't set because of an error.")







请到「今天看啥」查看全文