하루에 0.01%라도 성장하자

Develop/Android

Android API로 STT, TTS 구현하기

뚠님 2022. 7. 21. 18:14
반응형

STT (  Speach To Text )

TTS ( Text To Speach )

 

즉 사용자의 음성을 인식해서 텍스트로 표기하거나

텍스트를 인식해서 음성으로 말해주는 기술을 뜻한다.

 

놀랍게도 안드로이드에서 기본 API로 이 기술을 지원하고 있다.

( 더 놀랍게도 기본 제공이라는 것에 비해 안정적이다. - 개인적인 생각 - )

 

거두 절미 하고 작성해 보자

 

STT

 

버튼을 누르거나 특정 이벤트가 발생한 시점에 해당 Function을 실행하면 음성 인식을 시작한다.

private fun startVoiceRecording() {
        val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
            putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)
            putExtra(RecognizerIntent.EXTRA_LANGUAGE, "ko-KR")
        }

        speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this@MainActivity)
        speechRecognizer.setRecognitionListener(recognitionListener)
        speechRecognizer.startListening(intent)
    }
    
private val recognitionListener: RecognitionListener = object : RecognitionListener {
        override fun onReadyForSpeech(params: Bundle?) {
            Toast.makeText(applicationContext, "음성인식 시작", Toast.LENGTH_SHORT).show()
        }

        override fun onBeginningOfSpeech() {
        }

        override fun onRmsChanged(rmsdB: Float) {
        }

        override fun onBufferReceived(buffer: ByteArray?) {
        }

        override fun onEndOfSpeech() {
        }

        override fun onError(error: Int) {
            val message = when (error) {
                SpeechRecognizer.ERROR_AUDIO -> "오디오 에러"
                SpeechRecognizer.ERROR_CLIENT -> "클라이언트 에러"
                SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> "퍼미션 없음"
                SpeechRecognizer.ERROR_NETWORK -> "네트워크 에러"
                SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> "네트웍 타임아웃"
                SpeechRecognizer.ERROR_NO_MATCH -> "찾을 수 없음"
                SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> "RECOGNIZER 가 바쁨"
                SpeechRecognizer.ERROR_SERVER -> "서버가 이상함"
                SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> "말하는 시간초과"
                else -> "알 수 없는 오류임"
            }
            Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT).show()
        }

        override fun onResults(results: Bundle?) {
            val matches = results?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
            recodeStr = "" // 음성인식을 두번 연속 할 때 기존 인식된 텍스트를 초기화 하는 코드
            for (i in matches!!.indices) recodeStr += matches[i]
            Log.d("TEXT", "$recodeStr")
        }

        override fun onPartialResults(partialResults: Bundle?) {
        }

        override fun onEvent(eventType: Int, params: Bundle?) {
        }
    }

 

보면 음성인식 intent를 만들고 해당 실행하기 전에 listener를 만들어 붙여준 후 스타트를 한다.

 

음성인식이 성공적으로 완료되면 onResults 로 result 값이 떨어지고, 해당 값을 파싱하여 String  형태로 가져올 수 있다!

 

이것이 바로 STT.

 

TTS

    private lateinit var tts: TextToSpeech
    private fun initTTS() {
        tts = TextToSpeech(this, textToSpeechListener)
    }

    private val textToSpeechListener: TextToSpeech.OnInitListener = TextToSpeech.OnInitListener {
        if(isFirst) {
            isFirst = false
            return@OnInitListener
        }
        if (it == TextToSpeech.SUCCESS) {
            val result = tts.setLanguage(Locale.KOREA)
            if (result == TextToSpeech.LANG_NOT_SUPPORTED || result == TextToSpeech.LANG_MISSING_DATA) {
            	// 지원하지 않는 언어거나, 없는 언어일때 
            } else {
                // 정상 인식 되었을 때 실행
            }
        }
    }

TextToSpeach 를 선언하고 생성한다.

 

여기도 동일하게 Listener를 만들어서 TextToSpeach를 만들고 리스너를 붙여준다.

 

private fun speakOut() {
        tts.setPitch(1F)
        tts.setSpeechRate(1F)
        tts.speak("아뇽하세요!.", TextToSpeech.QUEUE_ADD, null, "id1")
    }

 

이후 해당 함수를 실행해서 음성으로 소리가 나오도록 한다.

pitch는 목소리 톤, Rate는 목소리 재생 속도다. 

생각보다 너무 쉽다. 역시... 구글

반응형