美文网首页
SWift5.0-系统API实现语音识别

SWift5.0-系统API实现语音识别

作者: 31313_iOS | 来源:发表于2019-07-12 18:59 被阅读0次

最近才发现,其实系统已经提供了语音转成文字的API,于是立马去试了一下。结果发现很不错,速度也还可以。支持iOS10级以上的版本,需要麦克风权限和语音识别权限。下面来看看如何达到效果(没有深入的理解,但是可以用了)。

一、引入系统库

import Speech

二、主要的类

  1. SFSpeechRecognizer声音处理器
    langugeSimple 要语音识别的语言简称,具体有哪些可以看上一篇语音阅读
SFSpeechRecognizer(locale: Locale(identifier: langugeSimple))

这句会根据传入的语言简称来返回一个声音处理器,如果不支持,怎会返回nil。更多细节可以查看官方文档。

通过下面的方法来得到语音识别的结果

 // Recognize speech utterance with a request
    // If request.shouldReportPartialResults is true, result handler will be called
    // repeatedly with partial results, then finally with a final result or an error.
    open func recognitionTask(with request: SFSpeechRecognitionRequest, resultHandler: @escaping (SFSpeechRecognitionResult?, Error?) -> Void) -> SFSpeechRecognitionTask
  1. AVAudioEngine专门用来处理声音的数据
    这里细节不在介绍了,直接上使用的代码
 lazy var audioEngine: AVAudioEngine = {
        let audioEngine = AVAudioEngine()
        audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: audioEngine.inputNode.outputFormat(forBus: 0)) { (buffer, audioTime) in
            // 为语音识别请求对象添加一个AudioPCMBuffer,来获取声音数据
            self.recognitionRequest.append(buffer)
        }
        return audioEngine
    }()
  1. SFSpeechAudioBufferRecognitionRequest语音识别器
  // 语音识别器
    lazy var recognitionRequest: SFSpeechAudioBufferRecognitionRequest = {
        let recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
        return recognitionRequest
    }()
  1. SFSpeechRecognitionTask语言识别任务管理器,启用和关闭都要使用这个管理进行
public enum SFSpeechRecognitionTaskState : Int {

    case starting // Speech processing (potentially including recording) has not yet begun

    case running // Speech processing (potentially including recording) is running

    case finishing // No more audio is being recorded, but more recognition results may arrive

    case canceling // No more recognition reuslts will arrive, but recording may not have stopped yet

    case completed // No more results will arrive, and recording is stopped.
}

二、完整的代码

import UIKit
import Speech

enum LGSpeechType: Int {
    case start
    case stop
    case finished
    case authDenied
}

typealias LGSpeechBlock = (_ speechType: LGSpeechType, _ finalText: String?) -> Void

@available(iOS 10.0, *)

class LGSpeechManager: NSObject {

    private var parentVc: UIViewController!
    private var speechTask: SFSpeechRecognitionTask?
    // 声音处理器
    private var speechRecognizer: SFSpeechRecognizer?
    
    static let share = LGSpeechManager()
    
    private var block: LGSpeechBlock?
    
    // 语音识别器
    lazy var recognitionRequest: SFSpeechAudioBufferRecognitionRequest = {
        let recognitionRequest = SFSpeechAudioBufferRecognitionRequest()
        return recognitionRequest
    }()
    
 
    
    lazy var audioEngine: AVAudioEngine = {
        let audioEngine = AVAudioEngine()
        audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: audioEngine.inputNode.outputFormat(forBus: 0)) { (buffer, audioTime) in
            // 为语音识别请求对象添加一个AudioPCMBuffer,来获取声音数据
            self.recognitionRequest.append(buffer)
        }
        return audioEngine
    }()
    
    
    func lg_startSpeech(speechVc: UIViewController, langugeSimple: String, speechBlock: @escaping LGSpeechBlock) {
        parentVc = speechVc
        block = speechBlock
        
        lg_checkmicroPhoneAuthorization { (microStatus) in
            if microStatus {
                self.lg_checkRecognizerAuthorization(recongStatus: { (recStatus) in
                    if recStatus {
                        //  初始化语音处理器的输入模式 语音处理器准备就绪(会为一些audioEngine启动时所必须的资源开辟内存)
                        self.audioEngine.prepare()
                        if (self.speechTask?.state == .running) {   // 如果当前进程状态是进行中
                            // 停止语音识别
                           self.lg_stopDictating()
                        } else {   // 进程状态不在进行中
                            self.speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: langugeSimple))
                            guard (self.speechRecognizer != nil) else {
                                self.showAlert("抱歉,暂不支持当前地区使用语音输入")
                                return
                            }
                            self.lg_setCallBack(type: .start, text: nil)
                            // 开启语音识别
                            self.lg_startDictating()
                        }
                    } else {
                        self.showAlert("您已取消授权使用语音识别,如果需要使用语音识别功能,可以到设置中重新开启!")
                        self.lg_setCallBack(type: .authDenied, text: nil)
                    }
                })
            } else {
                //麦克风没有授权
                self.showAlert("您已取消授权使用麦克风,如果需要使用语音识别功能,可以到设置中重新开启!")
                self.lg_setCallBack(type: .authDenied, text: nil)
            }
        }
    }
}


@available(iOS 10.0, *)
extension LGSpeechManager: SFSpeechRecognitionTaskDelegate {
    
    //判断语音识别权限
    private func lg_checkRecognizerAuthorization(recongStatus: @escaping (_ resType: Bool) -> Void) {
        let authorStatus = SFSpeechRecognizer.authorizationStatus()
        if authorStatus == .authorized {
            recongStatus(true)
        } else if authorStatus == .notDetermined {
            SFSpeechRecognizer.requestAuthorization { (status) in
                if status == .authorized {
                    recongStatus(true)
                } else {
                    recongStatus(false )
                }
            }
        } else {
            recongStatus(false)
        }
    }
    
    //检测麦克风
    private func lg_checkmicroPhoneAuthorization(authoStatus: @escaping (_ resultStatus: Bool) -> Void) {
        let microPhoneStatus = AVCaptureDevice.authorizationStatus(for: .audio)

        if microPhoneStatus == .authorized {
            authoStatus(true)
        } else if microPhoneStatus == .notDetermined {
            AVCaptureDevice.requestAccess(for: .audio, completionHandler: {(res) in
                if res {
                    authoStatus(true)
                } else {
                    authoStatus(false)
                }
            })
        } else {
            authoStatus(false)
        }
    }
    
    //开始进行
    private func lg_startDictating() {
        do {
            try audioEngine.start()
            speechTask = speechRecognizer!.recognitionTask(with: recognitionRequest) { (speechResult, error) in
                // 识别结果,识别后的操作
                if speechResult == nil {
                    return
                }
                self.lg_setCallBack(type: .finished, text: speechResult!.bestTranscription.formattedString)
            }
        } catch  {
            print(error)
            self.lg_setCallBack(type: .finished, text: nil)
        }
    }
    
    // 停止声音处理器,停止语音识别请求进程
    func lg_stopDictating() {
        lg_setCallBack(type: .stop, text: nil)
        audioEngine.stop()
        recognitionRequest.endAudio()
        speechTask?.cancel()
    }
    
    private func lg_setCallBack(type: LGSpeechType, text: String?) {
        if block != nil {
            block!(type, text)
        }
    }
    
    private func showAlert(_ message: String) {
        let alertVC = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        let firstAction = UIAlertAction(title: "知道了", style: .default, handler: {(action) in
        })
        alertVC.addAction(firstAction)
        parentVc.present(alertVC, animated: true, completion: nil)
    }
}

相关文章

网友评论

      本文标题:SWift5.0-系统API实现语音识别

      本文链接:https://www.haomeiwen.com/subject/uhgykctx.html