[Flutter] Flutter TTS

고랭지참치·2024년 6월 12일
0

Flutter

목록 보기
11/24

flutter_tts | Flutter Package

on Android


안드로이드의 경우 minSDK가 존재

minSdkVersion 21

또한 Native레벨에서 안드로이드는 Pause 기능이 없기 때문에, 임시방편으로 pause를 구현해놓은 상태. 때문에 안드로이드에서 pause 기능을 사용하려면 SDK 26 이상이어야 한다

  • 해당 내용 전문

    Pausing on Android

    Android TTS does not support the pause function natively, so we have implemented a work around. We utilize the native onRangeStart() method to determine the index of start when pause is invoked. We use that index to create a new text the next time speak is invoked. Due to using onRangeStart(), pause works on SDK versions >= 26. Also, if using start and end offsets inside of setProgressHandler(), you'll need to keep a track of them if using pause since they will update once the new text is created when speak is called after being paused.

TTS Setting


TTS Constructor & Riverpod 상태관리

  • TTS 오브젝트를 싱글톤으로 관리하기 위해 싱글톤패턴 사용
  • tts_handler 이용시 riverpod으로 관리하는 TTSstate를 관리해주기 위해 WidgetRef를 파라미터로 받도록 생성
TTSUtil(ref).init();

...

class TTSUtil {
	TTSUtil._internal();
  factory TTSUtil(WidgetRef ref) {
    _instance.ref = ref;
    return _instance;
  }

  final FlutterTts ttsUtil = FlutterTts();
  static final TTSUtil _instance = TTSUtil._internal();
  late WidgetRef ref;

	// init 시 세팅해줘야하는 기본 파라미터들
	Future<void> init() async {
    await _setAwaitOptions();
    await ttsUtil.setLanguage('ko-KR');
    await ttsUtil.setVolume(volume);
    await ttsUtil.setSpeechRate(rate);
    await ttsUtil.setPitch(pitch);
  }

	Future _setAwaitOptions() async {
    await ttsUtil.awaitSpeakCompletion(true);
  }

...
enum TTSState { playing, stopped, paused, continued }

(keepAlive: true)
class TTS extends _$TTS {
  
  TTSState build() {
    return TTSState.stopped;
  }

  void setTTSState(TTSState ttsState) {
    state = ttsState;
  }
}

한국어 Voice 종류

  • 총 8개의 한국어 Voice 중 4개의 Voice가 로컬로 지원되며, 나머지 4개는 네트워크 통신을 통해 Voice데이터를 가져와서 사용한다
  • 아래 코드는 로컬로 사용할 수 있는 4가지 종류(여자2, 남자 2)를 스위치로 설정한다.
enum TTSVoice { women1, women2, man1, man2 }

...

Future setVoice({required TTSVoice newVoiceenum}) async {
    final String newVoiceName;
    switch (newVoiceenum) {
      case TTSVoice.women1:
        newVoiceName = 'ko-KR-language';
        break;
      case TTSVoice.women2:
        newVoiceName = 'ko-kr-x-kob-local';
        break;
      case TTSVoice.man1:
        newVoiceName = 'ko-kr-x-kod-local';
        break;
      case TTSVoice.man2:
        newVoiceName = 'ko-kr-x-koc-local';
        break;
    }
		await ttsUtil.setVoice({
	      'name': newVoiceName,
	      'locale': 'ko-KR',
    });
  }

Handler

  • Flutter tts는 총 6개의 handler를 지원한다.
    • setStartHandler
    • setCompletionHandler
    • setCancelHandler
    • setPausedHanlder
    • setContinuedHandler
    • setErrorHandler
  • 아래 코드처럼 특정 handler 작동 시의 콜백 함수를 파라미터로 받아 실행시킬 수 있다.
  • handler가 실행될 때마다 해당 상황에 맞춰 TTSState를 관리하는 riverpod state의 값을 업데이트 해준다.
void setCompletionHandler({required Function() completionHandler}) {
    ttsUtil.setCompletionHandler(() {
      ref.read(tTSProvider.notifier).setTTSState(TTSState.stopped);
      completionHandler();
    });
  }

UI상 사용

late final TTSUtil ttsUtil;


  void initState() {
    super.initState();
    ttsUtil = TTSUtil(ref);
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      ttsUtil.speak(
          newVoiceText: '첫번째 나올 TTS 문장'
			);
    });
  }


  Widget build(BuildContext context) {

	//tts의 index단계가 끝날 때마다 0.5초 대기 시간 가진 후 다음 새로운 텍스트를 speak하는 코드
    ttsUtil.setCompletionHandler(completionHandler: () async {
      await Future.delayed(const Duration(milliseconds: 500), () async {
        await _handleTTSProgress();
      });
    });

...
	// 넘어가기 버튼이 클릭되면 tts stop & handle
		CustomTextButton.create(
			text: '넘어가기',
			onPressed: () async {
				await ttsUtil.stop();
				await _handleTTSProgress();
			},
		),

...

Future<void> _handleTTSProgress(
      ) async {
      ttsUtil.speak(
        newVoiceText:' ...  ',
      );
  }
profile
소프트웨어 엔지니어 / Flutter 개발자

0개의 댓글