2017-01-03 71 views
6

我同時實現語音到文本得到這個錯誤:終止應用程序由於未捕獲的應用程序崩潰時使用語音套件IOS

Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: _recordingTap == nil'

和:

ERROR: [0x1b2df5c40] >avae> AVAudioNode.mm:565: CreateRecordingTap: required condition is false: _recordingTap == nil

這裏是我的viewController的代碼:

public class ViewController: UIViewController, SFSpeechRecognizerDelegate { 
// MARK: Properties 

private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))! 

private var recognitionRequest: SFSpeechAudioBufferRecognitionRequest? 

private var recognitionTask: SFSpeechRecognitionTask? 

private let audioEngine = AVAudioEngine() 

@IBOutlet var textView : UITextView! 

@IBOutlet var recordButton : UIButton! 

// MARK: UIViewController 

public override func viewDidLoad() { 
    super.viewDidLoad() 

    // Disable the record buttons until authorization has been granted. 
    recordButton.isEnabled = false 
} 

override public func viewDidAppear(_ animated: Bool) { 
    speechRecognizer.delegate = self 

    SFSpeechRecognizer.requestAuthorization { authStatus in 
     /* 
      The callback may not be called on the main thread. Add an 
      operation to the main queue to update the record button's state. 
     */ 
     OperationQueue.main.addOperation { 
      switch authStatus { 
       case .authorized: 
        self.recordButton.isEnabled = true 

       case .denied: 
        self.recordButton.isEnabled = false 
        self.recordButton.setTitle("User denied access to speech recognition", for: .disabled) 

       case .restricted: 
        self.recordButton.isEnabled = false 
        self.recordButton.setTitle("Speech recognition restricted on this device", for: .disabled) 

       case .notDetermined: 
        self.recordButton.isEnabled = false 
        self.recordButton.setTitle("Speech recognition not yet authorized", for: .disabled) 
      } 
     } 
    } 
} 

private func startRecording() throws { 

    // Cancel the previous task if it's running. 
    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() 

    guard let inputNode = audioEngine.inputNode else { fatalError("Audio engine has no input node") } 
    guard let recognitionRequest = recognitionRequest else { fatalError("Unable to created a SFSpeechAudioBufferRecognitionRequest object") } 

    // Configure request so that results are returned before audio recording is finished 
    recognitionRequest.shouldReportPartialResults = true 

    // A recognition task represents a speech recognition session. 
    // We keep a reference to the task so that it can be cancelled. 
    recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in 
     var isFinal = false 

     if let result = result { 
      self.textView.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.recordButton.isEnabled = true 
      self.recordButton.setTitle("Start Recording", for: []) 
     } 
    } 

    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() 

    textView.text = "(Go ahead, I'm listening)" 
} 

// MARK: SFSpeechRecognizerDelegate 

public func speechRecognizer(_ speechRecognizer: SFSpeechRecognizer, availabilityDidChange available: Bool) { 
    if available { 
     recordButton.isEnabled = true 
     recordButton.setTitle("Start Recording", for: []) 
    } else { 
     recordButton.isEnabled = false 
     recordButton.setTitle("Recognition not available", for: .disabled) 
    } 
} 

// MARK: Interface Builder actions 

@IBAction func recordButtonTapped() { 
    if audioEngine.isRunning { 
     audioEngine.stop() 
     recognitionRequest?.endAudio() 
     recordButton.isEnabled = false 
     recordButton.setTitle("Stopping", for: .disabled) 
    } else { 
     try! startRecording() 
     recordButton.setTitle("Stop recording", for: []) 
    } 
} 
} 

回答

9

嘗試使用它在停止錄製

斯威夫特3

audioEngine.inputNode?.removeTap(onBus: 0) 

這是幫助我,我希望它幫助你。

+0

感謝您的幫助。 –

5

您可能已經在公共汽車上打了一個水龍頭,而且在同一輛公共汽車上不能有另一個。停止引擎時應該移除TapOnBus。

+1

感謝您的回答,它幫助我 – Evsenev

相關問題