import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../data/services/microsoft_tts_service.dart'; /// 微软 TTS 连续语音输出示例页面 class MicrosoftTtsContinuousExample extends StatefulWidget { const MicrosoftTtsContinuousExample({Key? key}) : super(key: key); @override State createState() => _MicrosoftTtsContinuousExampleState(); } class _MicrosoftTtsContinuousExampleState extends State { final MicrosoftTtsService _ttsService = Get.find(); // 语音列表 final List> _voices = [ {'name': '晓晓(女声)', 'value': 'zh-CN-XiaoxiaoNeural'}, {'name': '云扬(男声)', 'value': 'zh-CN-YunyangNeural'}, {'name': '晓双(女声)', 'value': 'zh-CN-XiaoshuangNeural'}, {'name': '云皓(男声)', 'value': 'zh-CN-YunhaoNeural'}, {'name': '晓墨(女声)', 'value': 'zh-CN-XiaomoNeural'}, {'name': '云泽(男声)', 'value': 'zh-CN-YunzeNeural'}, ]; String _selectedVoice = 'zh-CN-XiaoxiaoNeural'; double _rate = 0; double _pitch = 0; bool _isLoading = false; String _statusMessage = ''; // 预设的连续语音文本 final List _presetTexts = [ '欢迎使用微软语音合成服务,这是连续语音输出的第一段文本。', '这是第二段文本,用于测试连续语音输出功能。', '现在是第三段文本,我们正在测试微软语音合成服务的连续合成能力。', '最后一段测试文本,感谢您的收听。', ]; // 自定义文本列表 final List _textControllers = []; @override void initState() { super.initState(); // 初始化文本控制器 for (final text in _presetTexts) { _textControllers.add(TextEditingController(text: text)); } } @override void dispose() { // 释放文本控制器 for (final controller in _textControllers) { controller.dispose(); } super.dispose(); } /// 播放连续文本 Future _speakContinuous() async { final texts = _textControllers.map((controller) => controller.text).toList(); if (texts.every((text) => text.isEmpty)) { _showSnackBar('请至少输入一段文本'); return; } setState(() { _isLoading = true; _statusMessage = '正在合成语音...'; }); try { // 设置语音 await _ttsService.setVoice(_selectedVoice); // 停止之前的播放 await _ttsService.stop(); // 连续播放多段文本 final result = await _ttsService.speakMultiple( texts.where((text) => text.isNotEmpty).toList(), rate: _rate.round(), pitch: _pitch.round(), ); setState(() { _statusMessage = result ? '语音合成已加入队列' : '语音合成失败'; }); } catch (e) { _showSnackBar('语音合成失败: $e'); } finally { setState(() { _isLoading = false; }); } } /// 停止播放 Future _stopSpeaking() async { try { await _ttsService.stop(); setState(() { _statusMessage = '语音合成已停止'; }); } catch (e) { _showSnackBar('停止语音合成失败: $e'); } } /// 添加文本输入框 void _addTextInput() { setState(() { _textControllers.add(TextEditingController()); }); } /// 删除文本输入框 void _removeTextInput(int index) { if (_textControllers.length <= 1) { _showSnackBar('至少需要保留一个文本输入框'); return; } setState(() { _textControllers[index].dispose(); _textControllers.removeAt(index); }); } /// 显示提示信息 void _showSnackBar(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message)), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('微软连续语音合成示例'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: ListView( children: [ // 语音选择 DropdownButtonFormField( value: _selectedVoice, decoration: const InputDecoration( labelText: '选择语音', border: OutlineInputBorder(), ), items: _voices.map((voice) { return DropdownMenuItem( value: voice['value'], child: Text(voice['name']!), ); }).toList(), onChanged: (value) { if (value != null) { setState(() { _selectedVoice = value; }); } }, ), const SizedBox(height: 16), // 语速调节 Row( children: [ const Text('语速:'), Expanded( child: Slider( min: -100, max: 100, divisions: 20, value: _rate, label: _rate.round().toString(), onChanged: (value) { setState(() { _rate = value; }); }, ), ), Text('${_rate.round()}%'), ], ), // 音调调节 Row( children: [ const Text('音调:'), Expanded( child: Slider( min: -100, max: 100, divisions: 20, value: _pitch, label: _pitch.round().toString(), onChanged: (value) { setState(() { _pitch = value; }); }, ), ), Text('${_pitch.round()}%'), ], ), const SizedBox(height: 16), // 文本输入列表标题 Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( '连续语音文本', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ElevatedButton.icon( onPressed: _addTextInput, icon: const Icon(Icons.add), label: const Text('添加文本'), ), ], ), const SizedBox(height: 8), // 文本输入列表 ...List.generate(_textControllers.length, (index) { return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: TextField( controller: _textControllers[index], maxLines: 3, decoration: InputDecoration( labelText: '文本 ${index + 1}', border: const OutlineInputBorder(), ), ), ), IconButton( icon: const Icon(Icons.delete), onPressed: () => _removeTextInput(index), ), ], ), ); }), const SizedBox(height: 16), // 操作按钮 Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( child: ElevatedButton.icon( onPressed: _isLoading ? null : _speakContinuous, icon: const Icon(Icons.play_arrow), label: const Text('播放连续语音'), ), ), const SizedBox(width: 8), Expanded( child: ElevatedButton.icon( onPressed: _stopSpeaking, icon: const Icon(Icons.stop), label: const Text('停止'), style: ElevatedButton.styleFrom( backgroundColor: Colors.red, ), ), ), ], ), const SizedBox(height: 16), // 状态信息 Obx(() => Text( _ttsService.isSpeaking.value ? '正在播放语音...' : _statusMessage, style: const TextStyle(fontStyle: FontStyle.italic), textAlign: TextAlign.center, )), ], ), ), ); } }