Files
biz_xfj_cloud/lib/common/utils/manage/tts_manage.dart
T
dzc 6ef0b6320f feat:日志查看
fix:真机bug
2026-07-27 13:28:35 +08:00

115 lines
3.2 KiB
Dart

import 'package:flutter_tts/flutter_tts.dart';
import 'package:pj_supermarket_cloud/common/index.dart';
// 文字转语音
class TtsManage {
static const _tag = "文字转语音";
static const _iflytekEngine = "com.iflytek.speechcloud";
static final FlutterTts _flutterTts = FlutterTts();
static bool _isInitialized = false;
static bool _isAvailable = false;
static Future<void>? _initializing;
/// 初始化 TTS。
///
/// 收银终端只使用讯飞引擎;未安装或初始化失败时直接禁用语音,
/// 避免 TTS 插件异常阻断应用启动和收银流程。
static Future<void> initialize() async {
if (_isInitialized) return;
if (_initializing != null) {
await _initializing;
return;
}
final initializing = _initialize();
_initializing = initializing;
try {
await initializing;
} finally {
_initializing = null;
}
}
static Future<void> _initialize() async {
try {
final engines = await _flutterTts.getEngines;
final hasIflytekEngine = engines is List &&
engines.any((engine) => engine.toString() == _iflytekEngine);
if (!hasIflytekEngine) {
logger.w("|$_tag|未安装讯飞TTS引擎,已禁用语音播报");
return;
}
await _flutterTts.setEngine(_iflytekEngine);
await _flutterTts.setLanguage("zh-CN");
await _flutterTts.setVolume(1.0);
await _flutterTts.setSpeechRate(0.95);
await _flutterTts.setPitch(2.0);
_isAvailable = true;
} catch (e, stack) {
logger.w("|$_tag|讯飞TTS初始化失败,已禁用语音播报error:|$e|stack:|$stack|");
} finally {
_isInitialized = true;
}
}
/// 播放文本;讯飞 TTS 不可用时静默跳过。
static Future<void> speak(String text) async {
await initialize();
if (!_isAvailable) return;
try {
await _flutterTts.speak(text, focus: true);
} catch (e, stack) {
logger.w("|$_tag|语音播放失败error:|$e|stack:|$stack|");
}
}
// 停止播放
static Future<void> stop() async {
if (!_isAvailable) return;
try {
await _flutterTts.stop();
} catch (e, stack) {
logger.w("|$_tag|停止语音播放失败error:|$e|stack:|$stack|");
}
}
// 释放资源
static Future<void> dispose() async {
await stop();
}
/// 将数字转换为中文读法(手机号码格式)
/// 特别处理:1读为"幺",其他数字正常读法
static String numberToChineseReading(String number) {
if (number.isEmpty) return "";
// 数字到中文读法的映射
const Map<String, String> digitToChinese = {
'0': '零',
'1': '幺', // 手机号中1读为"幺"
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
'7': '七',
'8': '八',
'9': '九',
};
// 逐位转换
StringBuffer result = StringBuffer();
for (int i = 0; i < number.length; i++) {
String digit = number[i];
if (digitToChinese.containsKey(digit)) {
result.write(digitToChinese[digit]);
} else {
// 如果不是数字,保持原样
result.write(digit);
}
}
return result.toString();
}
}