import 'dart:io'; import 'package:flutter_tts/flutter_tts.dart'; import 'package:get/get.dart'; import '../../core/utils/logger.dart'; /// Flutter TTS服务,负责本地文本转语音功能 class FlutterTtsService extends GetxService { late FlutterTts _flutterTts; // 当前TTS状态 TtsState _ttsState = TtsState.stopped; TtsState get ttsState => _ttsState; // 可用的语音 List> _voices = []; List> get voices => _voices; // 当前选择的语音 String _currentVoice = ''; String get currentVoice => _currentVoice; set currentVoice(String voice) => _currentVoice = voice; // 语速 (0.1-2.0) double _rate = 0.5; double get rate => _rate; set rate(double value) => _rate = value; // 音量 (0.0-1.0) double _volume = 1.0; double get volume => _volume; set volume(double value) => _volume = value; // 音调 (0.5-2.0) double _pitch = 1.0; double get pitch => _pitch; set pitch(double value) => _pitch = value; // 文本队列 - 仅包含待播放的文本 List _textQueue = []; List get textQueue => _textQueue; // 当前正在播放的文本 String _currentText = ''; String get currentText => _currentText; // 是否正在处理队列 bool _isProcessingQueue = false; @override void onInit() { super.onInit(); _initTts(); } /// 初始化TTS引擎 Future _initTts() async { _flutterTts = FlutterTts(); // 设置完成回调 _flutterTts.setCompletionHandler(() { Logger.info('TTS播放完成: "$_currentText"'); // 清空当前播放文本 _currentText = ''; // 处理队列中的下一条文本 _processNextInQueue(); // 只有当队列为空且不再处理队列时才设置为stopped状态 if (_textQueue.isEmpty && !_isProcessingQueue) { _ttsState = TtsState.stopped; Logger.info('TTS队列播放完成,设置为stopped状态'); } }); // 设置错误回调 _flutterTts.setErrorHandler((error) { Logger.error('Flutter TTS错误: $error'); // 清空当前播放文本 _currentText = ''; // 尝试播放下一条文本 _processNextInQueue(); // 只有当队列为空且不再处理队列时才设置为stopped状态 if (_textQueue.isEmpty && !_isProcessingQueue) { _ttsState = TtsState.stopped; Logger.info('TTS队列播放出错且为空,设置为stopped状态'); } }); // 设置开始回调 _flutterTts.setStartHandler(() { _ttsState = TtsState.playing; }); // 设置取消回调 _flutterTts.setCancelHandler(() { // 清空当前播放文本 _currentText = ''; _isProcessingQueue = false; _ttsState = TtsState.stopped; Logger.info('TTS播放被取消,设置为stopped状态'); }); // 设置暂停回调 _flutterTts.setPauseHandler(() { _ttsState = TtsState.paused; }); // 设置继续回调 _flutterTts.setContinueHandler(() { _ttsState = TtsState.playing; }); // 加载可用语音 await _loadVoices(); Logger.info('Flutter TTS服务已初始化'); } /// 加载可用的语音 Future _loadVoices() async { try { if (Platform.isAndroid || Platform.isIOS) { final voices = await _flutterTts.getVoices; if (voices != null) { _voices = []; for (var voice in voices) { if (voice is Map) { final Map voiceMap = {}; voice.forEach((key, value) { if (key is String && value is String) { voiceMap[key] = value; } else if (key is String) { voiceMap[key] = value.toString(); } }); if (voiceMap.containsKey('name')) { _voices.add(voiceMap); } } } // 如果有可用语音,设置第一个为默认 if (_voices.isNotEmpty) { _currentVoice = _voices[0]['name'] ?? ''; await _flutterTts.setVoice({"name": _currentVoice}); } } } } catch (e) { Logger.error('加载TTS语音失败', e); } } /// 设置语音 Future setVoice(String voiceName) async { try { _currentVoice = voiceName; await _flutterTts.setVoice({"name": voiceName}); } catch (e) { Logger.error('设置TTS语音失败', e); } } /// 设置语速 Future setRate(double rate) async { try { _rate = rate; await _flutterTts.setSpeechRate(rate); } catch (e) { Logger.error('设置TTS语速失败', e); } } /// 设置音量 Future setVolume(double volume) async { try { _volume = volume; await _flutterTts.setVolume(volume); } catch (e) { Logger.error('设置TTS音量失败', e); } } /// 设置音调 Future setPitch(double pitch) async { try { _pitch = pitch; await _flutterTts.setPitch(pitch); } catch (e) { Logger.error('设置TTS音调失败', e); } } /// 设置语言 Future setLanguage(String language) async { try { await _flutterTts.setLanguage(language); } catch (e) { Logger.error('设置TTS语言失败', e); } } /// 添加文本到队列并开始处理队列(如果尚未开始) Future speak(String text) async { if (text.isEmpty) return; // 添加到队列 _addToQueue(text); // 开始处理队列(如果尚未开始) _startQueueProcessingIfNeeded(); } /// 添加多条文本到队列并开始处理队列(如果尚未开始) Future speakTexts(List texts) async { if (texts.isEmpty) return; // 添加所有非空文本到队列 int addedCount = 0; for (final text in texts) { if (text.isNotEmpty) { _textQueue.add(text); addedCount++; } } if (addedCount > 0) { Logger.info('已添加$addedCount条文本到TTS队列'); // 开始处理队列(如果尚未开始) _startQueueProcessingIfNeeded(); } } /// 添加文本到队列 void _addToQueue(String text) { if (text.isEmpty) return; _textQueue.add(text); Logger.info('已添加文本到TTS队列: "${text.length > 20 ? "${text.substring(0, 20)}..." : text}"'); } /// 开始处理队列(如果尚未开始) void _startQueueProcessingIfNeeded() { // 如果队列为空,不需要处理 if (_textQueue.isEmpty) return; // 如果已经在处理队列或正在播放,不需要重新开始 if (_isProcessingQueue || _ttsState == TtsState.playing) return; // 开始处理队列 _isProcessingQueue = true; _processNextInQueue(); } /// 处理队列中的下一条文本 void _processNextInQueue() { // 如果队列为空,结束处理但不立即设置stopped状态 if (_textQueue.isEmpty) { _currentText = ''; _isProcessingQueue = false; // 只有当当前没有文本在播放时才设置为stopped状态 if (_currentText.isEmpty) { _ttsState = TtsState.stopped; Logger.info('TTS队列为空,设置为stopped状态'); } return; } // 获取队列中的第一条文本并播放 _speakNextText(); } /// 播放队列中的下一条文本 Future _speakNextText() async { if (_textQueue.isEmpty) { _isProcessingQueue = false; // 只有当当前没有文本在播放时才设置为stopped状态 if (_currentText.isEmpty) { _ttsState = TtsState.stopped; Logger.info('TTS队列播放完成,设置为stopped状态'); } return; } // 获取队列中的第一条文本 final text = _textQueue.removeAt(0); _currentText = text; try { // 设置TTS参数 await _flutterTts.setSpeechRate(_rate); await _flutterTts.setVolume(_volume); await _flutterTts.setPitch(_pitch); if (_currentVoice.isNotEmpty) { await _flutterTts.setVoice({"name": _currentVoice}); } // 播放文本 await _flutterTts.speak(text); Logger.info('正在播放文本,队列中还有${_textQueue.length}条待播放'); } catch (e) { Logger.error('TTS播放文本失败', e); // 清空当前文本 _currentText = ''; // 尝试播放下一个 _processNextInQueue(); } } /// 停止播放并清空队列 Future stop() async { try { await _flutterTts.stop(); // 重置队列处理状态 _textQueue.clear(); _currentText = ''; _isProcessingQueue = false; _ttsState = TtsState.stopped; Logger.info('已停止TTS播放并清空队列'); } catch (e) { Logger.error('停止TTS播放失败', e); } } /// 暂停播放 Future pause() async { try { await _flutterTts.pause(); _ttsState = TtsState.paused; } catch (e) { Logger.error('暂停TTS播放失败', e); } } /// 清空队列并停止播放 Future clearQueue() async { _textQueue.clear(); await stop(); Logger.info('已清空TTS队列'); } @override void onClose() { _flutterTts.stop(); super.onClose(); } } /// TTS状态枚举 enum TtsState { playing, stopped, paused, }