import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'dart:async'; import 'package:flutter/foundation.dart'; import '../../../data/services/volcano_tts_api_service.dart'; class VolcanoTtsTestController extends GetxController { final VolcanoTtsApiService _ttsService = Get.find(); // 可观察状态 final isSpeaking = false.obs; final errorMessage = ''.obs; final isLoading = false.obs; final statusMessage = '未连接'.obs; // 添加实际音频播放状态 final isAudioPlaying = false.obs; // 播放状态检查定时器 Timer? _playbackCheckTimer; // 当前播放的索引 final currentPlayingIndex = RxInt(-1); // 当前使用的语音 - 使用预定义的值 final currentVoice = 'zh_female_meilinvyou_moon_bigtts'.obs; // 可用的语音列表 final List> availableVoices = [ {'id': 'zh_female_meilinvyou_moon_bigtts', 'name': '魅力女友'}, {'id': 'zh_male_shaonianzixin_moon_bigtts', 'name': '少年梓辛/Brayan'}, {'id': 'zh_male_beijingxiaoye_moon_bigtts', 'name': '北京小爷'}, {'id': 'zh_female_daimengchuanmei_moon_bigtts', 'name': '呆萌川妹'}, {'id': 'zh_female_wanqudashu_moon_bigtts', 'name': '湾区大叔'}, {'id': 'zh_female_sajiaonvyou_moon_bigtts', 'name': '撒娇女友'}, {'id': 'zh_male_shenyeboke_moon_bigtts', 'name': '深夜播客'}, ]; // 固定的播报内容 final RxList speechTexts = [ '这是第一条播报测试,请听取合成效果。', '这是第二条播报测试,火山语音合成支持连续多条播报。', '这是第三条播报测试,可以测试语音合成的流畅度和连贯性。', '这是第四条播报测试,感谢您的使用。', ].obs; // 事件订阅 StreamSubscription? _eventSubscription; @override void onInit() { super.onInit(); // 初始化UI状态 isSpeaking.value = false; isAudioPlaying.value = false; errorMessage.value = ''; isLoading.value = false; // 监听TTS服务状态 ever(_ttsService.isConnected, (bool connected) { if (connected) { statusMessage.value = '已连接'; } else { statusMessage.value = '未连接'; isSpeaking.value = false; isAudioPlaying.value = false; } }); // 监听TTS合成状态 ever(_ttsService.isSynthesizing, (bool synthesizing) { isSpeaking.value = synthesizing; }); // 监听TTS播放状态 ever(_ttsService.isPlaying.obs, (bool playing) { isAudioPlaying.value = playing; if (!playing && currentPlayingIndex.value >= 0) { // 如果播放结束,重置当前播放索引 currentPlayingIndex.value = -1; } }); // 设置事件监听 _setupEventListener(); // 连接到TTS服务 _connectToTtsService(); // 启动播放状态检查定时器 _startPlaybackCheckTimer(); } // 设置事件监听 void _setupEventListener() { _eventSubscription?.cancel(); _eventSubscription = _ttsService.eventStream.listen(_handleEvent); } // 处理事件 void _handleEvent(Map event) { final eventType = event['eventType']; switch (eventType) { case 'connectionStarted': statusMessage.value = '连接成功'; errorMessage.value = ''; break; case 'connectionFailed': statusMessage.value = '连接失败'; errorMessage.value = event['error'] ?? '未知错误'; break; case 'sessionStarted': statusMessage.value = '会话开始'; errorMessage.value = ''; break; case 'sessionFailed': statusMessage.value = '会话失败'; errorMessage.value = event['error'] ?? '未知错误'; currentPlayingIndex.value = -1; break; case 'ttsSentenceStart': statusMessage.value = '开始合成'; break; case 'ttsSentenceEnd': statusMessage.value = '合成完成'; break; case 'sessionFinished': statusMessage.value = '会话结束'; currentPlayingIndex.value = -1; break; case 'connectionFinished': statusMessage.value = '连接关闭'; currentPlayingIndex.value = -1; break; case 'error': statusMessage.value = '错误'; errorMessage.value = event['error'] ?? '未知错误'; break; case 'disconnected': statusMessage.value = '连接已断开'; currentPlayingIndex.value = -1; break; default: statusMessage.value = '事件: $eventType'; break; } // 强制更新UI update(); } // 连接到TTS服务 Future _connectToTtsService() async { try { isLoading.value = true; statusMessage.value = '正在连接...'; final success = await _ttsService.connect(); if (!success) { statusMessage.value = '连接失败'; errorMessage.value = '无法连接到火山语音服务'; } } catch (e) { statusMessage.value = '连接错误'; errorMessage.value = e.toString(); } finally { isLoading.value = false; } } /// 更新UI状态 void updateUIState() { // 强制更新UI update(); } /// 播放单条文本 Future playSingle(int index) async { if (index < 0 || index >= speechTexts.length) { return; } try { isSpeaking.value = true; isAudioPlaying.value = true; errorMessage.value = ''; currentPlayingIndex.value = index; final text = speechTexts[index]; final speaker = currentVoice.value; // 确保TTS服务已连接 if (!_ttsService.isConnected.value) { await _connectToTtsService(); } // 开始会话 await _ttsService.startSession(speaker); // 播放文本 await _ttsService.speak(text, speaker: speaker); // 结束会话 await _ttsService.endSession(); // 确保播放列表被清空 await _ttsService.stop(); } catch (e) { errorMessage.value = '播放出错'; if (kDebugMode) { print('播放出错: $e'); } } finally { isSpeaking.value = false; isAudioPlaying.value = false; currentPlayingIndex.value = -1; } } // 启动播放状态检查定时器 void _startPlaybackCheckTimer() { _playbackCheckTimer?.cancel(); _playbackCheckTimer = Timer.periodic(const Duration(milliseconds: 200), (timer) { // 更新实际播放状态 final actuallyPlaying = _ttsService.isPlaying; isAudioPlaying.value = actuallyPlaying; // 如果不再播放,确保重置状态 if (!actuallyPlaying && isSpeaking.value) { // 检查是否真的播放完成了 if (!_ttsService.isSynthesizing.value && currentPlayingIndex.value >= 0) { // 播放已完成,重置状态 isSpeaking.value = false; currentPlayingIndex.value = -1; // 更新UI update(); } } }); } /// 连续播放所有文本 Future speakContinuousTexts() async { if (isAudioPlaying.value || isLoading.value) { return; } try { isLoading.value = true; isSpeaking.value = true; isAudioPlaying.value = true; errorMessage.value = ''; // 确保TTS服务已连接 if (!_ttsService.isConnected.value) { await _connectToTtsService(); } final speaker = currentVoice.value; // 停止之前的播放 await _ttsService.stop(); // 开始会话 await _ttsService.startSession(speaker); // 连续播放所有文本 for (int i = 0; i < speechTexts.length; i++) { // 如果播放被中断,退出循环 if (!isSpeaking.value) break; currentPlayingIndex.value = i; statusMessage.value = '正在播放第 ${i + 1}/${speechTexts.length} 条文本'; // 播放当前文本 await _ttsService.speak(speechTexts[i], speaker: speaker); } // 结束会话 await _ttsService.endSession(); statusMessage.value = '播放完成'; } catch (e) { errorMessage.value = '播放出错'; if (kDebugMode) { print('连续播放出错: $e'); } // 尝试结束会话,忽略可能的错误 try { await _ttsService.endSession(); } catch (_) { // 忽略结束会话时的错误 } } finally { currentPlayingIndex.value = -1; isSpeaking.value = false; isLoading.value = false; // 确保最终状态正确 isAudioPlaying.value = false; // 强制更新UI update(); } } /// 停止播放 void stopSpeaking() async { try { isSpeaking.value = false; statusMessage.value = '正在停止播放...'; // 停止播放 await _ttsService.stop(); // 结束会话 await _ttsService.endSession(); // 重置UI状态 currentPlayingIndex.value = -1; statusMessage.value = '已停止播放'; } catch (e) { if (kDebugMode) { print('停止播放出错: $e'); } errorMessage.value = '停止播放出错'; } finally { isSpeaking.value = false; isLoading.value = false; isAudioPlaying.value = false; } } // 设置当前语音 void setVoice(String voiceId) { currentVoice.value = voiceId; } // 获取当前语音名称 String getCurrentVoiceName() { final voice = availableVoices.firstWhere( (v) => v['id'] == currentVoice.value, orElse: () => {'id': currentVoice.value, 'name': '未知语音'}, ); return voice['name'] ?? '未知语音'; } @override void onClose() { // 取消事件订阅 _eventSubscription?.cancel(); // 取消播放状态检查定时器 _playbackCheckTimer?.cancel(); // 断开TTS服务连接 _ttsService.disconnect(); super.onClose(); } }