【问题标题】:ios speech recognition Error Domain=kAFAssistantErrorDomain Code=216 "(null)"ios 语音识别错误域=kAFAssistantErrorDomain Code=216 "(null)"
【发布时间】:2017-11-29 17:48:39
【问题描述】:

基本上我是按照本教程学习 ios 语音识别模块: https://medium.com/ios-os-x-development/speech-recognition-with-swift-in-ios-10-50d5f4e59c48

但是当我在我的 iphone6 上测试它时,我总是得到这个错误: 错误域=kAFAssistantErrorDomain Code=216 "(null)"

我在互联网上搜索了它,但找到了非常少见的信息。

这是我的代码:

//
//  ViewController.swift
//  speech_sample
//
//  Created by Peizheng Ma on 6/22/17.
//  Copyright © 2017 Peizheng Ma. All rights reserved.
//

import UIKit
import AVFoundation
import Speech

class ViewController: UIViewController, SFSpeechRecognizerDelegate {

//MARK: speech recognize variables
let audioEngine = AVAudioEngine()
let speechRecognizer: SFSpeechRecognizer? = SFSpeechRecognizer(locale: Locale.init(identifier: "en-US"))
var request = SFSpeechAudioBufferRecognitionRequest()
var recognitionTask: SFSpeechRecognitionTask?
var isRecording = false

override func viewDidLoad() {
    // super.viewDidLoad()
    // get Authorization
    self.requestSpeechAuthorization()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

//MARK: properties
@IBOutlet weak var detectText: UILabel!
@IBOutlet weak var startButton: UIButton!

//MARK: actions
@IBAction func startButtonTapped(_ sender: UIButton) {
    if isRecording == true {


        audioEngine.stop()
//            if let node = audioEngine.inputNode {
//                node.removeTap(onBus: 0)
//            }
        audioEngine.inputNode?.removeTap(onBus: 0)
        // Indicate that the audio source is finished and no more audio will be appended
        self.request.endAudio()

        // Cancel the previous task if it's running
        if let recognitionTask = recognitionTask {
            recognitionTask.cancel()
            self.recognitionTask = nil
        }


        //recognitionTask?.cancel()
        //self.recognitionTask = nil
        isRecording = false
        startButton.backgroundColor = UIColor.gray
    } else {
        self.recordAndRecognizeSpeech()
        isRecording = true
        startButton.backgroundColor = UIColor.red
    }
}

//MARK: show alert
func showAlert(title: String, message: String, handler: ((UIAlertAction) -> Swift.Void)? = nil) {
    DispatchQueue.main.async { [unowned self] in
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .cancel, handler: handler))
        self.present(alertController, animated: true, completion: nil)
    }
}

//MARK: Recognize Speech
func recordAndRecognizeSpeech() {
    // Setup Audio Session
    guard let node = audioEngine.inputNode else { return }
    let recordingFormat = node.outputFormat(forBus: 0)
    node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
        self.request.append(buffer)
    }
    audioEngine.prepare()
    do {
        try audioEngine.start()
    } catch {
        self.showAlert(title: "SpeechNote", message: "There has been an audio engine error.", handler: nil)
        return print(error)
    }
    guard let myRecognizer = SFSpeechRecognizer() else {
        self.showAlert(title: "SpeechNote", message: "Speech recognition is not supported for your current locale.", handler: nil)
        return
    }
    if !myRecognizer.isAvailable {
        self.showAlert(title: "SpeechNote", message: "Speech recognition is not currently available. Check back at a later time.", handler: nil)
        // Recognizer is not available right now
        return
    }
    recognitionTask = speechRecognizer?.recognitionTask(with: request, resultHandler: { result, error in
        if let result = result {

            let bestString = result.bestTranscription.formattedString
            self.detectText.text = bestString

//                var lastString: String = ""
//                for segment in result.bestTranscription.segments {
//                    let indexTo = bestString.index(bestString.startIndex, offsetBy: segment.substringRange.location)
//                    lastString = bestString.substring(from: indexTo)
//                }
//                self.checkForColorsSaid(resultString: lastString)
        } else if let error = error {
            self.showAlert(title: "SpeechNote", message: "There has been a speech recognition error.", handler: nil)
            print(error)
        }
    })
}

//MARK: - Check Authorization Status
func requestSpeechAuthorization() {
    SFSpeechRecognizer.requestAuthorization { authStatus in
        OperationQueue.main.addOperation {
            switch authStatus {
            case .authorized:
                self.startButton.isEnabled = true
            case .denied:
                self.startButton.isEnabled = false
                self.detectText.text = "User denied access to speech recognition"
            case .restricted:
                self.startButton.isEnabled = false
                self.detectText.text = "Speech recognition restricted on this device"
            case .notDetermined:
                self.startButton.isEnabled = false
                self.detectText.text = "Speech recognition not yet authorized"
            }
        }
    }
}


}

非常感谢。

【问题讨论】:

  • 我经常遇到同样的错误,但不确定是什么问题。
  • 你好@Peizheng Ma 你有解决办法吗?我得到同样的错误请帮忙。 :(
  • 嗨@deltami,对不起,我还没有得到任何解决方案。苹果论坛似乎不如这里活跃:(我只是简单地压制错误。
  • @PeizhengMa 嘿,就我而言,它解决了不知道问题出在哪里,但现在我没有收到任何错误,它工作正常。 :)

标签: ios swift swift3 speech-recognition ios10


【解决方案1】:

我在遵循相同(优秀)教程时遇到了同样的问题,即使使用 GitHub 上的示例代码也是如此。为了解决这个问题,我必须做两件事:

首先,在代码开头添加request.endAudio(),以在startButtonTapped动作中停止录制。这标志着录音的结束。我看到你已经在你的示例代码中做到了。

其次,在recordAndRecognizeSpeech函数中,当'recognitionTask'启动时,如果没有检测到语音,则'result'将为nil并触发错误情况。所以,我在尝试分配结果之前测试了result != nil

因此,这两个函数的代码如下所示: 1.更新startButtonTapped:

@IBAction func startButtonTapped(_ sender: UIButton) {
    if isRecording {

        request.endAudio() // Added line to mark end of recording
        audioEngine.stop()

        if let node = audioEngine.inputNode {
            node.removeTap(onBus: 0)
        }
        recognitionTask?.cancel()

        isRecording = false
        startButton.backgroundColor = UIColor.gray

    } else {

        self.recordAndRecognizeSpeech()
        isRecording = true
        startButton.backgroundColor = UIColor.red
    }
}

以及 2. 在 recordAndRecognizeSpeech 内从 recognitionTask = ... 行更新:

    recognitionTask = speechRecognizer?.recognitionTask(with: request, resultHandler: { (result, error) in
        if result != nil { // check to see if result is empty (i.e. no speech found)
            if let result = result {
                let bestString = result.bestTranscription.formattedString
                self.detectedTextLabel.text = bestString

                var lastString: String = ""
                for segment in result.bestTranscription.segments {
                    let indexTo = bestString.index(bestString.startIndex, offsetBy: segment.substringRange.location)
                    lastString = bestString.substring(from: indexTo)
                }
                self.checkForColoursSaid(resultString: lastString)

            } else if let error = error {
                self.sendAlert(message: "There has been a speech recognition error")
                print(error)
            }
        }

    }) 

希望对你有帮助。

【讨论】:

    【解决方案2】:

    这样可以防止两个错误:上面提到的Code=216'SFSpeechAudioBufferRecognitionRequest cannot be re-used'错误。

    1. 完成而不是用取消来停止识别

    2. 停止音频

    像这样:

        // stop recognition
        recognitionTask?.finish()
        recognitionTask = nil
    
        // stop audio
        request.endAudio()
        audioEngine.stop()
        audioEngine.inputNode.removeTap(onBus: 0) // Remove tap on bus when stopping recording.
    

    附: audioEngine.inputNode 似乎不再是可选值,因此我使用了 no if let 构造。

    【讨论】:

    • 虽然这个答案看起来太简单了,但它确实修复了它声称要修复的两个错误!
    【解决方案3】:

    嘿,我遇到了同样的错误,但现在它工作得非常好。希望这段代码对你也有帮助:)。

    import UIKit
    import Speech
    
    class SpeechVC: UIViewController {
    
    @IBOutlet weak var slabel: UILabel!
    @IBOutlet weak var sbutton: UIButton!
    
    let audioEngine = AVAudioEngine()
    let SpeechRecognizer : SFSpeechRecognizer? = SFSpeechRecognizer()
    let request = SFSpeechAudioBufferRecognitionRequest()
    var recognitionTask:SFSpeechRecognitionTask?
    
    var isRecording = false
    override func viewDidLoad() {
        super.viewDidLoad()
    
    
        self.requestSpeechAuthorization()
    
        // Do any additional setup after loading the view, typically from a nib.
    }
    func recordAndRecognizeSpeech()
    {
        guard let node = audioEngine.inputNode else { return }
        let recordingFormat = node.outputFormat(forBus: 0)
        node.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer , _ in
    
            self.request.append(buffer)
        }
        audioEngine.prepare()
        do
        {
            try audioEngine.start()
        }catch
        {
            return print(error)
        }
        guard let myRecognizer = SFSpeechRecognizer() else {
            return
        }
        if !myRecognizer.isAvailable
        {
            return
        }
        recognitionTask = SpeechRecognizer?.recognitionTask(with: request, resultHandler: { result, error in
    
            if let result = result
            {
                let bestString = result.bestTranscription.formattedString
                self.slabel.text = bestString
    
                var lastString : String = ""
                for segment in result.bestTranscription.segments
                {
                    let indexTo = bestString.index(bestString.startIndex, offsetBy: segment.substringRange.location)
                    lastString = bestString.substring(from: indexTo)
                }
    
            }else if let error = error
            {
                print(error)
            }
        })
    }
    
    
    @IBAction func startAction(_ sender: Any) {
        if isRecording == true
        {
            audioEngine.stop()
            recognitionTask?.cancel()
            isRecording = false
            sbutton.backgroundColor = UIColor.gray
        }
        else{
            self.recordAndRecognizeSpeech()
            isRecording = true
            sbutton.backgroundColor = UIColor.red
        }
    
    }
    func cancelRecording()
    {
        audioEngine.stop()
        if let node = audioEngine.inputNode
        {
            audioEngine.inputNode?.removeTap(onBus: 0)
        }
        recognitionTask?.cancel()
    
    }
    
    
    func requestSpeechAuthorization()
    {
        SFSpeechRecognizer.requestAuthorization { authStatus in
            OperationQueue.main.addOperation {
                switch authStatus
                {
                case .authorized :
                    self.sbutton.isEnabled = true
                case .denied :
                    self.sbutton.isEnabled = false
                    self.slabel.text = "User denied access to speech recognition"
                case .restricted :
                    self.sbutton.isEnabled = false
                    self.slabel.text = "Speech Recognition is restricted on this Device"
                case .notDetermined :
                    self.sbutton.isEnabled = false
                    self.slabel.text = "Speech Recognition not yet authorized"
                }
            }
    
        }
    }
    }
    

    【讨论】:

      【解决方案4】:

      我遇到此错误是因为我在模拟器上运行应用程序。在普通设备上运行可以解决这个问题。

      【讨论】:

      • THNAKS。不知道为什么我希望模拟器在最有可能没有所有语音识别模块的情况下转录文本。即使在模拟器上,在线转录也能正常工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-28
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多