|
|
@ -8,8 +8,8 @@ import '../asr_service.dart'; |
|
|
|
|
|
|
|
|
/// 音频源类型 |
|
|
/// 音频源类型 |
|
|
enum AudioSourceType { |
|
|
enum AudioSourceType { |
|
|
microphone, // 使用设备麦克风 |
|
|
microphone, // 使用设备麦克风 |
|
|
external // 使用外部提供的音频数据 |
|
|
external // 使用外部提供的音频数据 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// Azure 语音识别服务 |
|
|
/// Azure 语音识别服务 |
|
|
@ -18,7 +18,8 @@ enum AudioSourceType { |
|
|
class AzureAsrService extends GetxService implements AsrService { |
|
|
class AzureAsrService extends GetxService implements AsrService { |
|
|
static final AzureAsrService to = Get.put(AzureAsrService()); |
|
|
static final AzureAsrService to = Get.put(AzureAsrService()); |
|
|
static const MethodChannel _channel = MethodChannel('azure_speech/asr'); |
|
|
static const MethodChannel _channel = MethodChannel('azure_speech/asr'); |
|
|
static const EventChannel _eventChannel = EventChannel('azure_speech/asr_events'); |
|
|
static const EventChannel _eventChannel = |
|
|
|
|
|
EventChannel('azure_speech/asr_events'); |
|
|
final GetStorage _storage = GetStorage(); |
|
|
final GetStorage _storage = GetStorage(); |
|
|
bool _isInitialized = false; |
|
|
bool _isInitialized = false; |
|
|
late final String _subscriptionKey; |
|
|
late final String _subscriptionKey; |
|
|
@ -77,7 +78,8 @@ class AzureAsrService extends GetxService implements AsrService { |
|
|
bool useEchoCancellation = false, |
|
|
bool useEchoCancellation = false, |
|
|
}) async { |
|
|
}) async { |
|
|
try { |
|
|
try { |
|
|
final List<String> languages = supportedLanguages ?? _defaultSupportedLanguages; |
|
|
final List<String> languages = |
|
|
|
|
|
supportedLanguages ?? _defaultSupportedLanguages; |
|
|
|
|
|
|
|
|
// 检查是否需要重新初始化 |
|
|
// 检查是否需要重新初始化 |
|
|
if (_isInitialized) { |
|
|
if (_isInitialized) { |
|
|
@ -85,7 +87,9 @@ class AzureAsrService extends GetxService implements AsrService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 设置音频源类型 |
|
|
// 设置音频源类型 |
|
|
_audioSourceType = useExternalAudio ? AudioSourceType.external : AudioSourceType.microphone; |
|
|
_audioSourceType = useExternalAudio |
|
|
|
|
|
? AudioSourceType.external |
|
|
|
|
|
: AudioSourceType.microphone; |
|
|
|
|
|
|
|
|
final bool result = await _channel.invokeMethod('initialize', { |
|
|
final bool result = await _channel.invokeMethod('initialize', { |
|
|
'subscriptionKey': _subscriptionKey, |
|
|
'subscriptionKey': _subscriptionKey, |
|
|
@ -120,7 +124,8 @@ class AzureAsrService extends GetxService implements AsrService { |
|
|
if (result is Map) { |
|
|
if (result is Map) { |
|
|
// 处理新格式返回 |
|
|
// 处理新格式返回 |
|
|
final String text = result['text'] as String? ?? ''; |
|
|
final String text = result['text'] as String? ?? ''; |
|
|
final String detectedLanguage = result['detectedLanguage'] as String? ?? ''; |
|
|
final String detectedLanguage = |
|
|
|
|
|
result['detectedLanguage'] as String? ?? ''; |
|
|
|
|
|
|
|
|
// 更新最新识别结果 |
|
|
// 更新最新识别结果 |
|
|
_latestRecognizedText = text; |
|
|
_latestRecognizedText = text; |
|
|
@ -157,7 +162,8 @@ class AzureAsrService extends GetxService implements AsrService { |
|
|
_eventStreamController = StreamController<RecognitionEvent>.broadcast(); |
|
|
_eventStreamController = StreamController<RecognitionEvent>.broadcast(); |
|
|
|
|
|
|
|
|
// 开始连续识别 |
|
|
// 开始连续识别 |
|
|
final bool result = await _channel.invokeMethod('startContinuousRecognition'); |
|
|
final bool result = |
|
|
|
|
|
await _channel.invokeMethod('startContinuousRecognition'); |
|
|
|
|
|
|
|
|
if (!result) { |
|
|
if (!result) { |
|
|
_cleanupEventStream(); |
|
|
_cleanupEventStream(); |
|
|
@ -180,7 +186,8 @@ class AzureAsrService extends GetxService implements AsrService { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
final bool result = await _channel.invokeMethod('stopContinuousRecognition'); |
|
|
final bool result = |
|
|
|
|
|
await _channel.invokeMethod('stopContinuousRecognition'); |
|
|
_cleanupEventStream(); |
|
|
_cleanupEventStream(); |
|
|
return result; |
|
|
return result; |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
@ -208,7 +215,8 @@ class AzureAsrService extends GetxService implements AsrService { |
|
|
switch (eventType) { |
|
|
switch (eventType) { |
|
|
case 'result': |
|
|
case 'result': |
|
|
final String text = eventMap['text'] as String? ?? ''; |
|
|
final String text = eventMap['text'] as String? ?? ''; |
|
|
final String detectedLanguage = eventMap['detectedLanguage'] as String? ?? ''; |
|
|
final String detectedLanguage = |
|
|
|
|
|
eventMap['detectedLanguage'] as String? ?? ''; |
|
|
_latestRecognizedText = text; |
|
|
_latestRecognizedText = text; |
|
|
_latestDetectedLanguage = detectedLanguage; |
|
|
_latestDetectedLanguage = detectedLanguage; |
|
|
_eventStreamController?.add(RecognitionEvent( |
|
|
_eventStreamController?.add(RecognitionEvent( |
|
|
@ -220,7 +228,8 @@ class AzureAsrService extends GetxService implements AsrService { |
|
|
|
|
|
|
|
|
case 'recognizing': |
|
|
case 'recognizing': |
|
|
final String text = eventMap['text'] as String? ?? ''; |
|
|
final String text = eventMap['text'] as String? ?? ''; |
|
|
final String detectedLanguage = eventMap['detectedLanguage'] as String? ?? ''; |
|
|
final String detectedLanguage = |
|
|
|
|
|
eventMap['detectedLanguage'] as String? ?? ''; |
|
|
_eventStreamController?.add(RecognitionEvent( |
|
|
_eventStreamController?.add(RecognitionEvent( |
|
|
type: RecognitionEventType.intermediateResult, |
|
|
type: RecognitionEventType.intermediateResult, |
|
|
text: text, |
|
|
text: text, |
|
|
@ -303,31 +312,4 @@ class AzureAsrService extends GetxService implements AsrService { |
|
|
_isInitialized = false; |
|
|
_isInitialized = false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@override |
|
|
|
|
|
Future<bool> pushAudioData(Uint8List data) async { |
|
|
|
|
|
if (!_isInitialized) { |
|
|
|
|
|
await initialize(useExternalAudio: true); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (_audioSourceType != AudioSourceType.external) { |
|
|
|
|
|
Logger.error('当前非外部音频模式,不能推送音频数据'); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
final bool result = await _channel.invokeMethod('pushAudioData', { |
|
|
|
|
|
'audioData': data // Flutter 会自动将 Uint8List 转换为 ByteBuffer |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (!result) { |
|
|
|
|
|
throw Exception('推送音频数据失败'); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
Logger.error('推送音频数据失败: $e'); |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|