You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
diplomatic-quarter/flutter_tts-voice_enhancement/lib/flutter_tts_web.dart

185 lines
4.7 KiB
Dart

import 'dart:async';
import 'dart:html' as html;
import 'dart:js';
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
enum TtsState { playing, stopped, paused, continued }
class FlutterTtsPlugin {
static const String PLATFORM_CHANNEL = "flutter_tts";
static MethodChannel channel;
bool awaitSpeakCompletion = false;
TtsState ttsState = TtsState.stopped;
get isPlaying => ttsState == TtsState.playing;
get isStopped => ttsState == TtsState.stopped;
get isPaused => ttsState == TtsState.paused;
get isContinued => ttsState == TtsState.continued;
static void registerWith(Registrar registrar) {
channel = MethodChannel(
PLATFORM_CHANNEL, const StandardMethodCodec(), registrar.messenger);
final instance = FlutterTtsPlugin();
channel.setMethodCallHandler(instance.handleMethodCall);
}
html.SpeechSynthesis synth;
html.SpeechSynthesisUtterance utterance;
List<dynamic> voices;
List<String> languages;
FlutterTtsPlugin() {
utterance = html.SpeechSynthesisUtterance();
synth = html.window.speechSynthesis;
_listeners();
}
void _listeners() {
utterance.onStart.listen((e) {
ttsState = TtsState.playing;
channel.invokeMethod("speak.onStart", null);
});
utterance.onEnd.listen((e) {
ttsState = TtsState.stopped;
channel.invokeMethod("speak.onComplete", null);
if (awaitSpeakCompletion) {
return 1;
}
});
utterance.onPause.listen((e) {
ttsState = TtsState.paused;
channel.invokeMethod("speak.onPause", null);
});
utterance.onResume.listen((e) {
ttsState = TtsState.continued;
channel.invokeMethod("speak.onContinue", null);
});
utterance.onError.listen((e) {
channel.invokeMethod("speak.onError", e);
if (awaitSpeakCompletion) {
return 0;
}
});
}
Future<dynamic> handleMethodCall(MethodCall call) async {
switch (call.method) {
case 'speak':
final text = call.arguments as String;
_speak(text);
if (!awaitSpeakCompletion) {
return 1;
}
break;
case 'awaitSpeakCompletion':
awaitSpeakCompletion = call.arguments as bool;
return 1;
break;
case 'stop':
_stop();
return 1;
break;
case 'pause':
_pause();
return 1;
break;
case 'setLanguage':
final language = call.arguments as String;
_setLanguage(language);
return 1;
break;
case 'getLanguages':
return _getLanguages();
break;
case 'setSpeechRate':
final rate = call.arguments as num;
_setRate(rate);
return 1;
break;
case 'setVolume':
final volume = call.arguments as num;
_setVolume(volume);
return 1;
break;
case 'setPitch':
final pitch = call.arguments as num;
_setPitch(pitch);
return 1;
break;
case 'isLanguageAvailable':
final lang = call.arguments as String;
return _isLanguageAvailable(lang);
break;
default:
throw PlatformException(
code: 'Unimplemented',
details: "The flutter_tts plugin for web doesn't implement "
"the method '${call.method}'");
}
}
void _speak(String text) {
if (ttsState == TtsState.stopped || ttsState == TtsState.paused) {
utterance.text = text;
if (ttsState == TtsState.paused) {
synth.resume();
} else {
synth.speak(utterance);
}
}
}
void _stop() {
if (ttsState != TtsState.stopped) {
synth.cancel();
}
}
void _pause() {
if (ttsState == TtsState.playing || ttsState == TtsState.continued) {
synth.pause();
}
}
void _setRate(num rate) => utterance.rate = rate * 2.0;
void _setVolume(num volume) => utterance.volume = volume;
void _setPitch(num pitch) => utterance.pitch = pitch;
void _setLanguage(String language) => utterance.lang = language;
bool _isLanguageAvailable(String language) {
if (voices?.isEmpty ?? true) _setVoices();
if (languages?.isEmpty ?? true) _setLanguages();
for (var lang in languages) {
if (lang.toLowerCase() == language.toLowerCase()) return true;
}
return false;
}
List<String> _getLanguages() {
if (voices?.isEmpty ?? true) _setVoices();
if (languages?.isEmpty ?? true) _setLanguages();
return languages;
}
void _setVoices() {
voices =
context['speechSynthesis'].callMethod('getVoices') as JsArray<dynamic>;
}
void _setLanguages() {
var langs = Set<String>();
for (var v in voices) {
langs.add(v['lang'] as String);
}
languages = langs.toList();
}
}