1

我正在尝试实现语音到文本应用程序,我可以使用 SFSpeechRecognizer 从麦克风录制音频。用例是一旦用户停止说话,一个方法应该自动调用并停止录制。你能帮助我的用例。

请找到以下代码

func startRecording() {
    
    // Clear all previous session data and cancel task
    if recognitionTask != nil {
        recognitionTask?.cancel()
        recognitionTask = nil
    }

    // Create instance of audio session to record voice
    let audioSession = AVAudioSession.sharedInstance()
    do {
        try audioSession.setCategory(AVAudioSession.Category.record, mode: AVAudioSession.Mode.measurement, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
        try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
    } catch {
        print("audioSession properties weren't set because of an error.")
    }

    self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

    let inputNode = audioEngine.inputNode

    guard let recognitionRequest = recognitionRequest else {
        fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
    }

    recognitionRequest.shouldReportPartialResults = true
    self.recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in

        var isFinal = false
        if result != nil {

            self.lblText.text = result?.bestTranscription.formattedString
            print(result?.bestTranscription.formattedString)
            print(result?.isFinal)
            isFinal = (result?.isFinal)!
        }
        
        if error != nil || isFinal {

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

            self.recognitionRequest = nil
            self.recognitionTask = nil

            self.btnStart.isEnabled = true
           
        }
    })

    let recordingFormat = inputNode.outputFormat(forBus: 0)
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
        self.recognitionRequest?.append(buffer)
    }
    self.audioEngine.prepare()

    do {
        try self.audioEngine.start()
    } catch {
        print("audioEngine couldn't start because of an error.")
    }
    self.lblText.text = "Say something, I'm listening!"

  }
}
4

2 回答 2

1

据我了解,您希望在用户停止讲话时停止识别。我建议使用 Timer 来跟踪在沉默中度过的时间。var detectionTimer: Timer?在您的 startRecording() 之外添加。和插入resultHandler的内部recognitionTask

self.detectionTimer?.invalidate()
self.detectionTimer = Timer.scheduledTimer(withTimeInterval: 2, repeats: false, block: { (timer) in 
    self.stopRecording() 
})

这样,在每个识别的单词之后,您将启动计时器,如果 2 秒内没有捕获任何内容,它将停止识别。stopRecording 应该看起来像这样

audioEngine.stop()
recognitionRequest?.endAudio()
recognitionRequest = nil
audioEngine.inputNode.removeTap(onBus: 0)
// Cancel the previous task if it's running
if let recognitionTask = recognitionTask {
  recognitionTask.cancel()
  self.recognitionTask = nil
}
于 2020-07-16T14:37:44.593 回答
0

您可以使用计时器来实现此目的。开始播放音频引擎后立即开始计时以识别语音。

  1. 如果语音将被连续识别,则计时器将不断重新启动。
  2. 如果在固定秒数选择器方法将被调用并停止识别后会有静音。

下面是代码 -

func timerReStart() {
        if timer != nil {
            timer?.invalidate()
            timer = nil
        }
        // Change the interval as per the requirement
        timer = Timer.scheduledTimer(timeInterval: 20, target: self, selector: #selector(self.handleTimerValue), userInfo: nil, repeats: false)
    }
    
    @objc func handleTimerValue() {
        cancelRecording()
    }
    
    func timerStop() {
        guard timer != nil else { return }
        timer?.invalidate()
        timer = nil
    }
    
    func startRecording() {
        
        // Clear all previous session data and cancel task
        if recognitionTask != nil {
            recognitionTask?.cancel()
            recognitionTask = nil
        }

        // Create instance of audio session to record voice
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setCategory(AVAudioSession.Category.record, mode: AVAudioSession.Mode.measurement, options: AVAudioSession.CategoryOptions.defaultToSpeaker)
            try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
        } catch {
            print("audioSession properties weren't set because of an error.")
        }

        self.recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

        let inputNode = audioEngine.inputNode

        guard let recognitionRequest = recognitionRequest else {
            fatalError("Unable to create an SFSpeechAudioBufferRecognitionRequest object")
        }

        recognitionRequest.shouldReportPartialResults = true
        self.recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in

            var isFinal = false
            if result != nil {

                self.lblText.text = result?.bestTranscription.formattedString
                print(result?.bestTranscription.formattedString)
                print(result?.isFinal)
                isFinal = (result?.isFinal)!
                self.timerReStart()
            }
            
            if error != nil || isFinal {

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

                self.recognitionRequest = nil
                self.recognitionTask = nil
                self.btnStart.isEnabled = true
                self.timerStop()
            }
            
        })

        let recordingFormat = inputNode.outputFormat(forBus: 0)
        inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer, when) in
            self.recognitionRequest?.append(buffer)
        }
        self.audioEngine.prepare()

        do {
            try self.audioEngine.start()
            //Start timer to check if there is silence
            self.timerReStart()
        } catch {
            print("audioEngine couldn't start because of an error.")
        }
        self.lblText.text = "Say something, I'm listening!"

      }
    }
    
    func cancelRecording() {
       if audioEngine.isRunning {
           let node = audioEngine.inputNode
           node.removeTap(onBus: 0)
           audioEngine.stop()
           recognitionTask?.cancel()
           recognitionTask = nil
       }
       self.timerStop()
   }
于 2020-07-16T15:22:04.777 回答