2017-03-01 1 views
7

Je pirate un petit projet en utilisant la reconnaissance vocale intégrée iOS 10. J'ai des résultats de travail en utilisant le microphone de l'appareil, mon discours est reconnu très précisément.SFSpeechRecognizer - détecter la fin de l'énoncé

Mon problème est que le rappel des tâches de reconnaissance est appelée pour chaque transcription partielle disponible, et je veux qu'il détecter personne ne parle plus et appeler la fonction de rappel avec isFinal la propriété est définie sur true. Cela n'arrive pas - l'application écoute indéfiniment.

Est-ce que SFSpeechRecognizer est capable de détecter la fin d'une phrase?

Voici mon code - il est basé sur l'exemple trouvé sur les Internets, c'est surtout un passe-partout nécessaire à reconnaître à partir de la source du microphone. Je l'ai modifié en ajoutant la reconnaissance taskHint. J'ai également mis shouldReportPartialResults à faux, mais il semble qu'il a été ignoré.

func startRecording() { 

    if recognitionTask != nil { 
     recognitionTask?.cancel() 
     recognitionTask = nil 
    } 

    let audioSession = AVAudioSession.sharedInstance() 
    do { 
     try audioSession.setCategory(AVAudioSessionCategoryRecord) 
     try audioSession.setMode(AVAudioSessionModeMeasurement) 
     try audioSession.setActive(true, with: .notifyOthersOnDeactivation) 
    } catch { 
     print("audioSession properties weren't set because of an error.") 
    } 

    recognitionRequest = SFSpeechAudioBufferRecognitionRequest() 
    recognitionRequest?.shouldReportPartialResults = false 
    recognitionRequest?.taskHint = .search 

    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 { 
      print("RECOGNIZED \(result?.bestTranscription.formattedString)") 
      self.transcriptLabel.text = result?.bestTranscription.formattedString 
      isFinal = (result?.isFinal)! 
     } 

     if error != nil || isFinal { 
      self.state = .Idle 

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

      self.recognitionRequest = nil 
      self.recognitionTask = nil 

      self.micButton.isEnabled = true 

      self.say(text: "OK. Let me see.") 
     } 
    }) 

    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.") 
    } 

    transcriptLabel.text = "Say something, I'm listening!" 

    state = .Listening 
} 

Répondre

8

Il semble que isFinal drapeau ne devient vrai lorsque cesse l'utilisateur de parler comme prévu. Je suppose que c'est un comportement recherché par Apple, car l'événement "L'utilisateur arrête de parler" est un événement indéfini.

Je crois que la meilleure façon d'atteindre votre objectif est de faire ce qui suit:

  • Vous avez à estabilish un « intervalle de silence ». Cela signifie que si l'utilisateur ne parle pas pendant une durée supérieure à votre intervalle, il a cessé de parler (c'est-à-dire 2 secondes).

  • Créer une minuterie au début du audio session:

var timer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "didFinishTalk", userInfo: nil, repeats: false)

  • lorsque vous obtenez de nouvelles transcriptions dans recognitionTask invalidate et redémarrez votre minuterie

    timer.invalidate() timer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: "didFinishTalk", userInfo: nil, repeats: false)

  • si le temporisateur expire, cela signifie que l'utilisateur ne parle pas depuis 2 secondes. Vous pouvez arrêter en toute sécurité Session audio et quitter

+0

Pourquoi Apple trouvé ce tuf? Seulement besoin de mettre en œuvre la méthode déléguée utile. – Ganesh