Kotlin으로 작성된 RecognitionListener를 사용하는 프로젝트가 있습니다. 음성-텍스트 기능은 항상 성공했으며 아무런 문제도 없었습니다.
지난주부터 onResult 함수가 두 번 호출되기 시작했습니다. 프로젝트가 변경되지 않았습니다. 몇 달 전부터 이전 버전의 프로젝트를 테스트했는데 동일한 문제가있었습니다.
세 가지 경우가 있습니다.
- 작은 텍스트 (1-8 단어) 및 SpeechRecognizer가 자동으로 중지됩니다.-> onResult ()가 두 번 호출됩니다.
- 큰 텍스트 (9 단어 이상) 및 SpeechRecognizer가 자동으로 중지됩니다.-> 정상적인 동작 (onResult ()가 한 번 호출 됨);
- 모든 코드 크기 및 SpeechRecognizer stopListening () 함수는 수동으로 (코드에서)-> 정상 동작으로 호출됩니다.
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()
}
listen (), endListening () 및 cancelListening ()은 모두 버튼에서 호출됩니다.
나는 같은 문제를 겪고 있으며 문제는 api 9가있는 Samsung s8에서만 발생합니다. 여기서 인식이 진행 중일 때 부분 결과도 볼 수 있습니다. 구형 장치에서는 이것을 경험하지 못합니다.
—
marcinj
Android 7 이상에서이 문제를 확인했습니다. 프로젝트도 변경하지 않았습니다.
—
페드로 앙리 케 플로레스
"문제는 api 9를 사용하는 Samsung s8에만 있습니다."– 필자가 보유한 장치에 대한 테스트에서 의미
—
marcinj
Pocophone F1에서 동일한 문제, 내 솔루션은 결과가 동일한 지 확인한 다음 두 번째 결과가 무시되는 경우 무시했습니다
—
Lotan
이것은 어제 내 앱 중 하나에서 발생하기 시작했습니다. 코드를 한 번만 실행할 수 있도록 부울을 추가했지만 갑자기 왜 이렇게 시작했는지에 대한 설명을 원합니다. 업데이트가 있습니까?
—
개빈 라이트