iOS自带的Speech语音识别功能封装

1、在plist 文件加入以下配置:



Speech Recognition Usage Description

语音识别

NSMicrophoneUsageDescription

麦克风权限

2、单例管理: 

//
//  SpeechManager.swift
//  ChatgptClient
//
//  Created by 柯木超 on 2023/5/16.
//

import UIKit
import Speech

class SpeechManager: NSObject {
    
    static let shared = SpeechManager()
    
    // 定义语言识别需要用到的几个对象的引用
    private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh-CN"))! // 创建与指定区域设置关联的语音识别器
    private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? // 语音识别的请求
    private var recognitionTask: SFSpeechRecognitionTask? // 语音识别的任务类
    private let audioEngine = AVAudioEngine() // 音频引擎,用于音频输入
    private var inputNode:AVAudioInputNode!

    override init() {
        super.init()
        do {
            try initConfig()
        } catch {
            print("录音不可用!")
        }

    }
    
    func initConfig()  throws {
        // 配置应用程序的音频会话
        let audioSession = AVAudioSession.sharedInstance() // 管理音频硬件资源的分配
        try audioSession.setCategory(.playAndRecord, options: [ .mixWithOthers]) // 设置音频会话的类别、模式和选项。
        try audioSession.setActive(true, options: .notifyOthersOnDeactivation) // 激活音频会话
        inputNode = audioEngine.inputNode // inputNode|outputNode分别对应硬件的麦克风和扬声器
    }
    
    //开启麦克风权限
    func openAudioSession() {
        
        let permissionStatus = AVAudioSession.sharedInstance().recordPermission
        if permissionStatus == AVAudioSession.RecordPermission.undetermined {
            AVAudioSession.sharedInstance().requestRecordPermission { (granted) in
                //此处可以判断权限状态来做出相应的操作,如改变按钮状态
                if !granted {
                    DispatchQueue.main.async {
                        ToastUtils.showMessage("不开启麦克风权限没法进行语音聊天哦!!!")
                    }
                }
            }
        }
    }
    
    func IsOpenAudioSession() -> Bool{
        let authStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.audio)
        return authStatus != .restricted && authStatus != .denied
    }

    func stopRecording() {
        self.audioEngine.stop()
        self.recognitionRequest?.endAudio()
    }
    
    // 录制方法
    func startRecording(comple:@escaping (_ resultStr: String?) -> ()) throws {
        if !IsOpenAudioSession() {
            openAudioSession()
            return
        }
        // 取消上一次正在识别任务(如果有的话)
        recognitionTask?.cancel()
        self.recognitionTask = nil

        // 创建并配置语音识别请求
        recognitionRequest = SFSpeechAudioBufferRecognitionRequest() // 从捕获的音频内容(如来自设备麦克风的音频)识别语音的请求
        guard let recognitionRequest = recognitionRequest else { fatalError("无法创建SFSpeechAudioBufferRecognitionRequest对象") }
        
        if #available(iOS 16, *) {
            // iOS 16 已经支持自动添加标点符号,不需要再喊标点符号了
            recognitionRequest.addsPunctuation = true
        }
        if #available(iOS 13, *) {
            if speechRecognizer.supportsOnDeviceRecognition {
                recognitionRequest.requiresOnDeviceRecognition = true
            }
        }

        
        // 设置在音频录制完成之前返回结果
        // 每产生一种结果就马上返回
        recognitionRequest.shouldReportPartialResults = true
        
        // 将语音识别数据仅限于设备上
        if #available(iOS 13, *) {
            // 将此属性设置为true以防止SFSpeechRecognitionRequest通过网络发送音频
            // 设备上的请求将不那么准确。
            recognitionRequest.requiresOnDeviceRecognition = true
        }
        
        // 为语音识别会话创建识别任务
        // 保留对任务的引用,以便可以取消该任务
        recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in
            var isFinal = false
            
            if let result = result {
                isFinal = result.isFinal
                print("【识别内容】\(result.bestTranscription.formattedString)")
            }
            
            if error != nil || isFinal {
                // 如果出现问题,停止识别语音
                self.audioEngine.stop()
                self.inputNode.removeTap(onBus: 0)
                self.recognitionRequest = nil
                self.recognitionTask = nil
                
                comple(validString(result?.bestTranscription.formattedString))
            }
        }

        // 配置麦克风输入
        let recordingFormat = inputNode.outputFormat(forBus: 0)
        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
            self.recognitionRequest?.append(buffer)
        }
        
        audioEngine.prepare()
        try audioEngine.start()

    }
}

3、使用方法:

(1) 开始识别

do {
      try SpeechManager.shared.startRecording { resultStr in
        if validString(resultStr) != "" {
            // 这里做识别后的操作
         } else {
            print("chat 返回数据为空")
           }
         }
       }
     } catch {
         print("语音输入失败")
     }

(2) 结束识别:

SpeechManager.shared.stopRecording()

你可能感兴趣的:(iOS,ios,语音识别,人工智能)