feat(tts): server-backed TTS engine selection
Introduce server TTS support and engine selection while keeping device TTS as the default. - Add new persistence keys for storing TTS engine and selected server voice (ttsEngine, ttsServerVoiceId, ttsServerVoiceName). - Extend TextToSpeechService to support two engines: TtsEngine.device (FlutterTts) and TtsEngine.server (remote audio). - Wire in an AudioPlayer and optional ApiService to fetch raw audio bytes from the server and play them, with event hooks mapped to existing lifecycle callbacks. - Implement fallback to device TTS on server errors or empty responses, and ensure player lifecycle (pause/stop/dispose) is handled when using server engine. - Allow engine and preferred voice to be configured before initialization and updated at runtime via updateSettings. This enables selecting a server-side voice and using a remote TTS provider while preserving compatibility with the existing device TTS implementation.
This commit is contained in:
@@ -3,6 +3,7 @@ import 'dart:async';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../core/services/settings_service.dart';
|
||||
import '../../../core/providers/app_providers.dart';
|
||||
import '../../../core/utils/markdown_to_text.dart';
|
||||
import '../services/text_to_speech_service.dart';
|
||||
|
||||
@@ -79,11 +80,15 @@ class TextToSpeechController extends Notifier<TextToSpeechState> {
|
||||
// Listen to settings changes and update TTS when initialized
|
||||
ref.listen<AppSettings>(appSettingsProvider, (previous, next) {
|
||||
if (_service.isInitialized && _service.isAvailable) {
|
||||
final selectedVoice = next.ttsEngine == TtsEngine.server
|
||||
? next.ttsServerVoiceId
|
||||
: next.ttsVoice;
|
||||
_service.updateSettings(
|
||||
voice: next.ttsVoice,
|
||||
voice: selectedVoice,
|
||||
speechRate: next.ttsSpeechRate,
|
||||
pitch: next.ttsPitch,
|
||||
volume: next.ttsVolume,
|
||||
engine: next.ttsEngine,
|
||||
);
|
||||
}
|
||||
}, fireImmediately: false);
|
||||
@@ -105,10 +110,13 @@ class TextToSpeechController extends Notifier<TextToSpeechState> {
|
||||
final settings = ref.read(appSettingsProvider);
|
||||
final future = _service
|
||||
.initialize(
|
||||
voice: settings.ttsVoice,
|
||||
voice: settings.ttsEngine == TtsEngine.server
|
||||
? settings.ttsServerVoiceId
|
||||
: settings.ttsVoice,
|
||||
speechRate: settings.ttsSpeechRate,
|
||||
pitch: settings.ttsPitch,
|
||||
volume: settings.ttsVolume,
|
||||
engine: settings.ttsEngine,
|
||||
)
|
||||
.then((available) {
|
||||
if (!ref.mounted) {
|
||||
@@ -289,7 +297,8 @@ class TextToSpeechController extends Notifier<TextToSpeechState> {
|
||||
}
|
||||
|
||||
final textToSpeechServiceProvider = Provider<TextToSpeechService>((ref) {
|
||||
final service = TextToSpeechService();
|
||||
final api = ref.watch(apiServiceProvider);
|
||||
final service = TextToSpeechService(api: api);
|
||||
ref.onDispose(() {
|
||||
unawaited(service.dispose());
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user