🗣️

【Android】TextToSpeechを利用してシンプルなテキスト読み上げアプリを作成する

2024/03/29に公開

シンプルなテキスト読み上げアプリの開発方法を解説します。このアプリは、ユーザーが入力したテキストを様々なモード(速く話す、遅く話す、高いピッチ、低いピッチ、通常)で読み上げる機能を提供します。

TextToSpeechActivity - Activityの設定

TextToSpeechActivityクラスです。、setContentを使用してUIをセットします。

package com.example.myapplication.ui

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.runtime.Composable

class TextToSpeechActivity : ComponentActivity() {
    private val viewModel: TextToSpeechViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TextToSpeechScreen(viewModel)
        }
    }
}

TextToSpeechScreen - UIの構成

TextToSpeechScreenコンポーザブル関数は、UIの主要な部分を構成します。ユーザーがテキストを入力できるテキストフィールドと、異なる読み上げモードを選択できるボタンを表示します。

import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TextToSpeechScreen(viewModel: TextToSpeechViewModel) {
    var text by remember { mutableStateOf(TextFieldValue("")) }

    Scaffold(
        topBar = {
            TopAppBar(title = { Text("Text to Speech") })
        }
    ) { padding ->
        Column(
            modifier = Modifier
                .padding(padding)
                .padding(16.dp)
        ) {
            OutlinedTextField(
                value = text,
                onValueChange = { newText ->
                    text = newText
                },
                label = { Text("Enter text here") },
                modifier = Modifier.fillMaxWidth()
            )
            Spacer(modifier = Modifier.height(8.dp))
            ButtonGroup(viewModel = viewModel, text = text.text)
        }
    }
}

ButtonGroup - モード選択ボタンの配置

ButtonGroupコンポーザブル関数では、異なる読み上げモードを選択するためのボタンが配置されます。各ボタンは、選択されたモードに基づいてviewModelspeakメソッドを呼び出します。

@Composable
fun ButtonGroup(viewModel: TextToSpeechViewModel, text: String) {
    Column {
        val modes = listOf("fast" to "Speak Fast", "slow" to "Speak Slow", "highPitch" to "High Pitch", "lowPitch" to "Low Pitch", "normal" to "Normal")
        modes.forEach { mode ->
            Button(
                onClick = { viewModel.speak(text, mode.first) },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 8.dp)
            ) {
                Text(mode.second)
            }
        }
    }
}

最後にTextToSpeechConverterクラスです
ここではメソッドごとにそれぞれ異なった話し方ができるようにしています。


class TextToSpeechConverter(context: Context) {
    private var textToSpeech: TextToSpeech? = null

    init {
        textToSpeech = TextToSpeech(context) { status ->
            if (status == TextToSpeech.SUCCESS) {
                textToSpeech?.language = Locale.JAPANESE
            }
        }
    }

    // 早口で話す
    fun speakFast(text: String, language: Locale = Locale.JAPAN) {
        textToSpeech?.language = language
        textToSpeech?.setSpeechRate(2.0f) // Max speed depends on the device
        speak(text)
    }

    // ゆっくり話す
    fun speakSlow(text: String, language: Locale = Locale.JAPAN) {
        textToSpeech?.language = language
        textToSpeech?.setSpeechRate(0.5f)
        speak(text)
    }

    // 高いピッチで話す
    fun speakHighPitch(text: String, language: Locale = Locale.JAPAN) {
        textToSpeech?.language = language
        textToSpeech?.setPitch(2.0f)
        speak(text)
    }

    // 低いピッチで話す
    fun speakLowPitch(text: String, language: Locale = Locale.JAPAN) {
        textToSpeech?.language = language
        textToSpeech?.setPitch(0.5f)
        speak(text)
    }

    // 通常の話し方
    fun speakNormal(text: String, language: Locale = Locale.JAPAN) {
        textToSpeech?.language = language
        textToSpeech?.setPitch(1.0f)
        textToSpeech?.setSpeechRate(1.0f)
        speak(text)
    }

    private fun speak(text: String) {
        textToSpeech?.speak(text, TextToSpeech.QUEUE_FLUSH, null, null)
    }

    fun shutdown() {
        textToSpeech?.stop()
        textToSpeech?.shutdown()
    }
}

これらのコンポーネントを組み合わせることで、ユーザーがテキストを入力し、好みのモードで読み上げることができるシンプルなテキスト読み上げアプリが完成します。

https://github.com/entaku0818/AudioMasterAndroid
こちらでサンプルコードを公開してますのでぜひ触ってみてください!

Discussion