Как реализовать SFSpeechRecognizationTaskDelegates

Я пытаюсь реализовать преобразование речи в текстовое приложение, я могу записывать звук с микрофона с помощью 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!"

  }
}

2 ответа

Насколько я понимаю, вы хотите остановить распознавание, когда пользователь перестает говорить. Я предлагаю использовать Таймер, чтобы отслеживать время, проведенное в тишине. Добавить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
}

Для этого можно использовать таймер. Начните отсчет времени, как только вы начнете воспроизводить звуковой движок, чтобы распознать речь.

  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()
   }
Другие вопросы по тегам