티스토리 뷰
speech to text와 text to speech의 예제입니다.
먼저 Manifest에 권한을 추가해줍니다.
// AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
아래는 권한을 확인하는 코드입니다.
// MainActivity.kt
private val REQUEST_CODE = 1
if (Build.VERSION.SDK_INT >= 23)
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.INTERNET, Manifest.permission.RECORD_AUDIO), REQUEST_CODE)
STT
STT는 두 가지 예제로 준비했습니다.
첫 번째는, onActivityResult를 통해 STT를 받는 전체 코드입니다.
class MainActivity : AppCompatActivity() {
private var speechRecognizer: SpeechRecognizer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// STTButton 클릭시 onActivityResult를 이용한 startSTT() 함수 실행
UseActivityResultSTTButton.setOnClickListener { startSTTUseActivityResult() }
}
// onActivityResult 사용한 예제
private fun startSTTUseActivityResult() {
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this)
val speechRecognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)
//putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
}
startActivityForResult(speechRecognizerIntent, 100)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == 100) {
viewText.text = data?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)!![0]
}
}
override fun onDestroy() {
if (speechRecognizer != null) {
speechRecognizer!!.stopListening()
}
super.onDestroy()
}
}
speechRecognizer에 SpeechRecognizer.createSpeechRecognizer를 통해 현재 context를 넣어주고
speechRecognizerIntent에는 RecognizerIntent의 속성을 넣어주고, packageName과 언어를 선택해줍니다.
언어는 getDefault로 골랐지만 KOREA으로 명시적으로 골라줘도 됩니다.
그리고 startActivityForResult를 통해 speechRecognizerIntent와 requestCode를 보냈습니다.
따라서 onActivityResult를 통해 viewText라는 id를 가진 TextView에 getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)를 통해 값을 가져옵니다.
배열의 0번 값이 제일 정확하므로 0번 배열의 값을 가져옵니다.
두 번째로, RecognitionListener를 사용한 STT 전체 코드입니다.
class MainActivity : AppCompatActivity() {
private var speechRecognizer: SpeechRecognizer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// STTButton 클릭시 startSTT() 함수 실행
STTButton.setOnClickListener { startSTT() }
}
// RecognitionListener 사용한 예제
private fun startSTT() {
val speechRecognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
}
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this).apply {
setRecognitionListener(recognitionListener())
startListening(speechRecognizerIntent)
}
}
private fun recognitionListener() = object : RecognitionListener {
override fun onReadyForSpeech(params: Bundle?) = Toast.makeText(this@MainActivity, "음성인식 시작", Toast.LENGTH_SHORT).show()
override fun onRmsChanged(rmsdB: Float) {}
override fun onBufferReceived(buffer: ByteArray?) {}
override fun onPartialResults(partialResults: Bundle?) {}
override fun onEvent(eventType: Int, params: Bundle?) {}
override fun onBeginningOfSpeech() {}
override fun onEndOfSpeech() {}
override fun onError(error: Int) {
when(error) {
SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> Toast.makeText(this@MainActivity, "퍼미션 없음", Toast.LENGTH_SHORT).show()
}
}
override fun onResults(results: Bundle) {
viewText.text = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)!![0]
}
}
override fun onDestroy() {
if (speechRecognizer != null) {
speechRecognizer!!.stopListening()
}
super.onDestroy()
}
}
전체 코드 구조는 첫 번째 코드와 비슷하지만 speechRecognizer에 SpeechRecognizer.createSpeechRecognizer를 통해 현재 context를 넣을 뿐만 아니라 setRecognitionListener로 RecognitionListener를 선언한 함수를 넣어주고 startListening에 speechRecognizerIntent를 넣습니다.
위와 같이 함수로 선언하여 넣어도 되고 아래와 같이 변수로 선언해서 넣어도 됩니다.
private fun startSTT() {
...
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this).apply {
setRecognitionListener(recognitionListener)
startListening(speechRecognizerIntent)
}
}
private val recognitionListener = object : RecognitionListener {
...
}
RecognitionListener 안에 오버라이드된 함수들의 역할은 아래 문서를 확인하면 됩니다.
https://developer.android.com/reference/android/speech/RecognitionListener
결과적으로 onResults를 통해 값을 받아오면 됩니다.
TTS
TTS의 전체 코드이다.
class MainActivity : AppCompatActivity(), TextToSpeech.OnInitListener {
private var tts: TextToSpeech? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// tts에 TextToSpeech 값 넣어줌
tts = TextToSpeech(this, this)
// TTSButton 클릭시 startTTS() 함수 실행
TTSButton.setOnClickListener { startTTS() }
}
// TTS 예제
private fun startTTS() {
tts!!.speak(viewText.text.toString(), TextToSpeech.QUEUE_FLUSH, null, "")
}
// TextToSpeech override 함수
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
// set US English as language for tts
val result = tts!!.setLanguage(Locale.KOREA)
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
//doSomething
} else {
//doSomething
}
} else {
//doSomething
}
}
override fun onDestroy() {
if (tts != null) {
tts!!.stop()
tts!!.shutdown()
}
super.onDestroy()
}
}
전체 예제 코드
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text=""
android:id="@+id/viewText" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginTop="30dp">
<Button
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="STT"
android:id="@+id/STTButton"/>
<Button
android:layout_width="150dp"
android:layout_height="wrap_content"
android:text="TTS"
android:id="@+id/TTSButton"/>
</LinearLayout>
<Button
android:layout_width="250dp"
android:layout_height="wrap_content"
android:text="STT(activityResult 사용)"
android:id="@+id/UseActivityResultSTTButton"/>
</androidx.appcompat.widget.LinearLayoutCompat>
MainActivity.kt
class MainActivity : AppCompatActivity(), TextToSpeech.OnInitListener {
private var tts: TextToSpeech? = null
private var speechRecognizer: SpeechRecognizer? = null
private val REQUEST_CODE = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// permission 확인
if (Build.VERSION.SDK_INT >= 23)
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.INTERNET, Manifest.permission.RECORD_AUDIO), REQUEST_CODE)
// tts에 TextToSpeech 값 넣어줌
tts = TextToSpeech(this, this)
// TTSButton 클릭시 startTTS() 함수 실행
TTSButton.setOnClickListener { startTTS() }
// STTButton 클릭시 onActivityResult를 이용한 startSTT() 함수 실행
UseActivityResultSTTButton.setOnClickListener { startSTTUseActivityResult() }
// STTButton 클릭시 startSTT() 함수 실행
STTButton.setOnClickListener { startSTT() }
}
// RecognitionListener 사용한 예제
private fun startSTT() {
val speechRecognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
}
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this).apply {
setRecognitionListener(recognitionListener())
startListening(speechRecognizerIntent)
}
}
private fun recognitionListener() = object : RecognitionListener {
override fun onReadyForSpeech(params: Bundle?) = Toast.makeText(this@MainActivity, "음성인식 시작", Toast.LENGTH_SHORT).show()
override fun onRmsChanged(rmsdB: Float) {}
override fun onBufferReceived(buffer: ByteArray?) {}
override fun onPartialResults(partialResults: Bundle?) {}
override fun onEvent(eventType: Int, params: Bundle?) {}
override fun onBeginningOfSpeech() {}
override fun onEndOfSpeech() {}
override fun onError(error: Int) {
when(error) {
SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> Toast.makeText(this@MainActivity, "퍼미션 없음", Toast.LENGTH_SHORT).show()
}
}
override fun onResults(results: Bundle) {
viewText.text = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION)!![0]
}
}
// onActivityResult 사용한 예제
private fun startSTTUseActivityResult() {
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this)
val speechRecognizerIntent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, packageName)
//putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
}
startActivityForResult(speechRecognizerIntent, 100)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == 100) {
viewText.text = data?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)!![0]
}
}
// TTS 예제
private fun startTTS() {
tts!!.speak(viewText.text.toString(), TextToSpeech.QUEUE_FLUSH, null, "")
}
// TextToSpeech override 함수
override fun onInit(status: Int) {
if (status == TextToSpeech.SUCCESS) {
// set US English as language for tts
val result = tts!!.setLanguage(Locale.KOREA)
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
//doSomething
} else {
//doSomething
}
} else {
//doSomething
}
}
override fun onDestroy() {
if (tts != null) {
tts!!.stop()
tts!!.shutdown()
}
if (speechRecognizer != null) {
speechRecognizer!!.stopListening()
}
super.onDestroy()
}
}
예제 코드
https://github.com/Im-Tae/Blog_Example/tree/master/Android/Android_STT_TTS_Example
'알려주는 이야기 > 안드로이드' 카테고리의 다른 글
안드로이드 구글 지도 사용하기 - 1 [구글 지도 띄우기] (0) | 2020.06.06 |
---|---|
코틀린 DataBinding 예제 (0) | 2020.05.04 |
안드로이드 SharedPreference에 Json값 저장 (0) | 2020.04.25 |
안드로이드 4대 컴포넌트 (0) | 2020.01.20 |
간단한 Toast 메시지 배우기 (0) | 2019.08.13 |