首页 > 解决方案 > 当我连续单击开始和停止操作时,我的应用程序崩溃了。我正在使用语音识别

问题描述

这是我的课程代码,我正在使用语音框架来实现语音到文本的转换。但是,每当我连续按 stop_start 操作时,我的应用程序就会崩溃,并且出现此错误- Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'SFSpeechAudioBufferRecognitionRequest cannot be re-used'

import UIKit
import Speech

class ViewController: UIViewController ,SFSpeechRecognizerDelegate {
    
    //MARK:- IBOutlet
    @IBOutlet weak var textViewAudioText: UITextView!
    @IBOutlet weak var btn_start: UIButton!
    
    //MARK: - Local Properties
    let audioEngine = AVAudioEngine()
    let speechReconizer : SFSpeechRecognizer? = SFSpeechRecognizer()
    let requestSFSpeech = SFSpeechAudioBufferRecognitionRequest()
    var task : SFSpeechRecognitionTask!
    var isStart : Bool = false
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.requestPermission()
    }
    
    func requestPermission(){
        self.btn_start.isUserInteractionEnabled = false
        SFSpeechRecognizer.requestAuthorization { authStatus in
            OperationQueue.main.addOperation {
                if authStatus == SFSpeechRecognizerAuthorizationStatus.authorized {
                    print("Accepted")
                    self.btn_start.isUserInteractionEnabled = true
                } else if authStatus == .denied{
                    print("user denied permission")
                } else if authStatus == .notDetermined{
                    print("Device does not have functionality")
                } else if authStatus == .restricted{
                    print("user restricted")
                }
            }
        }
        
    }
    
}

//MARK:- UIBUtton Action
extension ViewController{
    @IBAction func actionGetTextFromAudio(_ sender: UIButton) {
        self.convertAudioFileToText()
    }
    
    @IBAction func btn_start_stop(_ sender: UIButton) {
        //MARK:- Coding for start and stop sppech recognization...!
        self.isStart = !self.isStart
        if self.isStart {
            self.convertSpeechToText()
            self.btn_start.setTitle("STOP", for: .normal)
            self.btn_start.backgroundColor = .systemGreen
        } else {
            self.cancelSpeechRecognization()
            self.btn_start.setTitle("START", for: .normal)
            self.btn_start.backgroundColor = .systemOrange
        }
    }
}


//MARK:- METHOD CONVERT AUDIO TO TEXT
extension ViewController {
    
    func convertAudioFileToText() {            
        let audioURL = Bundle.main.url(forResource: "test1", withExtension: "mp3")
        
        let extractedExpr: SFSpeechRecognizer? = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
        let recognizer = extractedExpr
        let request = SFSpeechURLRecognitionRequest(url: audioURL!)
        
        request.shouldReportPartialResults = true
        
        if (recognizer?.isAvailable)! {
            recognizer?.recognitionTask(with: request) { result, error in
                guard error == nil else { print("Error: \(error!)"); return }
                guard let result = result else { print("No result!"); return }
                
                print(result.bestTranscription.formattedString)
                self.textViewAudioText.text = result.bestTranscription.formattedString
            }
        } else {
            print("Device doesn't support speech recognition")
        }
    }
    
    /*
     1. First get audio url from where you have store audio file.
     2. Then create instance of SFSpeechRecognizer with locale that you have want.
     3. Create instance of SFSpeechURLRecognitionRequest which are used to requesting recognitionTask.
     
     4.  recognitionTask will give you result and error. Where result contains bestTranscription.formattedString. formmatedString is your test result of audio file.
     
     5.  If set request.shouldReportPartialResults = true,
     this will give your partial result of every line speak in audio.
     */
    
    
}



extension ViewController{
    //MARK: UPDATED FUNCTION
    
    func cancelSpeechRecognization() {
        task.finish()
        requestSFSpeech.endAudio()
        audioEngine.stop()
        
        if audioEngine.inputNode.numberOfInputs > 0 {
            audioEngine.inputNode.removeTap(onBus: 0)
        }
        self.textViewAudioText.text = ""
    }
    
    
    func convertSpeechToText() {
        let node = audioEngine.inputNode
        let recordingFormat = node.outputFormat(forBus: 0)
        
        node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, _) in
            self.requestSFSpeech.append(buffer)
        }
        
        audioEngine.prepare()
        do {
            try audioEngine.start()
        } catch let error {
            print("Error comes here for starting the audio listner \(error.localizedDescription)")
        }
        
        guard let myRecognization = SFSpeechRecognizer() else {
            print("Recognization is not allow on your local")
            return
        }
        
        if !myRecognization.isAvailable {
            print("Recognization is free right now, Please try again after some time.")
        }
        
        task = speechReconizer?.recognitionTask(with: requestSFSpeech, resultHandler: { (response, error) in
            guard let response = response else {
                if error != nil {
                    print(error.debugDescription)
                    
                }else {
                    print("Problem in giving the response")
                }
                return
            }
            
            let message = response.bestTranscription.formattedString
            print("Message : \(message)")
            self.textViewAudioText.text = message
        })
    }
    
}

标签: iosswift

解决方案


它可能需要停止语音识别任务。试试这个可能会有所帮助

        if audioEngine.inputNode.numberOfInputs > 0 {
            audioEngine.inputNode.removeTap(onBus: 0)
        }

录制完成后停止音频

 func finishSpeech(){
    audioEngine.stop() //AVAudioEngine()
    recognitionTask?.cancel() //speechRecognizer?.recognitionTask
    request.endAudio()  //SFSpeechAudioBufferRecognitionRequest?
    audioEngine.inputNode.removeTap(onBus: 0)
 }

发布代表您的解释的答案。这可能会有所帮助


推荐阅读