Android RecognitionListener: onResults được gọi hai lần


10

Tôi có một dự án sử dụng RecognitionListener được viết bằng Kotlin. Chức năng chuyển lời nói thành văn bản luôn thành công và không bao giờ có bất kỳ vấn đề nào.

Kể từ tuần trước, chức năng onResult của nó bắt đầu được gọi hai lần. Không có thay đổi được thực hiện trên dự án. Tôi đã thử nghiệm các phiên bản cũ của dự án (từ vài tháng trước) và những phiên bản này có cùng một vấn đề.

Có ba trường hợp khác nhau:

  1. Văn bản nhỏ (1 đến 8 từ) và SpeechRecognizer bị dừng tự động -> onResult () được gọi hai lần;
  2. Văn bản lớn (9 từ trở lên) và SpeechRecognizer bị dừng tự động -> Hành vi bình thường (onResult () được gọi một lần);
  3. Bất kỳ kích thước văn bản và hàm SpeechRecognizer stopListening () được gọi thủ công (từ mã) -> Hành vi bình thường.

Dưới đây là mã lớp chuyển lời nói thành văn bản VoiceRecognition:

class VoiceRecognition(private val activity: Activity, language: String = "pt_BR") : RecognitionListener {

    private val AudioLogTag = "AudioInput"

    var voiceRecognitionIntentHandler: VoiceRecognitionIntentHandler? = null
    var voiceRecognitionOnResultListener: VoiceRecognitionOnResultListener? = null //Must have this
    var voiceRecognitionLayoutChanger: VoiceRecognitionLayoutChanger? = null

    var isListening = false

    private val intent: Intent
    private var speech: SpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(activity)

    init {
        speech.setRecognitionListener(this)

        intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
        intent.putExtra(
            RecognizerIntent.EXTRA_LANGUAGE_MODEL,
            RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
        )
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language)
    }

    //It is important to put this function inside a clickListener
    fun listen(): Boolean {
        if (ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.RECORD_AUDIO), 1)
            return false
        }

        speech.startListening(intent)

        Log.i(AudioLogTag, "startListening")

        return true
    }

    //Use this if you want to stop listening but still get recognition results
    fun endListening(){
        Log.i(AudioLogTag, "stopListening")

        speech.stopListening()
        isListening = false
    }

    fun cancelListening(){
        Log.i(AudioLogTag, "cancelListening")

        speech.cancel()
        voiceRecognitionLayoutChanger?.endListeningChangeLayout()
        isListening = false
    }

    override fun onReadyForSpeech(p0: Bundle?) {
        Log.i(AudioLogTag, "onReadyForSpeech")

        voiceRecognitionLayoutChanger?.startListeningChangeLayout()
        isListening = true
    }

    override fun onRmsChanged(p0: Float) {
//        Log.i(AudioLogTag, "onRmsChanged: $p0")
//        progressBar.setProgress((Int) p0)
    }

    override fun onBufferReceived(p0: ByteArray?) {
        Log.i(AudioLogTag, "onBufferReceived: $p0")
    }

    override fun onPartialResults(p0: Bundle?) {
        Log.i(AudioLogTag, "onPartialResults")
    }

    override fun onEvent(p0: Int, p1: Bundle?) {
        Log.i(AudioLogTag, "onEvent")
    }

    override fun onBeginningOfSpeech() {
        Log.i(AudioLogTag, "onBeginningOfSpeech")
    }

    override fun onEndOfSpeech() {
        Log.i(AudioLogTag, "onEndOfSpeech")

        voiceRecognitionLayoutChanger?.endListeningChangeLayout()
        isListening = false
    }

    override fun onError(p0: Int) {
        speech.cancel()
        val errorMessage = getErrorText(p0)
        Log.d(AudioLogTag, "FAILED: $errorMessage")
        voiceRecognitionLayoutChanger?.endListeningChangeLayout()
        isListening = false
    }

    override fun onResults(p0: Bundle?) {

        val results: ArrayList<String> = p0?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) as ArrayList<String>

        Log.i(AudioLogTag, "onResults -> ${results.size}")

        val voiceIntent: Int? = voiceRecognitionIntentHandler?.getIntent(results[0])
        if (voiceIntent != null && voiceIntent != 0) {
            voiceRecognitionIntentHandler?.handle(voiceIntent)
            return
        }

        voiceRecognitionOnResultListener!!.onResult(results[0])
    }

    private fun getErrorText(errorCode: Int): String {
        val message: String
        when (errorCode) {
            SpeechRecognizer.ERROR_AUDIO -> message = "Audio recording error"
            SpeechRecognizer.ERROR_CLIENT -> message = "Client side error"
            SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> message = "Insufficient permissions"
            SpeechRecognizer.ERROR_NETWORK -> message = "Network error"
            SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> message = "Network timeout"
            SpeechRecognizer.ERROR_NO_MATCH -> message = "No match"
            SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> message = "RecognitionService busy"
            SpeechRecognizer.ERROR_SERVER -> message = "Error from server"
            SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> message = "No speech input"
            else -> message = "Didn't understand, please try again."
        }
        return message
    }

    //Use it in your overriden onPause function.
    fun onPause() {
        voiceRecognitionLayoutChanger?.endListeningChangeLayout()
        isListening = false

        speech.cancel()
        Log.i(AudioLogTag, "pause")
    }

    //Use it in your overriden onDestroy function.
    fun onDestroy() {
        speech.destroy()
    }

lắng nghe (), endListening () và CancListening () đều được gọi từ một nút.


Tôi đang gặp vấn đề tương tự, vấn đề chỉ xảy ra với Samsung s8 với api 9 - ở đây tôi cũng có thể thấy kết quả một phần khi quá trình nhận dạng đang được tiến hành. Trên các thiết bị cũ hơn tôi không trải nghiệm điều này.
marcinj

Tôi đã thấy vấn đề này từ Android 7 trở lên ... Tôi thậm chí không thay đổi dự án của mình .. nó mới bắt đầu xảy ra.
Pedro Henrique Flores

"Vấn đề chỉ xảy ra với Samsung s8 với api 9" - điều đó có nghĩa là trong các thử nghiệm của tôi trên các thiết bị tôi có
marcinj

1
cùng một vấn đề trên Pocophone F1, giải pháp của tôi là kiểm tra xem kết quả có giống nhau không, sau đó bỏ qua kết quả thứ hai nếu chúng là
Lotan

Điều này chỉ bắt đầu xảy ra trong một trong những ứng dụng của tôi ngày hôm qua. Tôi đã thêm một boolean để cho phép mã chỉ thực thi một lần, nhưng tôi thích một lời giải thích về lý do tại sao nó đột nhiên bắt đầu làm điều này. Bất cứ cập nhật?
Gavin Wright

Câu trả lời:



1

Điều này chỉ bắt đầu xảy ra trong một trong những ứng dụng của tôi ngày hôm qua. Tôi đã thêm một boolean để cho phép mã chỉ thực thi một lần, nhưng tôi thích một lời giải thích về lý do tại sao nó đột nhiên bắt đầu làm điều này. Bất cứ cập nhật?


0

Tôi đã có cùng một vấn đề và tôi vừa thêm một cờ boolean trong mã của mình, nhưng tất nhiên đó là một giải pháp tạm thời và tôi không biết nguồn gốc của vấn đề này.

object : RecognitionListener {

        var singleResult = true

        override fun onResults(results: Bundle?) {
            if (singleResult) {
                results?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).let {
                    // do something with result
                }
                // next result will be ignored
                singleResult = false
            }
        }
    }

Vui lòng thêm một số mã ví dụ.
m02ph3u5
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.