You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
279 lines
7.4 KiB
279 lines
7.4 KiB
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'dart:async';
|
|
import 'package:flutter/foundation.dart';
|
|
import '../../../data/services/azure_tts_service.dart';
|
|
import '../../../core/utils/logger.dart';
|
|
|
|
class AzureTtsTestController extends GetxController {
|
|
// 使用优化后的 AzureTtsService
|
|
final AzureTtsService _ttsService = Get.put(AzureTtsService());
|
|
|
|
// 可观察状态
|
|
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 isLoadingVoices = false.obs;
|
|
final RxList<String> availableVoices = <String>[
|
|
'zh-CN-XiaoxiaoNeural',
|
|
'zh-CN-YunxiNeural',
|
|
'zh-CN-YunyangNeural',
|
|
].obs;
|
|
final Rx<String> selectedVoice = 'zh-CN-XiaoxiaoNeural'.obs;
|
|
|
|
// 语音参数
|
|
final rate = 0.obs;
|
|
final pitch = 0.obs;
|
|
final volume = 100.obs;
|
|
|
|
// 固定的播报内容
|
|
final RxList<String> speechTexts = <String>[
|
|
'这是第一条Azure语音播报测试,请听取合成效果。',
|
|
'这是第二条Azure语音播报测试,Azure语音合成支持连续多条播报。',
|
|
'这是第三条Azure语音播报测试,可以测试语音合成的流畅度和连贯性。',
|
|
'这是第四条Azure语音播报测试,感谢您的使用。',
|
|
].obs;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
|
|
// 初始化UI状态
|
|
isSpeaking.value = false;
|
|
isAudioPlaying.value = false;
|
|
errorMessage.value = '';
|
|
isLoading.value = false;
|
|
|
|
// 监听TTS播放状态
|
|
ever(_ttsService.isSpeaking, (bool playing) {
|
|
isAudioPlaying.value = playing;
|
|
if (!playing && currentPlayingIndex.value >= 0) {
|
|
// 如果播放结束,重置当前播放索引
|
|
currentPlayingIndex.value = -1;
|
|
}
|
|
});
|
|
|
|
// 启动播放状态检查定时器
|
|
_startPlaybackCheckTimer();
|
|
|
|
// 初始化TTS服务
|
|
_initializeTtsService();
|
|
}
|
|
|
|
/// 初始化TTS服务
|
|
Future<void> _initializeTtsService() async {
|
|
try {
|
|
isLoading.value = true;
|
|
errorMessage.value = '';
|
|
statusMessage.value = '正在初始化...';
|
|
|
|
// 初始化TTS服务
|
|
final result = await _ttsService.initialize();
|
|
|
|
if (result) {
|
|
// 设置默认语音
|
|
await _ttsService.setVoice(selectedVoice.value);
|
|
|
|
// 设置默认参数
|
|
await _ttsService.setSpeechParams(
|
|
rate: rate.value,
|
|
pitch: pitch.value,
|
|
volume: volume.value,
|
|
);
|
|
|
|
statusMessage.value = '已连接';
|
|
} else {
|
|
statusMessage.value = '连接失败';
|
|
errorMessage.value = '初始化TTS服务失败';
|
|
}
|
|
|
|
isLoading.value = false;
|
|
} catch (e) {
|
|
isLoading.value = false;
|
|
statusMessage.value = '连接失败';
|
|
errorMessage.value = '初始化TTS服务失败: $e';
|
|
Logger.error('初始化TTS服务失败: $e');
|
|
}
|
|
}
|
|
|
|
/// 切换语音
|
|
Future<void> changeVoice(String voice) async {
|
|
try {
|
|
isLoading.value = true;
|
|
errorMessage.value = '';
|
|
|
|
selectedVoice.value = voice;
|
|
|
|
// 设置语音
|
|
final result = await _ttsService.setVoice(voice);
|
|
|
|
if (result) {
|
|
statusMessage.value = '已设置语音: $voice';
|
|
} else {
|
|
errorMessage.value = '设置语音失败';
|
|
}
|
|
|
|
isLoading.value = false;
|
|
} catch (e) {
|
|
isLoading.value = false;
|
|
errorMessage.value = '设置语音失败: $e';
|
|
Logger.error('设置语音失败: $e');
|
|
}
|
|
}
|
|
|
|
/// 设置语音参数
|
|
Future<void> setSpeechParams({int? newRate, int? newPitch, int? newVolume}) async {
|
|
try {
|
|
if (newRate != null) rate.value = newRate;
|
|
if (newPitch != null) pitch.value = newPitch;
|
|
if (newVolume != null) volume.value = newVolume;
|
|
|
|
// 设置语音参数
|
|
final result = await _ttsService.setSpeechParams(
|
|
rate: rate.value,
|
|
pitch: pitch.value,
|
|
volume: volume.value,
|
|
);
|
|
|
|
if (result) {
|
|
statusMessage.value = '已设置语音参数';
|
|
} else {
|
|
errorMessage.value = '设置语音参数失败';
|
|
}
|
|
} catch (e) {
|
|
errorMessage.value = '设置语音参数失败: $e';
|
|
Logger.error('设置语音参数失败: $e');
|
|
}
|
|
}
|
|
|
|
/// 更新UI状态
|
|
void updateUIState() {
|
|
// 强制更新UI
|
|
update();
|
|
}
|
|
|
|
/// 播放单条文本
|
|
Future<void> playSingle(int index) async {
|
|
if (index < 0 || index >= speechTexts.length) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
isSpeaking.value = true;
|
|
isAudioPlaying.value = true;
|
|
errorMessage.value = '';
|
|
currentPlayingIndex.value = index;
|
|
statusMessage.value = '正在合成...';
|
|
|
|
final text = speechTexts[index];
|
|
|
|
// 播放文本
|
|
await _ttsService.speak(text);
|
|
|
|
statusMessage.value = '合成完成';
|
|
|
|
} catch (e) {
|
|
errorMessage.value = '播放出错';
|
|
statusMessage.value = '错误';
|
|
Logger.error('播放出错: $e');
|
|
} finally {
|
|
isSpeaking.value = false;
|
|
if (!_ttsService.isSpeaking.value) {
|
|
isAudioPlaying.value = false;
|
|
currentPlayingIndex.value = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 启动播放状态检查定时器
|
|
void _startPlaybackCheckTimer() {
|
|
_playbackCheckTimer?.cancel();
|
|
_playbackCheckTimer = Timer.periodic(const Duration(milliseconds: 200), (timer) {
|
|
// 更新实际播放状态
|
|
final actuallyPlaying = _ttsService.isSpeaking.value;
|
|
isAudioPlaying.value = actuallyPlaying;
|
|
|
|
// 如果不再播放,确保重置状态
|
|
if (!actuallyPlaying && isSpeaking.value) {
|
|
// 播放已完成,重置状态
|
|
isSpeaking.value = false;
|
|
currentPlayingIndex.value = -1;
|
|
// 更新UI
|
|
update();
|
|
}
|
|
});
|
|
}
|
|
|
|
/// 连续播放所有文本
|
|
Future<void> speakContinuousTexts() async {
|
|
if (isAudioPlaying.value || isLoading.value) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
isSpeaking.value = true;
|
|
errorMessage.value = '';
|
|
statusMessage.value = '开始连续播放';
|
|
|
|
// 播放所有文本
|
|
await _ttsService.speakMultiple(speechTexts.toList());
|
|
|
|
statusMessage.value = '连续播放完成';
|
|
|
|
} catch (e) {
|
|
errorMessage.value = '连续播放出错';
|
|
statusMessage.value = '错误';
|
|
Logger.error('连续播放出错: $e');
|
|
} finally {
|
|
isSpeaking.value = false;
|
|
}
|
|
}
|
|
|
|
/// 停止播放
|
|
Future<void> stopSpeaking() async {
|
|
try {
|
|
final result = await _ttsService.stop();
|
|
|
|
if (result) {
|
|
isSpeaking.value = false;
|
|
isAudioPlaying.value = false;
|
|
currentPlayingIndex.value = -1;
|
|
statusMessage.value = '已停止';
|
|
} else {
|
|
errorMessage.value = '停止播放失败';
|
|
}
|
|
} catch (e) {
|
|
errorMessage.value = '停止播放出错';
|
|
Logger.error('停止播放出错: $e');
|
|
}
|
|
}
|
|
|
|
/// 切换启用状态
|
|
void toggleEnabled() {
|
|
_ttsService.toggleEnabled();
|
|
statusMessage.value = _ttsService.isEnabled.value ? '已启用' : '已禁用';
|
|
}
|
|
|
|
@override
|
|
void onClose() {
|
|
// 取消定时器
|
|
_playbackCheckTimer?.cancel();
|
|
|
|
// 停止播放
|
|
_ttsService.stop();
|
|
|
|
super.onClose();
|
|
}
|
|
}
|