[Android/Kotlin]音声の読み上げ

目次

概要

指定した文字列の音声出力を行う。
大部分が参考ページによるものだが、今後はViewModelクラスで動くように考えたい。
今回の例はEditTextに入力した文字列を読ませる。

ソースコード

package com.seeking_star.test

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.speech.tts.TextToSpeech
import android.speech.tts.UtteranceProgressListener
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.EditText
import com.seeking_star.test.ui.main.MainFragment
import java.util.*

class MainActivity : AppCompatActivity(), TextToSpeech.OnInitListener {

    private var textToSpeech: TextToSpeech? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        textToSpeech = TextToSpeech(this, this)
        layout()
    }

    private fun layout() {
        findViewById<Button>(R.id.speechButton).setOnClickListener {
            val text = findViewById<EditText>(R.id.readEditText).text.toString()
            println("読み上げ:" + text)
            startSpeak(text)
        }
    }

    override fun onInit(status: Int) {
        if(status == TextToSpeech.SUCCESS){
            startSpeak("画面表示時に読み上げます。")

            val listener = object : UtteranceProgressListener(){
                var tag : String = "TTS"
                override fun onDone(utteranceId: String?) {
                    println("音声再生が完了しました。")
                }
                override fun onError(utteranceId: String?, errorCode: Int) {
                    println("音声再生中にエラーが発生しました。")
                }
                override fun onStart(utteranceId: String?) {
                    println("音声再生を開始します。")
                }
                override fun onStop(utteranceId: String?, interrupted: Boolean) {
                    println("音声再生を中止します。")
                }
                override fun onBeginSynthesis(utteranceId: String?, sampleRateInHz: Int, audioFormat: Int, channelCount: Int) {
                    println("音声の合成を開始します。")
                }
                override fun onAudioAvailable(utteranceId: String?, audio: ByteArray?) {
                    println("音声が利用可能になりました。")
                }
            }
            textToSpeech?.setOnUtteranceProgressListener(listener)
        } else {
            println("TextToSpeech初期化失敗")
        }
    }

    private fun startSpeak(text: String){
        textToSpeech?.setLanguage(Locale.JAPANESE)
        textToSpeech?.speak(text, TextToSpeech.QUEUE_FLUSH, null, "utteranceId")
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <EditText
            android:id="@+id/readEditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="" />

        <Button
            android:id="@+id/speechButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="読み上げ" />
    </LinearLayout>
</FrameLayout>
XML

デモ

詳細

言語の設定

setLanguageメソッドで設定する。
引数でLocaleクラスの言語を設定することで読み上げる言語を設定する。
今回の例では「Locale.JAPANESE」となっている。

音声

TextToSpeech.OnInitListenerを継承するクラスに設定する。
そうすることでonInit(status: Int)メソッドをオーバーライドして音声出力を行う準備の処理を行う。
ちなみに、画面表示と同時に音声の読み上げを行う時はここに読み上げを行う処理を書く。

onInit(status: Int)メソッドを使用する。

音声読み上げの各イベント時のデリゲートメソッド

音声の再生が完了したタイミングで処理を呼び出せるのはすごくありがたい。

メソッド名処理の内容
音声再生が完了onDone(utteranceId: String?)
音声再生中にエラーが発生onError(utteranceId: String?, errorCode: Int)
音声再生を開始onStart(utteranceId: String?)
音声再生を中止onStop(utteranceId: String?, interrupted: Boolean)
音声の合成を開始onBeginSynthesis(utteranceId: String?, sampleRateInHz: Int, audioFormat: Int, channelCount: Int)
音声が利用可能onAudioAvailable(utteranceId: String?, audio: ByteArray?)

参照ページ:
生涯エンジニア「Kotlinで合成音声を出力するアプリを作成[Android]」