簡體   English   中英

快速語音識別

[英]Speech Recognition in swift

實際上,我在代碼中使用了語音識別,以根據識別出的語音找出聯系方式。 但是,它不斷將單詞添加到緩沖區中,我要刪除的是先前記錄的單詞或行。 就像我要搜索“史蒂夫·喬布斯”,然后是“比爾·蓋茨”一樣,它都被組合為“史蒂夫·喬布斯·比爾·蓋茨”。 以下是我的代碼。

import UIKit
import Speech

class SpeechRecognizer:NSObject,SFSpeechRecognizerDelegate{

    static let shared:SpeechRecognizer? = {
        return SpeechRecognizer()
    }()

    var isRunning = false

    private var speechRecognizer:SFSpeechRecognizer!
    private var audioEngine:AVAudioEngine!
    private var recognitionRequest:SFSpeechAudioBufferRecognitionRequest!
    private var recognitionTask:SFSpeechRecognitionTask!

    public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
        if available {
            print("recordign available")
        } else {
            print("Recording not available")
        }

    }

    func stopRecording() {
        if audioEngine == nil {
            return
        }
        if audioEngine.isRunning {
            audioEngine.inputNode.removeTap(onBus: 0)
            audioEngine.stop()
            recognitionTask?.cancel()
            recognitionRequest?.endAudio()
            print("Stopped")
            isRunning = false
        }
    }


    func start(result:@escaping(String)->()) {
        getSpeechRegnizationPermission { (per) in
            if per && !self.isRunning{
                do {
                    try self.startRecording(rcResult: { (rcRes) in
                    result(rcRes)
                })
                } catch {
                    print(error)
                }
            } else if self.isRunning {
                print("alrdy running")
            } else {
                print("no permission")
            }
        }
    }


    private func startRecording(rcResult:@escaping (String)->()) throws {
        self.stopRecording()
        isRunning = true
        speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))!
        audioEngine = AVAudioEngine()
        recognitionTask = nil
        recognitionRequest = nil

        if let recognitionTask = recognitionTask {
            recognitionTask.cancel()
            self.recognitionTask = nil
        }

        let audioSession = AVAudioSession.sharedInstance()
        try audioSession.setCategory(AVAudioSessionCategoryRecord)
        try audioSession.setMode(AVAudioSessionModeMeasurement)
        try audioSession.setActive(true, with: .notifyOthersOnDeactivation)

        recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

        let inputNode = audioEngine.inputNode
        guard let recognitionRequest = recognitionRequest else { fatalError("Unable to create a SfSpeechAudioBufferRecognitionRequest object")}

        recognitionRequest.shouldReportPartialResults = true

        recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in var isFinal = false
            if let result = result {
                rcResult(result.bestTranscription.formattedString)
                isFinal = result.isFinal
                print("Final word is :",isFinal)

            }
            if error != nil || isFinal {
                self.audioEngine.stop()
                inputNode.removeTap(onBus: 0)
                self.recognitionRequest = nil
                self.recognitionTask = nil
            }
        }

        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()
       print("Im listening ")
    }



    private func getSpeechRegnizationPermission(status:@escaping (Bool)->()){
        if SFSpeechRecognizer.authorizationStatus() == .authorized {
         status(true)
            return
        }
        SFSpeechRecognizer.requestAuthorization { (sta) in
            switch sta {
            case .authorized:
                status(true)
            case .denied:
                status(false)
            case .notDetermined:
                SFSpeechRecognizer.requestAuthorization({ (st) in
                    if st  == .authorized {
                        status(true)
                    } else {
                        status(false)
                    }
                })
            case .restricted:
                status(false)
            }
        }
    }

}

我建議先合並stopRecording函數和此代碼塊, stopRecording僅使用stopRecording

    if error != nil || isFinal {
        self.audioEngine.stop()
        inputNode.removeTap(onBus: 0)
        self.recognitionRequest = nil
        self.recognitionTask = nil
    }

這樣,您將剩下一種處置正在使用的資源的方法,而且您無需在startRecording函數的第一行調用stopRecording 獲得結果后,將該結果傳遞到rcResult(result.bestTranscription.formattedString)塊, stopRecording在該位置調用stopRecording

另外,也不要使用recognitionTask?.finish() recognitionTask?.cancel()來調用recognitionTask?.cancel() recognitionTask?.finish()

希望有幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM