JINMUSOFTWARE

FlutterでTTSを利用してテキストを読み上げる方法

TTS(Text To Speexh)を利用してテキストから音声を再生する方法

TTSとは

「Text To Speech」の略です。

Flutterのパッケージです。プラグインとも呼ばれるようです。

このパッケージ機能は、テキストから音声を合成して発音します。

flutter_tts

環境

flutter: 3.19.5

flutter_tts: 4.0.2

emulator: Pixel 7 API 30 “R” Android 11.0

emulator: Pixel 8 API 33 “Tiramisu” Android 13.0

実機: Pixel 6a API 34 “Upside Down Cake” Android 14

注意事項

わたくしはFlutterの一年生です。やってみたら上手くいったことを記述しています。なので、セオリーに反していることがあるかもしれません。

よろしくおねがいします。

TTS導入手順

Androidターゲットで説明しております。

TTSパッケージをインストールします

Flutterのパッケージは、pub.devより「flutter tts」で検索できます。

インストールの方法は、installing のタブで確認できまね。方法は2つありますね。どっちか好きな方法でインストールしましょう。

1.flutterコマンドを実行する方法

flutter pub add flutter_tts

最新のVersionがインストールされます。

インストール後は、pubspec.yamlファイルが自動で更新されています。

2.pubspec.yamlファイルを編集する方法

dependencies:
  flutter_tts: ^4.0.2

pubspex.yamlを自分で編集します。

「dependencies:」のところに、「flutter_tts: ^4.0.2」を追記します。

この方法は、パッケージのVersion を指定できます。

編集後は、flutterコマンド「flutter pub get」を実行する必要があります。

flutter pub get

VSCodeを使用している場合は、ファイルを保存したときに自動で実行されます。

TTSパッケージ導入に伴う設定

さて、パッケージをインストールできました。

Androidターゲットであれば、ここでAppを実行するとエラーが発生するかもしれません。

落ち着いて、flutter_tts の Readme を確認してみましょう。

Androidでの注意事項が2つありますね。設定してみましょう。

設定1.minSdkVersionの値を21以上に設定する

場所:android/app/build.gradle

修正:minSdkVersion flutter.minSdkVersion ➡ minSdkVersion 21

defaultConfig {
    // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
    applicationId "com.example.tts10"
    // You can update the following values to match your application needs.
    // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
    // minSdkVersion flutter.minSdkVersion
    minSdkVersion 21
    targetSdkVersion flutter.targetSdkVersion
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName
}

build.gradleはandroid直下にもあるので間違わないことです。ただ中身が全然違うので気づくと思います。

設定2.AndroidManifest.xmlのqueriesに新しいintentを追加する

ターゲットのAndroidのversionが11の場合以下の設定も必要です。

場所:android/app/src/main/AndroidManifest.xml

修正:"<action android:name="android.intent.action.TTS_SERVICE" />" を追加する。

<queries>
    <intent>
        <action android:name="android.intent.action.PROCESS_TEXT" />
        <data android:mimeType="text/plain" />
    </intent>
    <intent>
        <action android:name="android.intent.action.TTS_SERVICE" />
    </intent>
</queries>

flutterのversionによっては、元々intentがなかったりします。flutter version 3.19.5 では上記のようにすでにintentでactionが定義されていました。

intentにはactionは1つまでしか記述できないようです。

よって、すでにintentがある場合は、あたらしく、intentから記述します。

Kotlinのversion違いによるエラーの対応

それでもまだ、以下のようなエラーが発生するかもしれません。VSCodeの「デバッグコンソール」で確認してください。

“Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.9.0, expected version is 1.7.1.”

訳:モジュールは互換性の無いVersionでコンパイルされていますよ。バイナリは、1.9.0ですね。1.7.1が期待されていました。 ➡ TTSパッケージは1.9.0で、私の環境が1.7,1のようです。

~~
~~
Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.9.0, expected version is 1.7.1.
~~
~~
┌─ Flutter Fix ────────────────────────────────────────────────────────
│ [!] Your project requires a newer version of the Kotlin Gradle plugin.
│ Find the latest version on https://kotlinlang.org/docs/releases.html#release-details, then
│ update C:\htdocs\flutter\3_package\tts\tts10\android\build.gradle:
│ ext.kotlin_version = '<latest-version>'
└──────────────────────────────────────────────────────────────────────
Error: Gradle task assembleDebug failed with exit code 1

Webで調べても、Chat-GPTでも情報は取れませんでした。Kotlin開発の情報はあったような気はしますが。

がしかし、発見しました。方法は2つあります。

flutter_ttsのkotlinのversionは?

解決方法の前にTTSパッケージのChangeLogを確認してみましょう。

TTSのVersion4.0.0のときに、”Kotlin 1.9.10″ が使用されていることがわかりますね。

方法1.settings.gradleで、kotlinのversionを指定しましょう。

場所:android/settings.gradle

修正:id “org.jetbrains.kotlin.android” version “1.7.10” apply false ➡ id “org.jetbrains.kotlin.android” version “1.9.10” apply false

plugins {
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
    id "com.android.application" version "7.3.0" apply false
    id "org.jetbrains.kotlin.android" version "1.9.10" apply false
}

方法2.flutter_ttsのversionをちょっと古いものを指定する

場所:pubspec.yaml

修正:flutter_tts: ^4.0.2 ➡ flutter_tts: ^3.8.5

3.8.5だとそのまま動作しました。

すきな方法で対応してくださいね。

プログラミング

さて、色々と大変でしたがコードを書いていきましょう。

import 'package:flutter/material.dart';
import 'package:flutter_tts/flutter_tts.dart'; // 1. パッケージをインポート。


void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'TTS Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const Home(),
    );
  }
}

class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<Home> createState() => _HomeState();
}

/// 初期化をinitState()で行う為に、Statefulを選択。
/// constructorの中で、非同期処理は呼ばないのセオリーのようだ。
class _HomeState extends State<Home> {
  final FlutterTts tts = FlutterTts(); // 2. インスタンスを生成。
  final String _text = 'おはよう。こんにちは。松田です。';

  @override
  void initState() {
    super.initState();
    initializeTts(); // 3.初期化処理
  }

  // 3.初期化処理
  initializeTts() async {
    await tts.setLanguage('ja-JA');
    await tts.setSpeechRate(0.6);
    await tts.setPitch(1.0);
    await tts.awaitSpeakCompletion(false); // 発話の完了まで待機。
    await tts.awaitSynthCompletion(true); // ファイルの合成まで待機。
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('TTS Demo'),
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
                onPressed: () async {
                  await tts.speak(_text); // 4. 発話を行う。
                },
                child: const Text('Play!')),
          ],
        ),
      ),
    );
  }
}

パッケージをimportして、インスタンスを生成して、初期設定をして、テキストを準備して、speak()メソッドを実行します。

emulatorですと雑音がはいりました。実機ですと綺麗な音声で再生されました。

言語コード

他の言語でも再生してみたいですよね。

言語コードをsetLanguageで設定すればいいですね。

言語コードは以下を参考にしました。

Flutterで音声読み上げライブラリ(flutter_tts)を使ってみる

どうやら、言語コードと国コードのセットようですね。

以上