Framework/Flutter

[Error]"Uncaught TypeError: Cannot read property 'cancel' of undefined"

  • -
반응형

최근 같이 공부하는 스터디팀에서 영어 단어 앱을 만들어 배포했는데요. Next.js로 웹을 구현하고 Flutter의 웹뷰를 이용해 제작/배포한 앱입니다.

영어 단어를 읽어주는 기능을 윈도우 함수 중 speechSynthesis로 구현했는데, 이 함수는 안드로이드 웹뷰에서는 지원되지 않는다고 합니다. iOS에서만 테스트를 하다보니 이런 부분을 체크하지 못한 것 같네요.

 

https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis

 

기존 코드를 보면 영어 단어 클릭시 아래와 같이 speechSynthesis를 이용해서 음성으로 표시되고 있었습니다.

window.speechSynthesis.cancel();

const speechMsg = new SpeechSynthesisUtterance();
speechMsg.rate = 1;
speechMsg.pitch = 1.2;
speechMsg.lang = "en-US";
speechMsg.text = itemWord.word;

window.speechSynthesis.speak(speechMsg);

 

애뮬레이터의 로그를 보면 이런 로그가 찍혀있습니다.

"Uncaught TypeError: Cannot read property 'cancel' of undefined",

 

이 문제를 해결하기 위해 Flutter의 TTS(Text To Speech) 패키지를 사용하기로 했습니다. TTS 패키지는 텍스트를 소리로 표현합니다.

이 패키지를 통해 iOS 에서는 기존 윈도우 함수를 사용하고 Android에서는 tts 함수를 사용하도록 처리했습니다.

 

먼저 패키지를 추가합니다.

flutter pub add flutter_tts

 

웹뷰 위젯안에 FlutterTts를 초기화하고, 접속 디바이스에 따라 채널명을 다르게 설정했습니다.

final FlutterTts tts = FlutterTts();
final String _webviewChannel =
      Platform.isAndroid ? 'androidChannel' : 'iosChannel';

 

initState 메소드가 실행될 때 초기화된 Flutter tts의 언어와 스피칭 속도를 지정합니다.

한글을 읽고 싶은 경우는 setLanguage를 "ko-KR"로 변경하면 됩니다.

tts.setLanguage('en');
tts.setSpeechRate(0.4);

 

디바이스에 따라 설정된 채널명으로 자바스크립트 채널을 설정합니다. 그리고 메세지를 통해 받아온 값을 그대로 읽도록 했습니다.

 ..addJavaScriptChannel(_webviewChannel,
    onMessageReceived: (JavaScriptMessage javaScriptMessage) {
  tts.speak(javaScriptMessage.message);
})

 

웹 소스에서는 아래와 같이 분기처리가 되어있기 때문에 androidChannel이 있는 경우에만 위의 코드가 실행됩니다.

const { androidChannel } = window;

if (androidChannel) {
  androidChannel.postMessage(itemWord.word);
} else {
  window.speechSynthesis.cancel();

  const speechMsg = new SpeechSynthesisUtterance();
  speechMsg.rate = 1;
  speechMsg.pitch = 1.2;
  speechMsg.lang = "en-US";
  speechMsg.text = itemWord.word;

  window.speechSynthesis.speak(speechMsg);
}

 

참고자료
 

Text-to-speech doesn't work in an Android WebView and Firefox

I've got a website (www.myexamplewebsite.com) that looks simplified like this: <html> <head> </head> <body> <img src="img/speaker-icon.png" onclick="speakerFunction()"...

stackoverflow.com

 

flutter_tts | Flutter Package

A flutter plugin for Text to Speech. This plugin is supported on iOS, macOS, Android, Web, & Windows.

pub.dev

 

반응형
Contents

포스팅 주소를 복사했습니다.

이 글이 도움이 되었다면 공감 부탁드립니다.