iOS 10:用 Speech 框架创建語音輸入 App

原文:http://www.appcoda.com.tw/siri-speech-framework/
在 2016 WWDC 大會上,蘋果推出了可以用於語音識別的 Speech Kit 框架。實際上,Siri 就是用 Speech Kit 框架來進行語音識別的。其實現在已經有一些語音識別框架了,但它們要麼太貴,要麼用法複雜。在本教程中,我將使用 Speech Kit 創建一個類似 Siri 的 app 用於將語音轉換成文本。

创建 UI

[ecko_alert color=”green”]前提: 你需要拥有 Xcode 8 beta 以及一台搭载 iOS 10 的设备。[/ecko_alert]

新建一個名為 SpeechToTextDemo 的專案。打開 Main.storyboard ,拖入一個 UILabel、一個 UITextView 以及一個 UIButton

最終效果如下:

speechkit-demo-1

然後在 ViewController.swift 中,分別為 UITextViewUIButton 創建相應的 IBOutlet 變量。在這個 demo 中,我用 “textView” 變量引用 UITextView,用 “microphoneButton” 變量來引用 UIButton 。然後創建一個空的 IBAction 方法,用於處理麥克風按鈕被點擊的事件:

@IBAction func microphoneTapped(_ sender: AnyObject) {}

如果你不想從頭開始,你可以從 這裡下載初始專案 并繼續後面的內容。

使用 Speech Framework

要使用 Speech framework,你首先要 import 這個框架并實現 SFSpeechRecognizerDelegate 協議。先 import 這個框架,然後將這個協議添加到類 ViewController 的聲明中。現在的 ViewController.swift 應該是這個樣子:

import UIKit
import Speechclass ViewController: UIViewController, SFSpeechRecognizerDelegate {@IBOutlet weak var textView: UITextView!@IBOutlet weak var microphoneButton: UIButton!override func viewDidLoad() {super.viewDidLoad()}@IBAction func microphoneTapped(_ sender: AnyObject) {}}

用戶授權

在進行語音識別之前,你必須獲得用戶的相應授權,因為語音識別並不是在 iOS 設備本地進行識別,而是在蘋果的服務器上進行識別的。所有的語音數據都需要傳給蘋果的後台服務器進行處理。因此必須得到用戶的授權。

我們先在 viewDidLoad 方法中獲取用戶授權。用戶應當允許我們的 app 使用聲頻輸入和語音識別。首先聲明一個 speechRecognizer 變量:

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

然後修改 viewDidLoad 方法為:

override func viewDidLoad() {super.viewDidLoad()microphoneButton.isEnabled = false  //2speechRecognizer.delegate = self  //3SFSpeechRecognizer.requestAuthorization { (authStatus) in  //4var isButtonEnabled = falseswitch authStatus {  //5case .authorized:isButtonEnabled = truecase .denied:isButtonEnabled = falseprint("User denied access to speech recognition")case .restricted:isButtonEnabled = falseprint("Speech recognition restricted on this device")case .notDetermined:isButtonEnabled = falseprint("Speech recognition not yet authorized")}OperationQueue.main.addOperation() {self.microphoneButton.isEnabled = isButtonEnabled}}
}
  1. 首先,我們創建了一個 SFSpeechRecognizer 對象,并指定其 locale identifier 為 en-US,也就是通知語音識別器用戶所使用的語言。這個對象將用於語音識別。
  2. 默認,我們將禁用 microphone 按鈕,一直到語音識別器被激活。

  3. 將語音識別器的 delgate 設為 self,也就是我們的 ViewController

  4. 然後,調用 SFSpeechRecognizer.requestAuthorization 獲得語音識別的授權。

  5. 最後,判斷授權狀態,如果用戶已授權,enable 麥克風按鈕。否則打印錯誤信息并禁用麥克風按鈕。

你可能以為現在運行 app 就能看到用戶授權提示了,其實不然。當你運行 app,app 會崩潰。這是什麼鬼?

提供授權信息

蘋果需要你為每個授權指定一個定制的消息文本。就 Speech framework 而言,我們必須獲得兩個授權:

  1. 使用麥克風
  2. 語音識別

要定制這些授權消息,你必須在 info.plist 文件中設置一些值。

以 Source Code 方式打開 info.plist 文件。首先,在 info.plist 文件上點擊右鍵,然後依次選擇 Open As > Source Code 菜單。然後,拷貝下面的 XML 并將之插入到 </dict> 標籤之前.

NSMicrophoneUsageDescription  當你按下“開始識別”并開始講話時,將使用麥克風進行錄音。NSSpeechRecognitionUsageDescription  當你對著麥克風說話時,將進行語音識別。

這會在 info.plist 文件中增加兩個 key:

  • NSMicrophoneUsageDescription - 這個 key 用於指定錄音設備授權信息。注意,只有在用戶點擊麥克風按鈕時,這條信息才會顯示。
  • NSSpeechRecognitionUsageDescription -這個 key 用於指定語音識別授權信息。

你可以隨意指定這些字符串的值。現在,請點擊 Run 編譯和運行 app,錯誤不再出現。

Speech Framework Authorization

[ecko_alert color=”gray”]備註: 當項目完成后,你不會看到錄音設備授權信息,那麼你可能是正在模擬器上運行 app。模擬器無法訪問 Mac 上的麥克風。[/ecko_alert]

語音識別處理

搞定用戶授權之後,我們來實現語音識別。在 ViewController 中添加如下變量:

private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
private var recognitionTask: SFSpeechRecognitionTask?
private let audioEngine = AVAudioEngine()
  1. 這個對象負責發起語音識別請求。它為語音識別器指定一個音頻輸入源。
  2. 這個對象用於保存發起語音識別請求后的返回值。通過這個對象,你可以取消或中止當前的語音識別任務。

  3. 這個對象引用了語音引擎。它負責提供录音输入。

然後新增一個方法,方法名叫做 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.")}recognitionRequest = SFSpeechAudioBufferRecognitionRequest()guard let inputNode = audioEngine.inputNode else {fatalError("Audio engine has no input node")}guard let recognitionRequest = recognitionRequest else {fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")}recognitionRequest.shouldReportPartialResults = truerecognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in var isFinal = falseif result != nil {self.textView.text = result?.bestTranscription.formattedStringisFinal = (result?.isFinal)!}if error != nil || isFinal {self.audioEngine.stop()inputNode.removeTap(onBus: 0)self.recognitionRequest = nilself.recognitionTask = nilself.microphoneButton.isEnabled = true}})let recordingFormat = inputNode.outputFormat(forBus: 0)inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) inself.recognitionRequest?.append(buffer)}audioEngine.prepare()do {try audioEngine.start()} catch {print("audioEngine couldn't start because of an error.")}textView.text = "Say something, I'm listening!"}

這個方法會在“開始錄音”按鈕被點擊后調用。它的主要功能是開始語音識別和監聽麥克風。讓我們逐行解釋一下這些程式碼:

  1. 行 3-6 - 檢查 recognitionTask 任務是否處於運行狀態。如果是,取消任務,開始新的語音識別任務。
  2. 行 8-15 - 創建一個 AVAudioSession 用於錄音。將它的 category 設置為 record,mode 設置為 measurement,然後開啟 audio session。因為對這些屬性進行設置有可能导致異常,因此你必須將它們放到 try catch 語句中。

  3. 行 17 - 初始化 recognitionRequest 對象。這裡我們創建了一個 SFSpeechAudioBufferRecognitionRequest 對象。在後面,我們會用它將錄音數據转發給蘋果服務器。

  4. 行 19-21 - 檢查 audioEngine (物理设备) 是否擁有有效的錄音設備。如果沒有,我們產生一個致命錯誤。

  5. 行 23-25 - 檢查 recognitionRequest 對象是否初始化成功,值不為nil

  6. 行 27 - 告訴 recognitionRequest 在用戶說話的同時,將識別結果分批返回。

  7. Line 29 - 在 speechRecognizer 上調用 recognitionTask 方法開始識別。方法參數中包括一個完成塊。當語音識別引擎每次採集到語音數據、修改當前識別、取消、停止、以及返回最終譯稿時都會調用完成塊。

  8. 行 31 - 定義一個 boolean 變量,用於檢查識別是否結束。

  9. 行 35 - 如果 result 不為 nil,將 textView.text 設置為 result 的最佳譯稿。如果 result 是最終譯稿,將 isFinal 設置為 true。

  10. 行 39-47 - 如果沒有錯誤發生,或者 result 已經結束,停止 audioEngine (錄音) 并終止 recognitionRequestrecognitionTask。同時,使 “開始錄音”按鈕可用。

  11. 行 50-53 - 向 recognitionRequest 加入一個音頻輸入。注意,可以在啟動 recognitionTask 之後再添加音頻輸入。Speech 框架會在添加完音頻輸入后立即開始識別。

  12. 行 55 - 預熱并啟動 audioEngine.

觸發語音識別

當我們新建一個語音識別任務時,我們必須確保語音識別是可用的,因此我們必須在 ViewController 中加入一個委託方法。當語音識別不可用或者狀態發生改變時,應當改變 microphoneButton.enable 屬性。這樣,我們需要實現 SFSpeechRecognizerDelegate 協議的 availabilityDidChange 方法如下所示:

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

當可用狀態發生改變時,該方法被調用。只有在語音識別可用的情況下,錄音按鈕才會啟用。

然後我們需要修改 microphoneTapped(sender:) 方法:

@IBAction func microphoneTapped(_ sender: AnyObject) {if audioEngine.isRunning {audioEngine.stop()recognitionRequest?.endAudio()microphoneButton.isEnabled = falsemicrophoneButton.setTitle("Start Recording", for: .normal)} else {startRecording()microphoneButton.setTitle("Stop Recording", for: .normal)}
}

在這個方法裡,我們必須檢查 audioEngine 是否處於運行狀態。如果是,app 將停止 audioEngine,停止向 recoginitionRequest 輸入音頻數據,禁用 microphoneButton 并將按鈕標題設置為“開始錄音”。

如果 audioEngine 未運行,app 調用 startRecording() 并設置按鈕標題為“停止錄音”。

太好了!你可以測試你的 app 了。將 app 安裝到 iOS 設備,點擊“開始錄音”按鈕。然後開始說話吧!

Speech to text app demo

備註:

  1. 蘋果公司限制了每台設備的識別次數。限制的次數沒有明確,你可以聯繫蘋果公司。
  2. 蘋果也限制了每個 app 的識別次數。

  3. 如果你經常達到這個限制,請和蘋果公司聯繫,他們可能會幫你解決這個問題。

  4. 語音識別會佔用更多的電量和流量。

  5. 語音識別的時長一次最多可持續 1 分鐘。

結束

在本文中,你學習了如何使用神奇的新的 Speech 框架,蘋果通過這一神奇的新框架將語音識別和將語音翻譯成文本的能力開放給開發者。在 Siri 中使用了同樣的框架。它是一個相當輕量的 API,但它的功能卻非常強大,允許開發者實現令人讚歎的功能,比如將一個音頻文件轉換成文本。

我建議你看一下 WWDC 2016 session 509。希望你能喜歡這篇文章,并喜歡上這個嶄新的 API 。

另外,你可以從 Github 下載本教程的完整專案.

譯者簡介

楊宏焱,男,中國大陸籍人士,CSDN 博客專家(個人博客 http://blog.csdn.net/kmyhy)。2009 年開始學習蘋果 iOS 開發,精通 O-C/Swift 和 Cocoa Touch 框架,開發有多個商店應用和企業 App。熱愛寫作,著有和翻譯有多本技術專著,包括:《企業級 iOS 應用實戰》、《iPhone & iPad 企業移動應用開發秘笈》、《iOS8 Swift 編程指南》,《寫給大忙人看的 Swift》、《iOS Swift game Development cookbook》等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/65808.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android 讯飞语音评测,非同凡响的语音输入法——讯飞Android输入法评测

Android平台上的输入法实在是多得数不过来了&#xff0c;除了谷歌官方的输入法&#xff0c;还有老牌的搜狗等输入法以及后来的百度输入法等同样也在移动平台上大放异彩&#xff0c;可以说&#xff0c;如果再有人去开发输入法&#xff0c;如果不做出点差异化&#xff0c;那么几乎…

ios手机输入字母重复问题

今天写项目遇到一个奇葩问题&#xff0c;测试告诉我说&#xff0c;ios输入字母都是双份的&#xff0c;安卓没有这个问题。 刚开始我是这样写的&#xff0c;使用的oninput原生事件&#xff0c;身份证号只允许输入数字和字母&#xff0c;可是测试测完就说ios输入字母总是双份的&a…

苹果11微信表格服务器地址怎么填,苹果实用技巧:iPhone11手机微信打字怎么换行...

我们购买了苹果产品之后&#xff0c;我们未必就一定全部都了解苹果产品当中的一些功能如何去使用&#xff0c;那么这个时候如果我们不知道使用这些功能&#xff0c;那么产品的价值也就大打折扣了&#xff0c;所以我们务必是要了解到这些功能的使用&#xff0c;那么今天小编就给…

iphone之使用讯飞语音sdk实现语音识别功能

1、首先下载讯飞sdk及文档&#xff1a;http://open.voicecloud.cn/ 2、学习里面的demo简单实现了一个小的语音识别功能 先做一个简单demo&#xff0c;看看识别效果。注&#xff1a;语音识别必须联网。 所有接口必需在联网状态下才能正常使用。 效果图: #import <UIKit/UIK…

使用nodeJS中的WebSocket实现简单的聊天功能

思路整理 webSocket是服务器向客户端发送信息的一种手段 这里是 更多关于 webSocket 的内容 如果想要了解更多关于 nodeJS 中的webSocket内容&#xff0c;点击这里 开始之前&#xff0c;我们需要新建两个客户端和一个服务端&#xff0c; 服务端负责保存与客户端的连接并且在双…

node.js连接mysql出现错误

node.js连接mysql出现错误&#xff1a; ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client 目前是因为版本较高&#xff0c;最新的加密方式node还不支持 解决办法&#xff1a; 1、登录m…

GeneGPT:用领域工具增强大型语言模型,以改善对生物医学信息的访问

文章目录 一、论文关键信息二、主要内容1. Motivations2. 解决方案关键3. 实验和结果 三、总结与讨论 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、论文关键信息 论文标题&#xff1a;GeneGPT: Augmenting Large Language Models with Domain …

怎么禁止计算机共享磁盘,访问限制,分享如何禁止别人访问你电脑的本地磁盘...

随着科技的快速发展&#xff0c;现在的小学生都用上手机了&#xff0c;更是有不少小孩子都会在电脑上玩游戏了&#xff0c;小学生玩LOL可是不少见。在小孩子玩电脑时&#xff0c;除了害怕他沉迷游戏&#xff0c;无心向学&#xff0c;还有就是担心熊孩子乱删电脑文件。如果误删了…

hosts配置 kentrl 网络禁止 访问

hosts禁止联网的工具 127.0.0.1 activate.navicat.com 127.0.0.1 syntevo.com www.syntevo.com #smartgit 127.0.0.1 release.gitkraken.com api.gitkraken.com GitKraken – 超好用的 Git 可视化工具 - 免费版本 “version”: “6.5.1”, “url_deb”: “https://release.axo…

QQ/微信里被禁止访问的网页怎么处理 被屏蔽的域名如何正常访问

最近越来越多的网站被微信的检测系统封杀&#xff0c;有的是确实违规&#xff0c;有的则是被误报了。出现这样的问题&#xff0c;网站的流量瞬间就清零了&#xff0c;对站长来说是天塌一样的打击&#xff0c;那我们有没有办法能够有效的防止域名被微信封杀呢&#xff1f; 一、先…

禁止访问某文件

1.web.config文件配置&#xff1a; 在Web.config文件 <system.web> <httpHandlers>添加一个节点 <system.web><httpHandlers><!--禁止访问IPData目录下的文本文件--><add path"IPData/*.txt" verb"*" type"System.…

用户登录 默认 计算机 用户文件,guest登录系统默认禁止guest访问本地计算机(组图)...

Win10共享文件夹&#xff0c;创建(启用)用户和共享文件&#xff0c;修改特定用户访问权限 内容 一、以访客身份登录 默认情况下&#xff0c;系统禁止访客访问本地计算机。如果允许访客用户访问&#xff0c;则需要进行以下设置&#xff1a; 1.打开访客账户。 图1.1 打开Guest用户…

禁止外部网络访问公司内网

PC0所在网段模拟公司内网&#xff0c;Server0模拟外部网络。 要求内网可以访问外部网络&#xff0c;但是外网不能连接内网 Router1 配置如下&#xff1a; interface FastEthernet0/0 ip address 192.168.10.254 255.255.255.0 duplex auto speed auto ! interface Serial2/0…

微信内链接已禁止访问是什么情况?微信链接防封细节

有时候我们在微信上浏览一些网址的时候会出现这样的情况,比如提示已停止访问该网页,其实提示这个也是为了广大用户的安全着想,毕竟有很多不法网址存在的,但是也由于错杀等原因导致打不开,点击链接提示已禁止访问几种原因是什么呢?那么碰到这种情况我们应该怎么做呢? 一…

为什么公司内部服务禁止访问外网?

文章目录 什么是访问外网&#xff1f;访问外网的风险什么业务场景需要申请外连公网&#xff1f; 上图网络访问分为两个方向&#xff1a; Internet&#xff08;外网&#xff09;访问公司网络 www.taobao.com&#xff1a;请求经路由转发后会到公司负载均衡服务器上&#xff0c;负…

手动禁止访问某些网页,告别摸鱼

手动禁止访问某些网页 开端解题思路逆向思维实现效果总结 开端 有一个不自觉地朋友&#xff0c;告诉我有了新电脑后很烦恼&#xff1a;速度快了&#xff0c;访问网页也快了&#xff0c;管不住自己的手……总在该专心学习工作的时候忍不住刷微博&#xff0c;或者追剧停不下来。…

GoogleChrome禁止访问端口解决

由于系统的版本迭代&#xff0c;从weblogic10.3.6升级到最新的weblogic14.1.1.0&#xff0c;在本地环境搭建创建weblogic域的时候&#xff0c;由于个人风采定义了一个端口为6666的端口&#xff0c;在一起部署完成&#xff0c;通过Google Chrome浏览器访问访问不到&#xff0c;提…

chatgpt赋能python:Python如何利用GPU加速

Python如何利用GPU加速 在大数据时代&#xff0c;数据处理和分析的速度越来越成为企业和个人必备的能力。然而&#xff0c;随着数据集的不断增大&#xff0c;计算机处理速度的瓶颈逐渐暴露出来。为此&#xff0c;GPU加速成为了解决这一问题的有效途径。 什么是GPU加速 GPU即…

国产Gpt究竟该如何使用?

说实话&#xff0c;当初ChatGPT横空出世我是不相信它可以进行专业知识的解答的&#xff0c;毕竟只是人为写出来的一个程序而已&#xff0c;但是当使用了一段时间以后&#xff0c;发现人工智能真的不是说说而已。发展到现在gpt3.5已经很可怕了&#xff0c;4.0又出了~~ 由于一些不…

【2023】分享国内外大厂开发主要AI网站

大厂原版 OpenAI ChatGPT 921 New Bing 415 Notion AI 90 百度文心一言 467 TruthGPT 105 讯飞星火认知大模型 141 进阶 Hugging Face 62 写作AI ​ Dyrt 394&#xff08;AI写作&#xff09; ​ DeepL Write 211&#xff08;写作翻译&#xff09; ​AI自动写文章 535 …