와챠의 우당탕탕 코딩 일기장

[Android/Kotlin]음성인식(STT:Speech-To-Text) 만들기 본문

코딩 일기장/Android(Kotlin)

[Android/Kotlin]음성인식(STT:Speech-To-Text) 만들기

minWachya 2022. 4. 21. 15:12
반응형

오늘은 Android Studio로 음성인식 기능을 만들어 보려고 한다

왜냐

그냥 궁금함

 

만들어보니까 너무나 쉽고 간단...


결과 화면

 

1. Manifest에 권한 + intent 추가

<!--인터넷 권한-->
<uses-permission android:name="android.permission.INTERNET" />
<!--오디오 사용 권한-->
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<queries>
   <intent>
        <action android:name="android.speech.RecognitionService" />
   </intent>
 </queries>

 

2. xml 코드짜기

대충 아래 꺼만 만듦

  • 말하기 버튼
  • 말한 내용을 보여줄 TextView
  • 음성인식 상태 TextView

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="아래 버튼을 눌러 음성인식 시작"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnSpeech"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="말하기"
        android:textSize="18sp"
        android:backgroundTint="@color/purple_200"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <TextView
        android:id="@+id/tvState"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="상태 체크"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnSpeech" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

3. kt 코드 짜기

설명은 주석에!~

package com.example.mystt

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.speech.RecognitionListener
import android.speech.RecognizerIntent
import android.speech.SpeechRecognizer
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.example.mystt.databinding.ActivityMainBinding

private lateinit var binding: ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var speechRecognizer: SpeechRecognizer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        // 권한 설정
        requestPermission()

        // RecognizerIntent 생성
        val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
        intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)    // 여분의 키
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "ko-KR")         // 언어 설정

        // <말하기> 버튼 눌러서 음성인식 시작
        binding.btnSpeech.setOnClickListener {
            // 새 SpeechRecognizer 를 만드는 팩토리 메서드
            speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this@MainActivity)
            speechRecognizer.setRecognitionListener(recognitionListener)    // 리스너 설정
            speechRecognizer.startListening(intent)                         // 듣기 시작
        }

    }

    // 권한 설정 메소드
    private fun requestPermission() {
        // 버전 체크, 권한 허용했는지 체크
        if (Build.VERSION.SDK_INT >= 23 &&
            ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.RECORD_AUDIO)
            != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(this@MainActivity,
                arrayOf(Manifest.permission.RECORD_AUDIO), 0)
        }
    }

    // 리스너 설정
    private val recognitionListener: RecognitionListener = object : RecognitionListener {
        // 말하기 시작할 준비가되면 호출
        override fun onReadyForSpeech(params: Bundle) {
            Toast.makeText(applicationContext, "음성인식 시작", Toast.LENGTH_SHORT).show()
            binding.tvState.text = "이제 말씀하세요!"
        }
        // 말하기 시작했을 때 호출
        override fun onBeginningOfSpeech() {
            binding.tvState.text = "잘 듣고 있어요."
        }
        // 입력받는 소리의 크기를 알려줌
        override fun onRmsChanged(rmsdB: Float) {}
        // 말을 시작하고 인식이 된 단어를 buffer에 담음
        override fun onBufferReceived(buffer: ByteArray) {}
        // 말하기를 중지하면 호출
        override fun onEndOfSpeech() {
            binding.tvState.text = "끝!"
        }
        // 오류 발생했을 때 호출
        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 -> "알 수 없는 오류임"
            }
            binding.tvState.text = "에러 발생: $message"
        }
        // 인식 결과가 준비되면 호출
        override fun onResults(results: Bundle) {
            // 말을 하면 ArrayList에 단어를 넣고 textView에 단어를 이어줌
            val matches = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)
            for (i in matches!!.indices) binding.textView.text = matches[i]
        }
        // 부분 인식 결과를 사용할 수 있을 때 호출
        override fun onPartialResults(partialResults: Bundle) {}
        // 향후 이벤트를 추가하기 위해 예약
        override fun onEvent(eventType: Int, params: Bundle) {}
    }
}

 

전체 코드(위에가 전부이긴 함)

https://github.com/minWachya/MySTT

 

GitHub - minWachya/MySTT: 음성인식 STT(Speech To Text)

음성인식 STT(Speech To Text). Contribute to minWachya/MySTT development by creating an account on GitHub.

github.com


성능

성능은 그닥 좋지 않다고는 하지만... 응?? 잘 모르겠음 기본적인 건 잘 알아 들음

음성인식은 '훠궈'를 인식 못 한다고 해서ㅋㅋ 해봤는데

진짜 못함

음성 인식은 더 발전해야 하는듯

 

상세 결과 화면

 

권한 화면
버튼 누른 후 화면

 

말하는 중 화면

 

음성인식 끝난 화면


참고

https://hanyeop.tistory.com/128

 

[Android] 안드로이드 스튜디오 음성인식 사용하기 구글 STT (Speech-to-Text)

안드로이드에서는 android.speech를 통해 음성지원을 지원해준다. 사용방법 AndroidManifest 에 오디오,인터넷 권한을 추가해준다. xml을 원하는 방식대로 만들어준다. public class MainActivity extends AppCo..

hanyeop.tistory.com

https://jwsoft91.tistory.com/160

 

[Kotlin]  STT  (Speech-to-Text)

구글 STT (Speech-to-Text) AndroidManifest.xml activity_main.xml <?xml version="1.0" encoding="utf-8"?> MainActivity.kt package com.jwsoft.kotlinproject import android.Manifest import android.conten..

jwsoft91.tistory.com

 

반응형
Comments