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.
201 lines
5.2 KiB
201 lines
5.2 KiB
import 'dart:async';
|
|
import 'dart:typed_data';
|
|
|
|
/// 音频源类型
|
|
enum AudioSourceType {
|
|
microphone, // 使用设备麦克风
|
|
systemAudio, // 使用系统音频(麦克风也启动保证后台也能正常运行)
|
|
systemAudioPlusMicrophone, // 使用系统音频+麦克风音频
|
|
external // 使用外部提供的音频数据
|
|
}
|
|
|
|
/// 语音识别服务接口
|
|
abstract class AsrService {
|
|
/// 支持的语言
|
|
List<String> get supportedLanguages;
|
|
|
|
/// 初始化语音识别服务
|
|
Future<bool> initialize({
|
|
List<String>? supportedLanguages,
|
|
});
|
|
|
|
/// 执行一次性语音识别
|
|
///
|
|
/// 返回识别的最终结果
|
|
Future<RecognitionEvent> recognizeOnce();
|
|
|
|
/// 开始连续语音识别
|
|
///
|
|
/// 返回一个包含识别事件的流
|
|
/// [skipAsrForCallMode] true 时仅占位,不真正启动本地 ASR(用于通话翻译 call 模式:
|
|
/// AST 端到端服务已自行处理识别+翻译+TTS)。多媒体翻译等 external 场景保持 false。
|
|
Future<bool> startContinuousRecognition(
|
|
bool audioSourceType, {
|
|
bool isRemoveFirstPunctuation = true,
|
|
String mode = "normal",
|
|
bool skipAsrForCallMode = false,
|
|
});
|
|
|
|
/// 停止连续语音识别
|
|
Future<bool> stopContinuousRecognition();
|
|
|
|
/// 设置识别回掉
|
|
///
|
|
/// 返回一个包含识别事件的流
|
|
Future<Stream<RecognitionEvent>> recognizeCallback();
|
|
|
|
/// 恢复原始音频状态
|
|
Future<void> restoreOriginalAudioState();
|
|
|
|
/// 禁用蓝牙音频
|
|
Future<void> disableBluetoothAudio();
|
|
|
|
/// 检查连续识别是否活跃
|
|
bool isContinuousRecognitionActive();
|
|
|
|
/// 开始录音
|
|
///
|
|
/// [filePath] 录音文件路径
|
|
/// [audioSourceType] 音频源类型
|
|
/// [acceptAudioData] 是否接受音频数据回调,默认为 false
|
|
Future<bool> enableRecord(
|
|
AudioSourceType audioSourceType,
|
|
String filePath,
|
|
bool acceptAudioData,
|
|
);
|
|
|
|
/// 获取音频数据流(如果支持)
|
|
Stream<Uint8List>? getAudioDataStream() => null;
|
|
|
|
/// 暂停录音
|
|
Future<bool> pauseRecord();
|
|
|
|
/// 继续录音
|
|
Future<bool> resumeRecord();
|
|
|
|
/// 设置音频配置
|
|
Future<bool> setAudioConfig({
|
|
int sampleRate = 16000,
|
|
int channels = 1,
|
|
});
|
|
|
|
// /// 移动文件到新路径
|
|
Future<bool> moveFile(String sourcePath, String destPath);
|
|
|
|
// /// 重命名指定路径的音频文件
|
|
Future<bool> renameFile(String filePath, String newName);
|
|
|
|
/// 结束录音
|
|
Future<bool> stopRecord(bool isSave);
|
|
|
|
/// 申请系统音频捕获授权(Android MediaProjection)
|
|
///
|
|
/// 仅在 Android 上有真正的实现:会弹出系统"录屏"授权弹窗,
|
|
/// 用户授权后内部启动前台服务,开始捕获系统播放音频并通过
|
|
/// 平台层把 PCM 直接写入 [enableRecord] 创建的 WAV 文件。
|
|
/// 返回 true 表示授权成功且捕获已启动;false 表示用户拒绝或失败。
|
|
/// 其他平台默认返回 false(不支持)。
|
|
Future<bool> requestScreenCapture() async => false;
|
|
|
|
/// 停止系统音频捕获(停掉 MediaProjection 前台服务)
|
|
/// 仅 Android 上有真正实现;其他平台默认返回 true(无副作用)。
|
|
Future<bool> stopScreenCapture() async => true;
|
|
|
|
/// 查询当前是否在系统音频捕获中
|
|
Future<bool> isScreenCapturing() async => false;
|
|
|
|
/// 释放资源
|
|
Future<void> dispose();
|
|
}
|
|
|
|
/// 识别事件类型
|
|
enum RecognitionEventType {
|
|
/// 最终识别结果
|
|
finalResult,
|
|
|
|
/// 麦识别结果
|
|
finalResult1,
|
|
|
|
/// 中间识别结果(实时反馈)
|
|
intermediateResult,
|
|
|
|
/// 会话开始
|
|
sessionStarted,
|
|
|
|
/// 会话结束
|
|
sessionStopped,
|
|
|
|
/// 识别取消
|
|
canceled,
|
|
|
|
/// 识别错误
|
|
error,
|
|
}
|
|
|
|
/// 识别事件
|
|
class RecognitionEvent {
|
|
/// 事件类型
|
|
final RecognitionEventType type;
|
|
|
|
/// 识别文本(仅在 finalResult 和 intermediateResult 类型中有效)
|
|
final String text;
|
|
|
|
/// 检测到的语言
|
|
final String detectedLanguage;
|
|
|
|
final String provider;
|
|
|
|
/// 角色
|
|
final String role;
|
|
|
|
/// 原始音频
|
|
final Uint8List? audio;
|
|
|
|
/// 错误信息(仅在 error 和 canceled 类型中有效)
|
|
final String error;
|
|
|
|
RecognitionEvent({
|
|
required this.type,
|
|
this.text = '',
|
|
this.detectedLanguage = '',
|
|
this.provider = '',
|
|
this.role = '',
|
|
this.audio,
|
|
this.error = '',
|
|
});
|
|
|
|
/// 创建最终结果事件的快捷构造函数
|
|
factory RecognitionEvent.finalResult({
|
|
required String text,
|
|
String detectedLanguage = '',
|
|
String provider = '',
|
|
}) {
|
|
return RecognitionEvent(
|
|
type: RecognitionEventType.finalResult,
|
|
text: text,
|
|
detectedLanguage: detectedLanguage,
|
|
provider: provider,
|
|
);
|
|
}
|
|
|
|
/// 创建错误事件的快捷构造函数
|
|
factory RecognitionEvent.error(String errorMessage) {
|
|
return RecognitionEvent(
|
|
type: RecognitionEventType.error,
|
|
error: errorMessage,
|
|
);
|
|
}
|
|
|
|
/// 检查是否为最终结果
|
|
bool get isFinalResult => type == RecognitionEventType.finalResult;
|
|
|
|
/// 检查是否为错误
|
|
bool get isError =>
|
|
type == RecognitionEventType.error ||
|
|
type == RecognitionEventType.canceled;
|
|
|
|
@override
|
|
String toString() {
|
|
return 'RecognitionEvent{type: $type, provider: $provider, text: $text, detectedLanguage: $detectedLanguage, error: $error}';
|
|
}
|
|
}
|
|
|