App 接入 Google TextToSpeech

1,463 阅读2分钟

一、关于 TextToSpeech

Speech Recognition & Synthesis 是来自 Google 的语音识别和合成应用程序提供了文本到语音的功能,通过 TextToSpeech 机制,任意 App 都可以方便地采用系统内置或第三方提供的 TTS Engine 进行播放铃声提示、语音提示的请求

默认 TTS Engine 可以在设备设置中手动更改:设置 -> 语言和输入法 -> 文字转语音(TTS)输出 -> 首选引擎,也可由 App 具体指定偏好的目标 Engine 来完成。

二、TTS 实现方案

实现TTS有大体上有两种方案:

  • 1.使用系统内置的TTS

    • 优点:集成简单,免费,Google语音引擎对于外语支持友好,中文也还不错
    • 缺点:扩展性相对来说低一点,只用于语音合成(文字转语音),需要设备安装语音引擎并在系统设置中设置默认
  • 2.集成第三方的SDK如百度语音、讯飞语音等

    • 优点:随应用一起部署,功能可扩展性强(语音合成,语音听写,唤醒词)
    • 缺点:集成相对来说复杂,收费,国际化问题,国内的一些语音方案目前对于外语的支持并不是很好

可能遇到的问题

Android11 软件包可见性问题导致 TextToSpeech 初始化失败

  • 解决办法:增加权限
... 
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<queries>
      <intent>
         <action android:name="android.intent.action.TTS_SERVICE" />
      </intent>
</queries>
 
<application ...

三、代码实现

/**
 * GoogleTts 工具类
 * Created by RoyYao on 2024/7/2
 */
class GoogleTtsUtil {
    private lateinit var textToSpeech: TextToSpeech

    companion object {
        val instance = InstanceHelper.instance
        const val TAG: String = "GoogleTtsUtil"
    }

    private object InstanceHelper {
        val instance = GoogleTtsUtil()
    }

    /**
     * 初始化 TTS
     */
    fun init(context: Context) {
        textToSpeech = TextToSpeech(context, { status: Int ->
            Log.i(TAG, "status: $status")
            if (status == TextToSpeech.SUCCESS) {
                //初始化成功
                Log.i(TAG, "init success")
                //获取支持的语言列表
                val supportedLocales =
                    textToSpeech.availableLanguages
                for (locale in supportedLocales) {
                    Log.i(TAG, "Supported Language$locale")
                }
//                //设置音调
//                textToSpeech.setPitch(1f)
//                //设置语速,1.0为正常语速
//                textToSpeech.setSpeechRate(1f)
                // 默认英语
                setLanguage(Locale.ENGLISH)
            } else {
                Log.i(TAG, "init fail")
            }
        }, "com.google.android.tts")
    }
    
    /**
     * 设置语言
     */
    private fun setLanguage(loc: Locale) {
        val result = textToSpeech.setLanguage(loc)
        if (result != TextToSpeech.LANG_COUNTRY_AVAILABLE
            && result != TextToSpeech.LANG_AVAILABLE
        ) {
            Log.e(TAG, "TTS暂时不支持这种语音的朗读!")
        }
    }

    fun speak(content: String, callBack: TtsCallBack? = null) {
        mTime = System.currentTimeMillis()
        val speechResult = textToSpeech.speak(
            content,
            TextToSpeech.QUEUE_FLUSH,
            null,
            System.currentTimeMillis().toString()
        )
        Log.i(TAG, "speechResult = $speechResult")

        textToSpeech.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
            override fun onStart(p0: String?) {
            }

            override fun onDone(p0: String?) {
                callBack?.onCompleted()
            }

            override fun onError(p0: String?) {
            }
        })
    }

    fun isSpeaking(): Boolean {
        return textToSpeech.isSpeaking
    }

    fun stopSpeaking() {
        textToSpeech.stop()
    }
}

四、使用

        // 应用启动时初始化
        GoogleTtsUtil.instance.init(context)
        // 需要使用的地方调用
        GoogleTtsUtil.instance.speak("需要合成的内容")

参考资料