Chapter 47

スマホ機能編4:音声の文字化(SpeechToText)

kazutxt
kazutxt
2021.05.15に更新

このチャプターでは、STT(音声の文字化)について解説します。

スマートフォンに向かって喋った音声データを文字データに変換しテキスト化する方法を解説します。

事前準備

パッケージインストール

まず、必要なパッケージをインストールします。

pubspec.yml
speech_to_text: ^3.2.0

iOS

つづいて、iOS用のスマートフォンの機能を使うための権限を設定します。

ios/Runner/info.plist
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app requires to speech recognition/<string>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires to add file to your photo library your microphone </string>

Android

最後に、Android用のスマートフォンの機能を使うための権限を設定します。

android/app/src/main/AndroidManifest.xml
<queries>
  <intent>
    <action android:name="android.speech.RecognitionService" />
  </intent>
</queries>

実装

SpeechToTextを使って、喋った内容を文字にします。

main.dart
import 'package:flutter/material.dart';
import 'package:speech_to_text/speech_recognition_error.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart' as stt;

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);
  final String? title;
  
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String lastWords = "";
  String lastError = '';
  String lastStatus = '';
  stt.SpeechToText speech = stt.SpeechToText();

  Future<void> _speak() async {
    bool available = await speech.initialize(
        onError: errorListener, onStatus: statusListener);
    if (available) {
      speech.listen(onResult: resultListener);
    } else {
      print("The user has denied the use of speech recognition.");
    }
  }

  Future<void> _stop() async {
    speech.stop();
  }

  void resultListener(SpeechRecognitionResult result) {
    setState(() {
      lastWords = '${result.recognizedWords}';
    });
  }

  void errorListener(SpeechRecognitionError error) {
    setState(() {
      lastError = '${error.errorMsg} - ${error.permanent}';
    });
  }

  void statusListener(String status) {
    setState(() {
      lastStatus = '$status';
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '変換文字:$lastWords',
              style: Theme.of(context).textTheme.headline4,
            ),
            Text(
              'ステータス : $lastStatus',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton:
          Row(mainAxisAlignment: MainAxisAlignment.end, children: [
        FloatingActionButton(onPressed: _speak, child: Icon(Icons.play_arrow)),
        FloatingActionButton(onPressed: _stop, child: Icon(Icons.stop))
      ]),
    );
  }
}

await speech.initializeで初期化を行い、speech.listenでSTTを開始します。
resultListenerに変換された文字が順次やってくるため、変数にいれて、格納しています。

動作確認

再生ボタンで識別開始、停止ボタンで終了します。
識別中にしゃべると次々と文字列に変換されていきます。