69 lines
2.3 KiB
Dart
69 lines
2.3 KiB
Dart
import 'dart:async';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:mymuseum_visitapp/Services/Glasses/engines/wake_word_engine.dart';
|
|
|
|
/// Wake word via OpenWakeWord — service Android natif (foreground service).
|
|
/// Utilise ONNX Runtime pour l'inférence on-device du modèle hey_visit.onnx.
|
|
/// Survit au background Android contrairement au STT continu.
|
|
///
|
|
/// iOS non supporté — fallback sur SpeechToTextWakeWordEngine côté iOS.
|
|
class OpenWakeWordEngine implements WakeWordEngine {
|
|
static const _methodChannel = MethodChannel('be.unov.mymuseum/wake_word');
|
|
static const _eventChannel = EventChannel('be.unov.mymuseum/wake_word_events');
|
|
|
|
/// Nom du fichier .tflite dans assets/files (sans extension).
|
|
/// Ex: "hey_visit", "hey_museum", "hey_guide"
|
|
final String modelName;
|
|
|
|
StreamSubscription<dynamic>? _subscription;
|
|
void Function()? _onDetected;
|
|
bool _running = false;
|
|
|
|
OpenWakeWordEngine({this.modelName = 'hey_visit'});
|
|
|
|
@override
|
|
Future<void> start({
|
|
required void Function() onDetected,
|
|
void Function(String command)? onDetectedWithCommand,
|
|
}) async {
|
|
if (_running) return;
|
|
if (!_isAndroid) {
|
|
debugPrint('[OpenWakeWordEngine] Android only — no-op on this platform');
|
|
return;
|
|
}
|
|
|
|
_onDetected = onDetected;
|
|
_running = true;
|
|
|
|
_subscription = _eventChannel.receiveBroadcastStream().listen(
|
|
(event) {
|
|
if (event == 'detected' && _running) {
|
|
debugPrint('[OpenWakeWordEngine] Wake word detected');
|
|
// OpenWakeWord ne capture pas la commande inline — l'orchestrateur
|
|
// lance un cycle STT séparé via onDetected()
|
|
_onDetected?.call();
|
|
}
|
|
},
|
|
onError: (e) => debugPrint('[OpenWakeWordEngine] Event error: $e'),
|
|
);
|
|
|
|
await _methodChannel.invokeMethod('start', {'modelName': modelName});
|
|
debugPrint('[OpenWakeWordEngine] Service started (model: $modelName)');
|
|
}
|
|
|
|
@override
|
|
Future<void> stop() async {
|
|
if (!_running) return;
|
|
_running = false;
|
|
await _subscription?.cancel();
|
|
_subscription = null;
|
|
if (_isAndroid) {
|
|
await _methodChannel.invokeMethod('stop');
|
|
}
|
|
debugPrint('[OpenWakeWordEngine] Service stopped');
|
|
}
|
|
|
|
bool get _isAndroid => defaultTargetPlatform == TargetPlatform.android;
|
|
}
|