jphacks/NG_2305

音声認識された文章が保持されない

Closed this issue · 4 comments

問題

音声認識時に話すのを止めてから再び話し始めると、前の文章が保持されずに削除されてしまう。

再現動画

やること

音声認識で得た文章をすべて保持するように修正する。

原因

音声認識の結果を変数へ格納するspeak()において、文字列messageが追加されていくのではなくて都度transcriptへ代入されること。

private func speak(_ message: String) {
    transcript = message
}

対策方法の考察

speak()を次のように変更すれば文字列が追加されていくようになるが、このままだと新たな不具合が発生してしまう。

private func speak(_ message: String) {
    transcript += message    // '='を'+='へ変更
}

request.shouldReportPartialResults = trueにしていると音声認識の結果が途中であっても出力される。
この設定はリアルタイムで音声認識を行うために必要だが、一回の音声認識タスクにおいて一段落つく度に結果が出力されるので、同じ文字列が何度も出力されてしまう。
よって、speak()においてtranscript += messageとしても同じ文字列が追加されていってしまい、解決できない。

対策1

SpeechRecognizerによる音声認識が最終的に確定した段階で出力するようにする。

変更前

途中結果も出力
request.shouldReportPartialResults = true

変更後

最終結果のみ出力
request.shouldReportPartialResults = false

問題

対策1による対策の結果、出力が予想以上に遅くなった。リアルタイムぽさが損なわれる形になってしまっているので、改善が必要。

参考動画

3A6EF523-DAA2-49F1-B7A3-D0023EBBE97E_4_5005_c

やること

出力結果を保持しつつ、なるべく速度も維持

対策案2

speak()において音声認識タスクがひと段落し、以前の文章が削除されたか判定する。messageは変数に逐次保存し、削除判定の際にprv変数に保存する。transcript = prv + messageとすることで過去の文章を保持しつつ、新たな認識はmessageのまま取得することができる。

初期化

private var log_message: String = ""
private var prv: String = ""

speak()

private func speak(_ message: String) {
    if(!message.contains(" ") && log_message != "" && log_message != message){
        prv +=  log_message + " "
    }
    transcript = prv + message
    log_message = message
    print("transcript:",transcript)
}

reset()

func reset() {
    log_message = ""
    prv = ""
    task?.cancel()
    audioEngine?.stop()
    audioEngine = nil
    request = nil
    task = nil
}

注意点

transcript = ""ではリセットできない。prv += log_message + " "transcript = prv + messageがreset後にも影響していると考えられる。