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.
218 lines
6.7 KiB
218 lines
6.7 KiB
import 'dart:async';
|
|
import 'package:get/get.dart';
|
|
import '../../../data/services/volcano_asr_api_service.dart';
|
|
import '../../../core/utils/logger.dart';
|
|
|
|
class VolcanoAsrTestController extends GetxController {
|
|
// Observable variables
|
|
final isListening = false.obs;
|
|
final errorMessage = ''.obs;
|
|
final recognitionResults = <String>[].obs;
|
|
final isContinuous = false.obs;
|
|
final connectionStatus = 'Disconnected'.obs;
|
|
|
|
// 当前识别中的文本
|
|
final currentRecognizingText = ''.obs;
|
|
|
|
// 当前识别的索引
|
|
int _currentRecognitionIndex = -1;
|
|
|
|
// Services
|
|
late final VolcanoAsrApiService _asrService;
|
|
|
|
// Stream subscriptions
|
|
StreamSubscription? _recognitionSubscription;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
|
|
// Initialize the ASR service
|
|
_asrService = Get.find<VolcanoAsrApiService>();
|
|
|
|
// Subscribe to recognition stream
|
|
_recognitionSubscription = _asrService.recognitionStream.listen((event) {
|
|
switch (event.type) {
|
|
case RecognitionEventType.started:
|
|
// 开始新的识别
|
|
if (isContinuous.value) {
|
|
// 如果是连续模式,检查是否需要创建新条目
|
|
if (_currentRecognitionIndex == -1 || recognitionResults.isEmpty) {
|
|
// 如果没有当前识别索引或结果列表为空,添加新条目
|
|
recognitionResults.add('');
|
|
_currentRecognitionIndex = recognitionResults.length - 1;
|
|
}
|
|
} else {
|
|
// 非连续模式,清空结果并添加新条目
|
|
recognitionResults.clear();
|
|
recognitionResults.add('');
|
|
_currentRecognitionIndex = 0;
|
|
}
|
|
currentRecognizingText.value = '';
|
|
break;
|
|
|
|
case RecognitionEventType.recognizing:
|
|
// 实时识别结果
|
|
if (event.text.isNotEmpty) {
|
|
currentRecognizingText.value = event.text;
|
|
|
|
// 确保有一个当前条目可以更新
|
|
if (_currentRecognitionIndex == -1 || _currentRecognitionIndex >= recognitionResults.length) {
|
|
recognitionResults.add('');
|
|
_currentRecognitionIndex = recognitionResults.length - 1;
|
|
}
|
|
|
|
// 更新当前条目
|
|
recognitionResults[_currentRecognitionIndex] = event.text;
|
|
}
|
|
break;
|
|
|
|
case RecognitionEventType.finalResult:
|
|
// 最终识别结果
|
|
if (event.text.isNotEmpty) {
|
|
// 确保有一个当前条目可以更新
|
|
if (_currentRecognitionIndex == -1 || _currentRecognitionIndex >= recognitionResults.length) {
|
|
recognitionResults.add(event.text);
|
|
_currentRecognitionIndex = recognitionResults.length - 1;
|
|
} else {
|
|
// 更新当前条目为最终结果
|
|
recognitionResults[_currentRecognitionIndex] = event.text;
|
|
}
|
|
|
|
// 收到最终结果后,重置索引,为新句子做准备
|
|
_currentRecognitionIndex = -1;
|
|
|
|
// 清空当前识别文本
|
|
currentRecognizingText.value = '';
|
|
}
|
|
break;
|
|
|
|
case RecognitionEventType.error:
|
|
// 错误处理
|
|
if (event.error != null) {
|
|
errorMessage.value = event.error!;
|
|
|
|
// 如果有错误且正在识别,停止识别
|
|
if (isListening.value) {
|
|
isListening.value = false;
|
|
connectionStatus.value = 'Disconnected';
|
|
|
|
// 停止语音识别,不尝试重启
|
|
_asrService.stopRecognition();
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
// 注意:处理其他事件类型
|
|
default:
|
|
// 其他事件类型不做特殊处理
|
|
break;
|
|
}
|
|
});
|
|
|
|
// Update connection status based on service state
|
|
ever(_asrService.isListening, (bool listening) {
|
|
isListening.value = listening;
|
|
connectionStatus.value = listening ? 'Connected' : 'Disconnected';
|
|
});
|
|
|
|
// Update error message from service
|
|
if (_asrService.errorMessage.isNotEmpty) {
|
|
errorMessage.value = _asrService.errorMessage;
|
|
}
|
|
}
|
|
|
|
@override
|
|
void onClose() {
|
|
// Cancel all subscriptions
|
|
_recognitionSubscription?.cancel();
|
|
|
|
// Disconnect from the ASR service if still connected
|
|
if (_asrService.isConnected) {
|
|
stopListening();
|
|
}
|
|
|
|
super.onClose();
|
|
}
|
|
|
|
// Start listening for speech
|
|
Future<void> startListening() async {
|
|
try {
|
|
// Clear previous error message
|
|
errorMessage.value = '';
|
|
|
|
// 如果是新的识别会话
|
|
if (!isListening.value) {
|
|
currentRecognizingText.value = '';
|
|
|
|
// 如果不是连续识别模式,则清空结果列表
|
|
if (!isContinuous.value) {
|
|
recognitionResults.clear();
|
|
_currentRecognitionIndex = -1;
|
|
}
|
|
}
|
|
|
|
// 使用麦克风录音功能
|
|
final success = await _asrService.startRecognition(
|
|
sampleRate: 16000,
|
|
bitsPerSample: 16,
|
|
channels: 1,
|
|
format: 'pcm',
|
|
codec: 'raw',
|
|
enablePunc: true,
|
|
);
|
|
|
|
if (success) {
|
|
isListening.value = true;
|
|
connectionStatus.value = 'Connected';
|
|
} else {
|
|
errorMessage.value = _asrService.errorMessage;
|
|
Logger.error('Failed to start recognition: ${_asrService.errorMessage}');
|
|
}
|
|
} catch (e) {
|
|
errorMessage.value = e.toString();
|
|
Logger.error('Error starting recognition: $e');
|
|
}
|
|
}
|
|
|
|
// 重新开始识别(用于连续识别模式)
|
|
Future<void> _restartRecognition() async {
|
|
// 短暂延迟,确保上一次识别完全结束
|
|
await Future.delayed(const Duration(milliseconds: 500));
|
|
|
|
// 如果仍处于监听状态且是连续识别模式,则开始新的识别
|
|
if (isListening.value && isContinuous.value) {
|
|
startListening();
|
|
}
|
|
}
|
|
|
|
// Stop listening for speech
|
|
void stopListening() {
|
|
try {
|
|
connectionStatus.value = 'Disconnecting...';
|
|
|
|
// 停止麦克风录音
|
|
_asrService.stopRecognition().then((_) {
|
|
isListening.value = false;
|
|
connectionStatus.value = 'Disconnected';
|
|
|
|
// 重置当前识别索引
|
|
_currentRecognitionIndex = -1;
|
|
}).catchError((e) {
|
|
errorMessage.value = e.toString();
|
|
Logger.error('Error stopping recognition: $e');
|
|
});
|
|
} catch (e) {
|
|
errorMessage.value = e.toString();
|
|
Logger.error('Error stopping recognition: $e');
|
|
}
|
|
}
|
|
|
|
// Clear recognition results
|
|
void clearResults() {
|
|
recognitionResults.clear();
|
|
currentRecognizingText.value = '';
|
|
_currentRecognitionIndex = -1;
|
|
}
|
|
}
|