web-dev-qa-db-ja.com

SFSpeechRecognizer-発話の終わりを検出する

IOS 10に組み込まれている音声認識を使用して、小さなプロジェクトをハッキングしています。デバイスのマイクを使用して作業結果を取得しました。私の音声は非常に正確に認識されます。

私の問題は、利用可能なすべての部分文字起こしに対して認識タスクコールバックが呼び出されることです人が話すのを停止したことを検出し、isFinalプロパティをtrueに設定してコールバックを呼び出します。それは起こっていません-アプリは無期限に聞いています。

SFSpeechRecognizerは文末を検出できますか?

ここに私のコードがあります-それはインターネットで見つけられた例に基づいています、それは主にマイクソースから認識するために必要なボイラープレートです。認識taskHintを追加して変更しました。また、shouldReportPartialResultsをfalseに設定しましたが、無視されているようです。

    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
}
19
Tomek Cejner

isFinalフラグは、ユーザーが期待どおりに話をやめたときにtrueにならないようです。 「ユーザーが話をやめた」というイベントは未定義のイベントなので、これはAppleが望まれる動作だと思います。

私はあなたの目標を達成する最も簡単な方法は次のことをすることだと思います:

  • 「沈黙の間隔」を確立する必要があります。つまり、ユーザーがあなたの間隔よりも長い時間話さない場合、彼は話をやめました(つまり、2秒)。

  • _audio session_の先頭にTimerを作成します。

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

  • recognitionTaskinvalidateで新しい文字起こしを取得し、タイマーを再起動したとき

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

  • タイマーが時間切れになった場合、これはユーザーが2秒間通話しないことを意味します。安全にオーディオセッションを停止して終了できます

17
Joe Aspara

IOS10での私のテストに基づいて、shouldReportPartialResultsがfalseに設定されている場合、結果を取得するには60秒待つ必要があります。

3
Zebra

私は現在、アプリ内のテキストに音声を使用しており、それは私にとってはうまくいきます。私のauthenticationTaskブロックは次のとおりです。

recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
        var isFinal = false

        if let result = result, result.isFinal {
            print("Result: \(result.bestTranscription.formattedString)")
            isFinal = result.isFinal
            completion(result.bestTranscription.formattedString, nil)
        }

        if error != nil || isFinal {
            self.audioEngine.stop()
            inputNode.removeTap(onBus: 0)

            self.recognitionRequest = nil
            self.recognitionTask = nil
            completion(nil, error)
        }
    })
1
Alan S