AVSpeechRecognizer:必需条件为false:_recordingTap ==在Swift3中出现nil错误

时间:2017-02-14 23:35:47

标签: swift avspeechsynthesizer sfspeechrecognizer

我不知道为什么会出现这个错误。我得到的错误是

  

由于未捕获的异常'com.apple.coreaudio.avfaudio'而终止应用程序,原因:'必需条件为false:_recordingTap == nil'

更新

实际上,这有效,但经过几次,突然按下按钮,麦克风不再起作用。然后它会导致错误并崩溃。

你能帮帮我吗?

class ViewController: UIViewController, SFSpeechRecognizerDelegate, UITextViewDelegate, AVSpeechSynthesizerDelegate {

@IBOutlet weak var myTextView: UITextView!
@IBOutlet weak var microphoneButton: UIButton!

private let speechRecognizer = SFSpeechRecognizer(locale: Locale.init(identifier: "en-US"))!
private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest?
private var recognitionTask: SFSpeechRecognitionTask?
private let audioEngine = AVAudioEngine()

var rightButton = UIBarButtonItem()

override func viewDidLoad() {
    super.viewDidLoad()

    microphoneButton.isEnabled = false
    speechRecognizer.delegate = self
    speechRecognizerFunc()

    myTextView.delegate = self
    myTextView.isUserInteractionEnabled = false

}



@IBAction func cancelButton(_ sender: UIBarButtonItem) {
    self.dismiss(animated: true, completion: nil)
}


func speechRecognizerFunc(){
    SFSpeechRecognizer.requestAuthorization {
        (authStatus) in
        var isButtonEnabled = false

        switch authStatus {

        case .authorized:
            isButtonEnabled = true

        case .denied:
            isButtonEnabled = false
            print("User denied access to speech recognition")

        case .restricted:
            isButtonEnabled = false
            print("Speech recognition restricted on this device")

        case .notDetermined:
            isButtonEnabled = false
            print("Speech recognition not yet authorized")
        }

        OperationQueue.main.addOperation() {
            self.microphoneButton.isEnabled = isButtonEnabled
        }
    }
}

@IBAction func microphoneTapped(_ sender: AnyObject) {


    if audioEngine.isRunning {

        audioEngine.stop()
        recognitionRequest?.endAudio()
        microphoneButton.isEnabled = false
        microphoneButton.setTitle("Start", for: .normal)
        myTextView.text = ""

    } else {

        myTextView.text = "Say something. I'm listening...."
        startRecording()
        microphoneButton.setTitle("Stop", for: .normal)
    }
}

func startRecording() {

    if recognitionTask != nil {
        recognitionTask?.cancel()
        recognitionTask = nil
    }

    let audioSession = AVAudioSession.sharedInstance()

    do {

        try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker)
        try audioSession.setMode(AVAudioSessionModeMeasurement)

        try audioSession.setActive(true, with: .notifyOthersOnDeactivation)

    } catch {

        print("audioSession properties weren't set because of an error.")

    }

    recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

    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 = speechRecognizer.recognitionTask(with: recognitionRequest, resultHandler: {

        (result, error) in

        var isFinal = false

        if result != nil {

            self.myTextView.text = result?.bestTranscription.formattedString
            isFinal = (result?.isFinal)!

        }

        if error != nil || isFinal {

            self.audioEngine.stop()
            inputNode.removeTap(onBus: 0)

            self.recognitionRequest = nil
            self.recognitionTask = nil

            self.microphoneButton.isEnabled = true
            self.performSegue(withIdentifier: "nv", sender: nil)
        }
    })

    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.")
    }
}

func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) {
    if available {
        microphoneButton.isEnabled = true
    } else {
        microphoneButton.isEnabled = false
    }
}

func popUpAlert(title: String, msg: String){
    let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
    let okay = UIAlertAction(title: "Okay", style: .default, handler: nil)
    alert.addAction(okay)
    self.present(alert, animated: true, completion: nil)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "nv" {
        let vc = segue.destination as! SpeechTableViewController
        vc.text = self.myTextView.text
        print("ViewControoler: text value: \(textValue)")

    }

}

}

1 个答案:

答案 0 :(得分:2)

你可以快速点击开始录制按钮重复此崩溃,原因是如果你停止audioEngine,audioEngine.inputNode仍然存在。你需要添加它来停止记录。

    audioEngine.stop()
    recognitionRequest?.endAudio()
    audioEngine.inputNode?.removeTap(onBus: 0)