feat: 添加唤醒功能
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
// 导出核心管理类
|
||||
export 'src/vosk_wakeword_manager.dart';
|
||||
|
||||
import 'src/interface/flutter_vosk_wakeword_platform_interface.dart';
|
||||
// 导出错误定义
|
||||
export 'src/vosk_wakeword_error.dart';
|
||||
|
||||
class FlutterVoskWakeword {
|
||||
Future<String?> getPlatformVersion() {
|
||||
return FlutterVoskWakewordPlatform.instance.getPlatformVersion();
|
||||
}
|
||||
}
|
||||
// 导出数据模型
|
||||
export 'src/model/recognition_event.dart';
|
||||
@@ -26,4 +26,7 @@ abstract class FlutterVoskWakewordPlatform extends PlatformInterface {
|
||||
Future<String?> getPlatformVersion() {
|
||||
throw UnimplementedError('platformVersion() has not been implemented.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
// recognition event type
|
||||
enum RecognitionEventType {
|
||||
// partial
|
||||
partial,
|
||||
// final result
|
||||
finalResult,
|
||||
// wakeword
|
||||
wakeword,
|
||||
// error
|
||||
error
|
||||
}
|
||||
|
||||
// recognition event
|
||||
class RecognitionEvent {
|
||||
final RecognitionEventType type;
|
||||
final String? text;
|
||||
|
||||
RecognitionEvent({required this.type, this.text});
|
||||
|
||||
factory RecognitionEvent.fromJson(Map<String, dynamic> json) {
|
||||
return RecognitionEvent(
|
||||
type: RecognitionEventType.values.firstWhere((e) => e.name == json['type']),
|
||||
text: json['text'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'type': type.name,
|
||||
'text': text,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecognitionEvent{type: $type, text: $text}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/// Vosk 插件的基础异常类
|
||||
class VoskWakewordException implements Exception {
|
||||
final String? message;
|
||||
VoskWakewordException([this.message]);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType: $message';
|
||||
}
|
||||
|
||||
/// 当原生代码无法分配内存时抛出
|
||||
class VoskWakewordMemoryException extends VoskWakewordException {
|
||||
VoskWakewordMemoryException(super.message);
|
||||
}
|
||||
|
||||
/// 当模型文件或IO操作失败时抛出
|
||||
class VoskWakewordIOException extends VoskWakewordException {
|
||||
VoskWakewordIOException(super.message);
|
||||
}
|
||||
|
||||
/// 当传入无效参数时抛出
|
||||
class VoskWakewordInvalidArgumentException extends VoskWakewordException {
|
||||
VoskWakewordInvalidArgumentException(super.message);
|
||||
}
|
||||
|
||||
/// 当状态不正确(例如,未初始化就调用start)时抛出
|
||||
class VoskWakewordInvalidStateException extends VoskWakewordException {
|
||||
VoskWakewordInvalidStateException(super.message);
|
||||
}
|
||||
|
||||
/// 当发生未预期的运行时错误时抛出
|
||||
class VoskWakewordRuntimeException extends VoskWakewordException {
|
||||
VoskWakewordRuntimeException(super.message);
|
||||
}
|
||||
|
||||
/// 将原生端返回的错误码转换为对应的 Exception
|
||||
Exception voskStatusToException(String code, String? message) {
|
||||
switch (code) {
|
||||
case 'VoskWakewordMemoryException':
|
||||
return VoskWakewordMemoryException(message);
|
||||
case 'VoskWakewordIOException':
|
||||
return VoskWakewordIOException(message);
|
||||
case 'VoskWakewordInvalidArgumentException':
|
||||
return VoskWakewordInvalidArgumentException(message);
|
||||
case 'VoskWakewordInvalidStateException':
|
||||
return VoskWakewordInvalidStateException(message);
|
||||
case 'VoskWakewordRuntimeException':
|
||||
return VoskWakewordRuntimeException(message);
|
||||
default:
|
||||
return VoskWakewordException("Unexpected error: $code, message: $message");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'vosk_wakeword_error.dart';
|
||||
import 'model/recognition_event.dart';
|
||||
|
||||
/// Vosk 唤醒词插件的主接口 (单例模式)
|
||||
///
|
||||
/// 这个类负责向原生代码发送指令,并通过 Stream 接收识别事件。
|
||||
/// 所有的音频采集和处理都在原生端完成。
|
||||
class FlutterVoskWakeword {
|
||||
// 私有构造函数
|
||||
FlutterVoskWakeword._internal();
|
||||
// 获取唯一实例
|
||||
static FlutterVoskWakeword get instance => _instance;
|
||||
// 静态、唯一的实例
|
||||
static final FlutterVoskWakeword _instance = FlutterVoskWakeword._internal();
|
||||
|
||||
// Factory 构造函数返回唯一实例
|
||||
factory FlutterVoskWakeword() => _instance;
|
||||
|
||||
static const MethodChannel _methodChannel = MethodChannel('flutter_vosk_wakeword/methods');
|
||||
static const EventChannel _eventChannel = EventChannel('flutter_vosk_wakeword/events');
|
||||
|
||||
Stream<RecognitionEvent>? _recognitionStream;
|
||||
|
||||
/// 监听识别事件的流
|
||||
Stream<RecognitionEvent> get recognitionStream {
|
||||
_recognitionStream ??= _eventChannel
|
||||
.receiveBroadcastStream()
|
||||
.map((event) => RecognitionEvent.fromJson(Map<String, dynamic>.from(event)));
|
||||
return _recognitionStream!;
|
||||
}
|
||||
|
||||
/// 初始化 Vosk 引擎和模型
|
||||
Future<bool> initialize({
|
||||
// required String modelPath,
|
||||
required List<String> wakeWords,
|
||||
}) async {
|
||||
try {
|
||||
final result = await _methodChannel.invokeMethod<bool>('initialize', {
|
||||
// 'modelPath': modelPath,
|
||||
'wakeWords': wakeWords,
|
||||
});
|
||||
return result ?? false;
|
||||
} on PlatformException catch (e) {
|
||||
throw voskStatusToException(e.code, e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/// 开始监听
|
||||
Future<bool> start() async {
|
||||
try {
|
||||
return await _methodChannel.invokeMethod<bool>('start') ?? false;
|
||||
} on PlatformException catch (e) {
|
||||
throw voskStatusToException(e.code, e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/// 停止监听
|
||||
Future<bool> stop() async {
|
||||
try {
|
||||
return await _methodChannel.invokeMethod<bool>('stop') ?? false;
|
||||
} on PlatformException catch (e) {
|
||||
throw voskStatusToException(e.code, e.message);
|
||||
}
|
||||
}
|
||||
|
||||
/// 释放所有原生资源
|
||||
Future<bool> dispose() async {
|
||||
try {
|
||||
return await _methodChannel.invokeMethod<bool>('dispose') ?? false;
|
||||
} on PlatformException catch (e) {
|
||||
throw voskStatusToException(e.code, e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user