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.

154 lines
4.8 KiB

import 'dart:async';
import 'package:get/get.dart';
import '../../../data/services/flutter_asr_service.dart';
import '../../../core/utils/logger.dart';
/// Flutter ASR测试控制器,演示如何使用FlutterAsrService
class FlutterAsrTestController extends GetxController {
// 获取ASR服务实例
final FlutterAsrService _asrService = Get.find<FlutterAsrService>();
// 当前ASR状态 - 使用Rx包装以便UI可以响应变化
final Rx<AsrState> _asrState = AsrState.notInitialized.obs;
AsrState get asrState => _asrState.value;
// 当前识别的文本 - 使用Rx包装以便UI可以响应变化
final RxString _recognizedText = ''.obs;
String get recognizedText => _recognizedText.value;
// 识别准确度 - 使用Rx包装以便UI可以响应变化
final RxDouble _confidence = 0.0.obs;
double get confidence => _confidence.value;
// 是否正在监听 - 计算属性
bool get isListening => asrState == AsrState.listening;
// 是否可用 - 使用Rx包装以便UI可以响应变化
final RxBool _isAvailable = false.obs;
bool get isAvailable => _isAvailable.value;
// 可用的语言列表 - 使用Rx包装以便UI可以响应变化
final RxList<dynamic> _locales = <dynamic>[].obs;
List<dynamic> get locales => _locales;
// 当前选择的语言 - 使用Rx包装以便UI可以响应变化
final RxString _currentLocale = ''.obs;
String get currentLocale => _currentLocale.value;
// 历史记录 - 使用Rx包装以便UI可以响应变化
final RxList<String> _history = <String>[].obs;
List<String> get history => _history;
// 连续识别模式 - 使用Rx包装以便UI可以响应变化
final RxBool _continuousMode = false.obs;
bool get continuousMode => _continuousMode.value;
set continuousMode(bool value) => _continuousMode.value = value;
// 定时器,用于定期更新状态
late Timer _updateTimer;
// 识别结果订阅
StreamSubscription<String>? _resultSubscription;
@override
void onInit() {
super.onInit();
// 初始化状态
_updateState();
// 设置定时器,每300毫秒更新一次状态,确保UI能够及时反映服务状态变化
_updateTimer = Timer.periodic(const Duration(milliseconds: 300), (_) {
_updateState();
// 如果启用了连续模式,且当前不在监听状态,且ASR已初始化,则自动重新开始监听
if (_continuousMode.value &&
_asrState.value != AsrState.listening &&
_asrState.value != AsrState.notInitialized &&
_asrState.value != AsrState.error &&
_isAvailable.value) {
_restartListening();
}
});
// 订阅识别结果流
_resultSubscription = _asrService.recognitionResults.listen(_onFinalResult);
}
/// 更新控制器状态,从服务获取最新状态
void _updateState() {
_asrState.value = _asrService.asrState;
_recognizedText.value = _asrService.lastWords;
_confidence.value = _asrService.confidence;
_isAvailable.value = _asrService.isAvailable;
_locales.assignAll(_asrService.locales);
_currentLocale.value = _asrService.currentLocale;
}
/// 开始语音识别
Future<bool> startListening() async {
return await _asrService.startListening();
}
/// 停止语音识别
Future<void> stopListening() async {
await _asrService.stopListening();
}
/// 取消语音识别
Future<void> cancelListening() async {
await _asrService.cancelListening();
}
/// 切换连续识别模式
void toggleContinuousMode() {
_continuousMode.value = !_continuousMode.value;
Logger.info('连续识别模式: ${_continuousMode.value ? '开启' : '关闭'}');
// 如果开启连续模式且当前未在监听,则开始监听
if (_continuousMode.value && !isListening && _isAvailable.value) {
startListening();
}
}
/// 重新开始监听(用于连续模式)
Future<void> _restartListening() async {
// 添加小延迟,避免过于频繁的重启
await Future.delayed(const Duration(milliseconds: 300));
if (_continuousMode.value && !isListening && _isAvailable.value) {
Logger.info('连续模式: 重新开始监听');
await startListening();
}
}
/// 设置语言
void setLocale(String localeId) {
_asrService.setLocale(localeId);
_currentLocale.value = localeId;
}
/// 处理最终识别结果
void _onFinalResult(String result) {
if (result.isNotEmpty) {
// 添加到历史记录
_history.insert(0, result);
// 限制历史记录数量
if (_history.length > 10) {
_history.removeLast();
}
}
}
/// 清空历史记录
void clearHistory() {
_history.clear();
}
@override
void onClose() {
_updateTimer.cancel();
_resultSubscription?.cancel();
super.onClose();
}
}