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.

202 lines
5.7 KiB

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../data/services/microsoft_tts_service.dart';
/// 微软 TTS 示例页面
class MicrosoftTtsExample extends StatefulWidget {
const MicrosoftTtsExample({Key? key}) : super(key: key);
@override
State<MicrosoftTtsExample> createState() => _MicrosoftTtsExampleState();
}
class _MicrosoftTtsExampleState extends State<MicrosoftTtsExample> {
final TextEditingController _textController = TextEditingController();
final MicrosoftTtsService _ttsService = Get.find<MicrosoftTtsService>();
// 语音列表
final List<Map<String, String>> _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 = '';
@override
void initState() {
super.initState();
_textController.text = '欢迎使用微软语音合成服务,这是一个示例文本。';
}
@override
void dispose() {
_textController.dispose();
super.dispose();
}
/// 播放文本
Future<void> _speakText() async {
if (_textController.text.isEmpty) {
_showSnackBar('请输入要合成的文本');
return;
}
setState(() {
_isLoading = true;
_statusMessage = '正在合成语音...';
});
try {
// 设置语音
await _ttsService.setVoice(_selectedVoice);
// 生成 SSML
final ssml = _ttsService.generateSsml(
text: _textController.text,
rate: _rate.round(),
pitch: _pitch.round(),
);
// 播放 SSML
final result = await _ttsService.speakSsml(ssml);
setState(() {
_statusMessage = result;
});
} catch (e) {
_showSnackBar('语音合成失败: $e');
} finally {
setState(() {
_isLoading = false;
});
}
}
/// 显示提示信息
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: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 文本输入框
TextField(
controller: _textController,
maxLines: 5,
decoration: const InputDecoration(
labelText: '输入要合成的文本',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
// 语音选择
DropdownButtonFormField<String>(
value: _selectedVoice,
decoration: const InputDecoration(
labelText: '选择语音',
border: OutlineInputBorder(),
),
items: _voices.map((voice) {
return DropdownMenuItem<String>(
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),
// 播放按钮
ElevatedButton(
onPressed: _isLoading ? null : _speakText,
child: _isLoading
? const CircularProgressIndicator()
: const Text('播放'),
),
const SizedBox(height: 16),
// 状态信息
Text(
_statusMessage,
style: const TextStyle(fontStyle: FontStyle.italic),
textAlign: TextAlign.center,
),
],
),
),
);
}
}