博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS 语音识别,语音转文字的实现(Speech 框架的使用)
阅读量:5883 次
发布时间:2019-06-19

本文共 5576 字,大约阅读时间需要 18 分钟。

闲来无聊翻看苹果官方文档的时候看到一个 ,之前并没有接触过这个框架,看了一下这个框架其实不大,于是决定研究一下。 Speech API可让我们扩展和增强应用程序中的语音识别体验,而无需键盘,就可以实现语音输入这样的功能。既然涉及到语音这些敏感的数据,必然是要通过用户授权的,也就是说 info.plist 文件中需要添加响应的键值来获取用户权限。因为语音识别并不是在iOS 设备本地进行识别,而是在苹果的伺服器上进行识别的。所有的语音数据都需要传给苹果的后台服务器进行处理。因此必须得到用户的授权。

NSMicrophoneUsageDescription
当你按下 开始 按钮,我们将使用麦克风进行录音
NSSpeechRecognitionUsageDescription
当你对着麦克风说话时,我们将开始语音识别
复制代码

语音识别是基于网络的服务,因此强制执行限制,以便所有应用程序可以免费使用该服务。每个设备可能会限制每天可以执行的识别次数,并且每个应用程序可以根据每天的请求数量在全球范围内进行限制。例如,如果识别请求快速失败(在启动的一秒或两秒内),则识别服务可能暂时无法应用到您的应用程序中,您可能希望稍后再次请求用户。 此外语音识别可以为电池寿命和网络使用造成相对较高的负担。在iOS 10中,话音音频持续时间限制在约1分钟,这与键盘相关听写的限制相似。 对于Speech 的使用姿势官方是给出了案例的,可以来 。当然你也可以看我的 ,欢迎 Star鼓励。

下面给出我的代码和一些代码注释:

////  ViewController.swift//  YaHoYiSpeech////  Created by 太阳在线YHY on 2017/6/10.//  Copyright © 2017年 太阳在线. All rights reserved.//import UIKitimport Speechclass ViewController: UIViewController {	@IBOutlet weak var textView: UITextView!		@IBOutlet weak var startBtn: UIButton!			//  在进行语音识别之前,你必须获得用户的相应授权,因为语音识别并不是在iOS 设备本地进行识别,而是在苹果的伺服器上进行识别的。所有的语音数据都需要传给苹果的后台服务器进行处理。因此必须得到用户的授权。	// 创建语音识别器,指定语音识别的语言环境 locale ,将来会转化为什么语言,这里是使用的当前区域,那肯定就是简体汉语啦	private let speechRecognizer = SFSpeechRecognizer(locale: Locale.autoupdatingCurrent)	// 使用 identifier 这里设置的区域是台湾,将来会转化为繁体汉语	//	private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh-TW"))			// 发起语音识别请求,为语音识别器指定一个音频输入源,这里是在音频缓冲器中提供的识别语音。	// 除 SFSpeechAudioBufferRecognitionRequest 之外还包括:	// SFSpeechRecognitionRequest  从音频源识别语音的请求。	// SFSpeechURLRecognitionRequest 在录制的音频文件中识别语音的请求。	private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?	// 语音识别任务,可监控识别进度。通过他可以取消或终止当前的语音识别任务	private var recognitionTask: SFSpeechRecognitionTask?	// 语音引擎,负责提供录音输入	private let audioEngine = AVAudioEngine()		override func viewDidLoad() {		super.viewDidLoad()				// 输出一下语音识别器支持的区域,就是上边初始化SFSpeechRecognizer 时 locale 所需要的 identifier	    print(SFSpeechRecognizer.supportedLocales())				startBtn.isEnabled = false		// 设置语音识别器代理		speechRecognizer?.delegate = self				// 要求用户授予您的应用许可来执行语音识别。		SFSpeechRecognizer.requestAuthorization { (status) in			var isButtonenable = false			// 识别器的授权状态			switch status {			    // 经过授权				case .authorized:					// 经过授权之后就允许录音按钮点击					isButtonenable = true			    // 拒绝授权				case .denied:					isButtonenable = false					print("User denied access to speech recognition")			    // 保密,也就是不授权				case .restricted:					isButtonenable = false					print("Speech recognition restricted on this device")			    // 未决定				case .notDetermined:					isButtonenable = false					print("Speech recognition not yet authorized")				}								OperationQueue.main.addOperation() {					self.startBtn.isEnabled = isButtonenable				}		}	}		func startRecordingPersonSpeech() {		// 检查 recognitionTask 任务是否处于运行状态。如果是,取消任务开始新的任务		if recognitionTask != nil {			// 取消当前语音识别任务。			recognitionTask?.cancel()			// 语音识别任务的当前状态 是一个枚举值			print(recognitionTask!.state)						recognitionTask = nil					}				// 建立一个AVAudioSession 用于录音		let audioSession = AVAudioSession.sharedInstance()		do {			// category 设置为 record,录音			try audioSession.setCategory(AVAudioSessionCategoryRecord)			// mode 设置为 measurement			try audioSession.setMode(AVAudioSessionModeMeasurement)			// 开启 audioSession			try audioSession.setActive(true, with: .notifyOthersOnDeactivation)		} catch {			print("audioSession properties weren't set because of an error.")		}				// 初始化RecognitionRequest,在后边我们会用它将录音数据转发给苹果服务器		recognitionRequest = SFSpeechAudioBufferRecognitionRequest()				// 检查 iPhone 是否有有效的录音设备		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 = true				// 使用recognitionTask方法开始识别。		recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in			// 用于检查识别是否结束			var isFinal = false			// 如果 result 不是 nil,			if result != nil {				// 将 textView.text 设置为 result 的最佳音译				self.textView.text = result?.bestTranscription.formattedString				// 如果 result 是最终,将 isFinal 设置为 true				isFinal = (result?.isFinal)!			}						// 如果没有错误发生,或者 result 已经结束,停止audioEngine 录音,终止 recognitionRequest 和 recognitionTask			if error != nil || isFinal {				self.audioEngine.stop()				inputNode.removeTap(onBus: 0)								self.recognitionRequest = nil				self.recognitionTask = nil				// 开始录音按钮可用				self.startBtn.isEnabled = true			}		})				// 向recognitionRequest加入一个音频输入		let recordingFormat = inputNode.outputFormat(forBus: 0)		inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in			self.recognitionRequest?.append(buffer)		}				audioEngine.prepare()				do {			// 开始录音			try audioEngine.start()		} catch {			print("audioEngine couldn't start because of an error.")		}				textView.text = "请讲话!"			}			@IBAction func startRecording(_ sender: UIButton) {		if audioEngine.isRunning {			// 停止录音			audioEngine.stop()			// 表示音频源已完成,并且不会再将音频附加到识别请求。			recognitionRequest?.endAudio()			startBtn.isEnabled = false			startBtn.setTitle("开始", for: .normal)		} else {			startRecordingPersonSpeech()			startBtn.setTitle("结束", for: .normal)		}	}}extension ViewController: SFSpeechRecognizerDelegate {	func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {		if available {			startBtn.isEnabled = true		}else {			startBtn.isEnabled = false		}	}}复制代码

转载地址:http://eztix.baihongyu.com/

你可能感兴趣的文章
Jndi配置数据源
查看>>
华为交换机端口链路类型简析——access、trunk、hybrid
查看>>
[转载] Live Writer 配置写 CSDN、BlogBus、cnBlogs、163、sina 博客
查看>>
2013年SEO集群最新优化工具
查看>>
SQL:连表查询
查看>>
MySQL日期函数、时间函数总结(MySQL 5.X)
查看>>
c语言用尾插法新建链表和输出建好的链表
查看>>
Java基础学习总结(1)——equals方法
查看>>
Java基础学习总结(2)——接口
查看>>
【性能优化】---懒加载---
查看>>
DNS 不生效的修改方法
查看>>
web.xml配置详解
查看>>
HTTP协议详解
查看>>
Struts2文件上传
查看>>
我的友情链接
查看>>
Oracle数据库之SQL起航
查看>>
Oracle数据库之SQL单行函数---日期函数集锦
查看>>
使用OpenCV与Face++实现人脸解锁
查看>>
高性能 Oracle JDBC 编程
查看>>
java 中ResultSet可以获取的数据类型及返回值类型列表
查看>>