AVSpeechRecognizer: обязательное условие - false: _recordingTap == nil error в Swift3

Понятия не имею, почему у меня эта ошибка. Я получил ошибку

Завершение работы приложения из-за неперехваченного исключения 'com.apple.coreaudio.avfaudio', причина: 'требуемое условие неверно: _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)")

    }

}

}


person Ryohei    schedule 14.02.2017    source источник
comment
проверьте свой входной узел, если inputnote! = nill   -  person Nilesh Parmar    schedule 08.05.2017


Ответы (1)


Вы можете быстро нажать кнопку начала записи, чтобы повторить этот сбой, причина в том, что если вы остановите audioEngine, audioEngine.inputNode все еще там. Вам нужно добавить это, чтобы остановить запись.

    audioEngine.stop()
    recognitionRequest?.endAudio()
    audioEngine.inputNode?.removeTap(onBus: 0)
person shujucn    schedule 22.09.2017
comment
я пробовал, но не работал, братан let format = input.inputFormat (forBus: 0) if format.channelCount == 0 {print (format.channelCount empty) engine.stop () input.removeTap (onBus: 0)} - person famfamfam; 30.03.2021