---
# System prepended metadata

title: TextToSpeech
tags: [Android, Kotlin]

---

###### tags: `Android` `Kotlin`
# TextToSpeech
本文紀錄著如何使用 ==TextToSpeech==

TextToSpeech 是 Android 在 API 4 提供的文本朗讀套件，能將指定文字轉換成語音並朗讀
而且還能將文本對應的音頻錄製成檔案並儲存

## 檢查語音模型
有些手機預設可能沒有安裝其他語言的語音模型
此時要進行檢查，並帶使用者前往設定的地方下載語音模型
```kotlin=
private fun isLanguageAvailable(locale: Locale): Boolean {
    val status = speaker.isLanguageAvailable(locale)
    val isAvailable = !(status == TextToSpeech.LANG_MISSING_DATA || status == TextToSpeech.LANG_NOT_SUPPORTED)

    if (!isAvailable) {
        val installIntent = Intent()
        installIntent.action = TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA
        startActivity(installIntent)
    }

    return isAvailable
}
```

https://stackoverflow.com/questions/5913188/missing-languages-in-tts-android

## 顯示語音資料
```kotlin=
private fun showInfo() {
    if (!::speaker.isInitialized) return

    //語音引擎資訊
    speaker.engines.forEach {
        Log.e("engine", "name:${it.name}, label:${it.label}")
    }

    //目前語音資訊
    Log.e("voice", "name:${speaker.voice.name}, " +
        "language:${speaker.voice.locale.language}, " +
        "country: ${speaker.voice.locale.country}")
}
```

## 使用方式
```kotlin=
private lateinit var speaker: TextToSpeech

private fun speakText(text: String, language: String) {
    if (::speaker.isInitialized)
        speaker.speak(text, TextToSpeech.QUEUE_FLUSH,null, "0")
    else {
        speaker = TextToSpeech(this, TextToSpeech.OnInitListener {
            when (it) {
                TextToSpeech.SUCCESS -> {
                    val locale = with(language) {
                        when {
                            contains("en") -> Locale.US
                            else -> Locale.TRADITIONAL_CHINESE
                        }
                    }

                    //檢查裝置是否有該語言的語音資料
                    if (!isLanguageAvailable(locale)) return@OnInitListener
                    
                    //設定朗讀語言
                    speaker.language = locale

                    //設定語速
                    speaker.setSpeechRate(0.8f)

                    //若正在念其他的內容，就直接刷掉
                    speaker.speak(text, TextToSpeech.QUEUE_FLUSH,null, "0")

                    //顯示語音資訊
                    showInfo()
                }
                TextToSpeech.ERROR -> {
                    Toast.makeText(this, "無法進行語音播放，請確保網路連線正常", Toast.LENGTH_SHORT).show()
                }
            }
        })
    }
}

private fun isLanguageAvailable(locale: Locale): Boolean {
    val status = speaker.isLanguageAvailable(locale)
    val isAvailable = !(status == TextToSpeech.LANG_MISSING_DATA || status == TextToSpeech.LANG_NOT_SUPPORTED)

    if (!isAvailable) {
        val installIntent = Intent()
        installIntent.action = TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA
        startActivity(installIntent)
    }

    return isAvailable
}

private fun showInfo() {
    if (!::speaker.isInitialized) return

    //語音引擎資訊
    speaker.engines.forEach {
        Log.e("engine", "name:${it.name}, label:${it.label}")
    }

    //目前語音資訊
    Log.e("voice", "name:${speaker.voice.name}, " +
            "language:${speaker.voice.locale.language}, " +
            "country: ${speaker.voice.locale.country}")
}

override fun onDestroy() {
    if (::speaker.isInitialized) {
        speaker.stop() //停止朗讀
        speaker.shutdown() //回收
    }
    super.onDestroy()
}
```

## 參考文章
[Android 自動朗讀（TTS）實現](https://blog.csdn.net/tracydragonlxy/article/details/78200382)
[官方文件](https://developer.android.com/reference/android/speech/tts/TextToSpeech)
[官方部落格介紹](https://android-developers.googleblog.com/2009/09/introduction-to-text-to-speech-in.html?m=1)
[Android TextToSpeech 使用指南](https://enderhoshi.github.io/2019/11/25/Android%20TextToSpeech%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/)

## 未完成項目
- 音頻轉檔案儲存