본문 바로가기
개발노트/Flutter

[Flutter] STT(Speech to text) 구현하기

by 전지적진영시점 2023. 3. 14.
반응형

이번 포스팅에서는 

flutter에서 라이브러리를 사용해 STT(speech to text) 기능을 구현해볼겁니다.

해당 코드는 Flutter Dev 사이트를 참고하여 직접 테스트 해보고 가져왔습니다.

 

먼저 stt 기능을 사용하기 위해 flutter에서 제공하는 stt 라이브러리를 가져옵니다!

pubspec.yaml 파일 내 dependencies 에 라이브러리를 추가해줍니다.

dependencies:
  flutter:
    sdk: flutter

  #stt, tts
  speech_to_text: ^6.1.1
  flutter_tts: ^3.6.3

 

본 포스팅에서는 stt.dart 파일과 생성하여 기능을 넣어주었습니다.

 

화면단은 모양을 이렇게 잡아줍니다.

@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
      body: Column(children: [
        Expanded(
          flex: 4,
          child: Container(
            padding: EdgeInsets.only(top: 100.0),
            child: Column(
              children: <Widget>[
                const Center(
                  child: Text(
                    '음성 인식 결과',
                    style: TextStyle(fontSize: 22.0),
                  ),
                ),
                Expanded(
                  child: Stack(
                    children: <Widget>[
                      Container(
                        color: Theme.of(context).selectedRowColor,
                        child: Center(
                          child: Text(
                            lastWords,
                            textAlign: TextAlign.center,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
        Container(
          padding: const EdgeInsets.only(bottom: 50.0),
          child: Column(
            children: <Widget>[
              Column(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  IconButton(
                    onPressed: !_hasSpeech || speech.isListening
                        ? null
                        : startListening,
                    icon: Icon(Icons.mic),
                  ),
                  Container(
                      margin: const EdgeInsets.only(top: 0.0),
                      child: const Text("click!",
                          style: TextStyle(
                              fontSize: 12.0,
                              fontWeight: FontWeight.w400,
                              color: Colors.blue)))
                ],
              ),
            ],
          ),
        ),
      ]),
    ),
  );
}

 

listener 호출

 

void startListening() {
  _logEvent('start listening');
  lastWords = '';
  lastError = '';
  speech.listen(
      onResult: resultListener,
      listenFor: Duration(seconds: 30),
      pauseFor: Duration(seconds: 5),
      partialResults: true,
      localeId: _currentLocaleId,
      onSoundLevelChange: soundLevelListener,
      cancelOnError: true,
      listenMode: ListenMode.confirmation);
  setState(() {});
}

 

결과값 받기

 

void resultListener(SpeechRecognitionResult result) {
  _logEvent(
      'Result listener final: ${result.finalResult}, words: ${result.recognizedWords}');
  setState(() {
    lastWords = result.recognizedWords;
  });
}

 

 

 

 

<전체소스>

 

import 'dart:math';
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';

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Flutter Demo',
      home: SttPage(),
    );
  }
}

class SttPage extends StatefulWidget {
  const SttPage({Key? key}) : super(key: key);

  @override
  _SttPageState createState() => _SttPageState();
}

class _SttPageState extends State<SttPage> {
  bool _hasSpeech = false;
  bool _logEvents = false;
  double level = 0.0;
  double minSoundLevel = 50000;
  double maxSoundLevel = -50000;
  String lastWords = '';
  String lastError = '';
  String lastStatus = '';
  String _currentLocaleId = '';
  List<LocaleName> _localeNames = [];
  final SpeechToText speech = SpeechToText();

  @override
  void initState() {
    super.initState();

    initSpeechState();
  }

  Future<void> initSpeechState() async {
    _logEvent('Initialize');
    var hasSpeech = await speech.initialize(
        onError: errorListener,
        onStatus: statusListener,
        debugLogging: true,
        finalTimeout: Duration(milliseconds: 0));
    if (hasSpeech) {
      _localeNames = await speech.locales();

      var systemLocale = await speech.systemLocale();
      _currentLocaleId = systemLocale?.localeId ?? '';
    }

    if (!mounted) return;

    setState(() {
      _hasSpeech = hasSpeech;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(children: [
          Expanded(
            flex: 4,
            child: Container(
              padding: EdgeInsets.only(top: 100.0),
              child: Column(
                children: <Widget>[
                  const Center(
                    child: Text(
                      '음성 인식 결과',
                      style: TextStyle(fontSize: 22.0),
                    ),
                  ),
                  Expanded(
                    child: Stack(
                      children: <Widget>[
                        Container(
                          color: Theme.of(context).selectedRowColor,
                          child: Center(
                            child: Text(
                              lastWords,
                              textAlign: TextAlign.center,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
          Container(
            padding: const EdgeInsets.only(bottom: 50.0),
            child: Column(
              children: <Widget>[
                Column(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: <Widget>[
                    IconButton(
                      onPressed: !_hasSpeech || speech.isListening
                          ? null
                          : startListening,
                      icon: Icon(Icons.mic),
                    ),
                    Container(
                        margin: const EdgeInsets.only(top: 0.0),
                        child: const Text("click!",
                            style: TextStyle(
                                fontSize: 12.0,
                                fontWeight: FontWeight.w400,
                                color: Colors.blue)))
                  ],
                ),
              ],
            ),
          ),
        ]),
      ),
    );
  }

  void startListening() {
    _logEvent('start listening');
    lastWords = '';
    lastError = '';
    speech.listen(
        onResult: resultListener,
        listenFor: Duration(seconds: 30),
        pauseFor: Duration(seconds: 5),
        partialResults: true,
        localeId: _currentLocaleId,
        onSoundLevelChange: soundLevelListener,
        cancelOnError: true,
        listenMode: ListenMode.confirmation);
    setState(() {});
  }

  void resultListener(SpeechRecognitionResult result) {
    _logEvent(
        'Result listener final: ${result.finalResult}, words: ${result.recognizedWords}');
    setState(() {
      lastWords = result.recognizedWords;
    });
  }

  void soundLevelListener(double level) {
    minSoundLevel = min(minSoundLevel, level);
    maxSoundLevel = max(maxSoundLevel, level);
    // _logEvent('sound level $level: $minSoundLevel - $maxSoundLevel ');
    setState(() {
      this.level = level;
    });
  }

  void errorListener(SpeechRecognitionError error) {
    _logEvent(
        'Received error status: $error, listening: ${speech.isListening}');
    setState(() {
      lastError = '${error.errorMsg} - ${error.permanent}';
    });
  }

  void statusListener(String status) {
    _logEvent(
        'Received listener status: $status, listening: ${speech.isListening}');
    setState(() {
      lastStatus = '$status';
    });
  }

  void _logEvent(String eventDescription) {
    if (_logEvents) {
      var eventTime = DateTime.now().toIso8601String();
      print('$eventTime $eventDescription');
    }
  }
}
반응형

댓글