flutter_baidu_speech_tts 1.0.3
flutter_baidu_speech_tts: ^1.0.3 copied to clipboard
Baidu TTS plugin for Flutter: online, offline and mixed speech synthesis on Android, iOS and HarmonyOS.
example/lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_baidu_speech_tts/flutter_baidu_speech_tts.dart';
import 'utils/tts_config.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final FlutterBaiduTts _tts = FlutterBaiduTts();
final TextEditingController _textController = TextEditingController(
text: 'Hello, this is Flutter Baidu TTS.',
);
StreamSubscription<BaiduTtsEvent>? _eventSubscription;
final List<String> _logs = <String>[];
String _cuid = ''; // 指纹信息
@override
void initState() {
super.initState();
_refreshCuid();
}
@override
void dispose() {
_eventSubscription?.cancel();
_textController.dispose();
super.dispose();
}
Future<void> _appendLog(String message) async {
if (!mounted) {
return;
}
setState(() {
_logs.insert(
0,
'${DateTime.now().toIso8601String().substring(11, 19)} $message',
);
if (_logs.length > 50) {
_logs.removeLast();
}
});
}
Future<void> _refreshCuid() async {
try {
final String? cuid = await _tts.getCuid();
if (!mounted) return;
setState(() {
_cuid = cuid ?? '';
});
} catch (e) {
if (!mounted) return;
setState(() {
_cuid = '';
});
await _appendLog('getCuid error => $e');
}
}
Future<void> _ensureEventSubscription() async {
if (_eventSubscription != null) {
return;
}
_eventSubscription = _tts.typedEvents.listen(
(BaiduTtsEvent event) {
_appendLog('event => ${event.event ?? event.message} | ${event.raw}');
},
onError: (Object error) {
_appendLog('event error => $error');
},
);
}
Future<void> _runAction(
String label,
Future<BaiduTtsResult> Function() action,
) async {
final result = await action();
await _appendLog('$label => $result');
if (!mounted) {
return;
}
}
Future<void> _initialize() async {
await _ensureEventSubscription();
await _runAction(
'initialize',
() => _tts.initializeWithConfig(TtsConfig.buildInitConfig()),
);
// cuid 通常在 SDK 初始化后才可用,初始化完成后再刷新一次。
await _refreshCuid();
}
Future<void> _speak() async {
await _runAction(
'speak',
() => _tts.speakText(_textController.text.trim(),
mode: BaiduTtsMode.offline),
);
}
Future<void> _synthesize() async {
await _runAction(
'synthesize',
() => _tts.synthesizeText(
_textController.text.trim(),
),
);
}
Future<void> _pause() async {
await _runAction('pause', _tts.pauseTts);
}
Future<void> _resume() async {
await _runAction('resume', _tts.resumeTts);
}
Future<void> _stop() async {
await _runAction('stop', _tts.stopTts);
}
Future<void> _release() async {
await _runAction('release', _tts.releaseTts);
}
Widget _button(IconData icon, String label, VoidCallback onPressed) {
return SizedBox(
width: 160,
child: ElevatedButton.icon(
onPressed: onPressed,
icon: Icon(icon, size: 18),
label: Text(label),
),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: true,
home: Scaffold(
appBar: AppBar(
title: const Text('Baidu TTS Flutter Demo'),
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Text(
'设备cuid:${_cuid.isEmpty ? '(未获取,请先 Initialize)' : _cuid}',
),
),
const SizedBox(width: 8),
IconButton(
tooltip: '刷新 cuid',
icon: const Icon(Icons.refresh, size: 18),
onPressed: _refreshCuid,
),
],
),
TextField(
controller: _textController,
maxLines: 4,
decoration: const InputDecoration(
labelText: 'Text',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
Wrap(
spacing: 8,
runSpacing: 8,
children: <Widget>[
_button(Icons.tune, 'Initialize', _initialize),
_button(Icons.volume_up, 'Speak', _speak),
_button(Icons.graphic_eq, 'Synthesize', _synthesize),
_button(Icons.pause, 'Pause', _pause),
_button(Icons.refresh, 'Resume', _resume),
_button(Icons.stop, 'Stop', _stop),
_button(Icons.delete_outline, 'Release', _release),
],
),
const SizedBox(height: 16),
Row(
children: <Widget>[
Text('Event log',
style: Theme.of(context).textTheme.titleMedium),
const Spacer(),
IconButton(
tooltip: '清空日志',
icon: const Icon(Icons.delete_sweep, size: 20),
onPressed: () => setState(() => _logs.clear()),
),
],
),
const SizedBox(height: 8),
Container(
constraints: const BoxConstraints(minHeight: 180),
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
border: Border.all(color: Colors.black26),
borderRadius: BorderRadius.circular(6),
),
child: SelectableText(
_logs.isEmpty ? 'No events yet.' : _logs.join('\n'),
),
),
],
),
),
),
),
);
}
}