flutter_wake_word 0.0.53
flutter_wake_word: ^0.0.53 copied to clipboard
This is an on-device "wake word" package for Flutter. A wake word is a keyword or sentance that activates your application
flutter_wake_word #
A Flutter plugin for custom wake word detection on iOS and Android.
Use it to create one or more wake word detector instances, start and stop keyword detection, receive detection events, configure VAD behavior, manage recording helpers, and use speaker verification where supported by the native platform.
Contact: info@DaVoice.io
Installation #
Add the package to pubspec.yaml:
dependencies:
flutter_wake_word: ^0.0.52
Then run:
flutter pub get
This version retains the package's earlier Flutter/Dart minimums. On AGP 8 it
applies the Kotlin plugin needed by older Flutter projects; on AGP 9 with
built-in Kotlin it does not apply that plugin. Flutter 3.47 or newer is required
when an app enables android.builtInKotlin=true.
Android Setup #
The Android package includes a local native AAR. Add the plugin libs
repository to your app's Android Gradle configuration if your app does not
already resolve it automatically:
allprojects {
repositories {
google()
mavenCentral()
maven { url "${project(':flutter_wake_word').projectDir}/libs" }
mavenLocal()
}
}
Android compatibility and ABIs #
The package declares Android API 23 and ships arm64-v8a binaries. Wake-word
inference has been verified on a current Samsung device; the native runtime
still needs a physical API-23 inference test. This package does not provide
armeabi-v7a or x86_64.
The AAR retains its existing x86 ONNX Runtime files for development
compatibility. That slice has a native API 27 floor and is outside the API 23
support contract. Apps using the complete Davoice speech and TTS stack should
ship arm64-v8a, because the TTS package is ARM64-only.
Import #
import 'package:flutter_wake_word/flutter_wake_word.dart';
Quick Start #
final wakeWord = FlutterWakeWord();
await wakeWord.setKeywordDetectionLicense('YOUR_LICENSE');
await wakeWord.createInstance(
'main',
'hey_app.onnx',
0.7,
3,
);
await wakeWord.startKeywordDetection(0.7);
// Stop later.
await wakeWord.stopKeywordDetection();
For direct instance control:
final detector = createKeyWordFlutterPCInstance('main');
await detector.createInstance('hey_app.onnx', 0.7, 3);
await detector.setKeywordDetectionLicense('YOUR_LICENSE');
final subscription = detector.onKeywordDetectionEvent().listen((event) {
final phrase = event['phrase'];
final model = event['modelName'] ?? event['model'];
});
await detector.startKeywordDetection('main', 0.7);
Multi-Model Detection #
final detector = createKeyWordFlutterPCInstance('multi');
await detector.createInstanceMulti(
'multi',
['hey_app.onnx', 'help_now.onnx'],
[0.7, 0.8],
[3, 3],
[1000, 1000],
);
detector.onKeywordDetectionEvent().listen((event) {
final phrase = event['phrase'];
final model = event['modelName'] ?? event['model'];
});
await detector.startKeywordDetection('multi', 0.7);
UseModel Helper #
UseModel manages multiple wake word instances for you.
final model = UseModel();
await model.setKeywordDetectionLicense('YOUR_LICENSE');
await model.loadModel(
[
InstanceConfig(
id: 'main',
modelName: 'hey_app.onnx',
threshold: 0.7,
bufferCnt: 3,
),
],
(event) {
final phrase = event['phrase'];
},
);
await model.startListening();
await model.stopListening();
Wake Word API #
FlutterWakeWord #
High-level API:
FlutterWakeWord.getPlatformVersion()
FlutterWakeWord.setKeywordDetectionLicense(String license)
FlutterWakeWord.createInstance(...)
FlutterWakeWord.createInstanceMulti(...)
FlutterWakeWord.startKeywordDetection(double threshold)
FlutterWakeWord.stopKeywordDetection()
FlutterWakeWord.getVoiceProps(String instanceId)
FlutterWakeWord.startSilentVADDetection(String instanceId)
FlutterWakeWord.stopSilentVADDetection(String instanceId)
FlutterWakeWord.startVADDetection(String instanceId)
FlutterWakeWord.stopVADDetection(String instanceId)
FlutterWakeWord.onVADDetectionEvent(String instanceId)
FlutterWakeWord.setVADParams(String instanceId, double threshold, int msWindow)
FlutterWakeWord.getVADParams(String instanceId)
FlutterWakeWord.setKeywordLicense(String instanceId, String license)
FlutterWakeWord.getRecordingWavArray(String instanceId)
FlutterWakeWord.getRecordingWav(String instanceId)
FlutterWakeWord.pauseDetection(String instanceId, {bool stopMic = false})
FlutterWakeWord.unPauseDetection(String instanceId)
FlutterWakeWord.setTTSActive(String instanceId, bool active)
FlutterWakeWord.removeAllRNBridgeListeners()
FlutterWakeWord.setWakewordAudioRoutingConfig(AudioRoutingConfig config)
KeyWordFlutterPC #
Lower-level per-instance API:
createKeyWordFlutterPCInstance(String instanceId, {bool isSticky = false})
KeyWordFlutterPC.createInstance(...)
KeyWordFlutterPC.createInstanceMulti(...)
KeyWordFlutterPC.setKeywordDetectionLicense(String license)
KeyWordFlutterPC.setKeywordLicense(String license)
KeyWordFlutterPC.replaceKeywordDetectionModel(...)
KeyWordFlutterPC.startKeywordDetection(...)
KeyWordFlutterPC.stopKeywordDetection(...)
KeyWordFlutterPC.destroyInstance()
KeyWordFlutterPC.startForegroundService()
KeyWordFlutterPC.stopForegroundService()
KeyWordFlutterPC.onKeywordDetectionEvent()
KeyWordFlutterPC.getVoiceProps()
KeyWordFlutterPC.startSilentVADDetection()
KeyWordFlutterPC.stopSilentVADDetection()
KeyWordFlutterPC.startVADDetection()
KeyWordFlutterPC.stopVADDetection()
KeyWordFlutterPC.onVADDetectionEvent()
KeyWordFlutterPC.setVADParams(double threshold, int msWindow)
KeyWordFlutterPC.getVADParams()
KeyWordFlutterPC.getRecordingWavArray()
KeyWordFlutterPC.getRecordingWav()
KeyWordFlutterPC.pauseDetection({bool stopMic = false})
KeyWordFlutterPC.unPauseDetection()
KeyWordFlutterPC.setTTSActive(bool active)
KeyWordFlutterPC.removeListeners()
KeyWordFlutterPC.removeAllRNBridgeListeners()
KeyWordFlutterPC.setWakewordAudioRoutingConfig(AudioRoutingConfig config)
Top-level helpers:
pauseDetection(String instanceId, {bool stopMic = false})
unPauseDetection(String instanceId)
setWakewordTTSActive(String instanceId, bool active)
removeAllRNBridgeListeners()
setWakewordAudioRoutingConfig(AudioRoutingConfig config)
VAD #
Voice activity detection APIs are available through FlutterWakeWord or
KeyWordFlutterPC.
final detector = createKeyWordFlutterPCInstance('main');
await detector.startVADDetection();
final vadSub = detector.onVADDetectionEvent().listen((event) {
// Handle VAD event payload.
});
await detector.setVADParams(0.5, 300);
final props = await detector.getVoiceProps();
await detector.stopVADDetection();
Platform support depends on the native library bundled for each platform.
Recording Helpers #
final detector = createKeyWordFlutterPCInstance('main');
final wav = await detector.getRecordingWav();
final wavBytes = await detector.getRecordingWavArray();
getRecordingWav() returns the native recording payload or path. Availability
depends on the native platform implementation.
Pause And Resume #
await detector.pauseDetection(stopMic: true);
await detector.unPauseDetection();
Audio Routing #
AudioRoutingConfig and RouteConfigEntry configure wake-word audio routing on
iOS and Android. Pair setTTSActive(true) with setTTSActive(false) around
physical TTS playback when wake-word detection should remain active. Android
updates the selected detector; iOS updates the shared wakeWordDuringTTS
profile and returns whether the begin operation was applied.
Use AECConfig for the app-wide STT, wake-word, and TTS echo-cancellation
policy. When aec is present, native code ignores the older wakewordAEC
setting. Supported modes are off, duringTTS, and always.
await setWakewordAudioRoutingConfig(
AudioRoutingConfig(
aec: AECConfig(mode: AECMode.duringTTS),
defaultRoute: RouteConfigEntry(
category: WakewordAudioCategory.playAndRecord,
mode: WakewordAudioMode.defaultMode,
options: [
WakewordAudioOption.mixWithOthers,
WakewordAudioOption.defaultToSpeaker,
],
preferredInput: WakewordPreferredInput.none,
),
bluetoothHFP: RouteConfigEntry(
category: WakewordAudioCategory.playAndRecord,
mode: WakewordAudioMode.voiceChat,
options: [
WakewordAudioOption.allowBluetooth,
WakewordAudioOption.mixWithOthers,
],
preferredInput: WakewordPreferredInput.builtInMic,
),
),
);
Speaker Verification #
Speaker verification mirrors the native speaker verification bridge where supported.
Verify WAV #
final verifier = await createSpeakerVerificationInstance('speaker-engine');
await verifier.create(
'speaker_model.dm',
'enrollment.json',
options: {
'decisionThreshold': 0.35,
'frameSize': 1280,
'tailSeconds': 2.0,
'maxTailSeconds': 3.0,
'cmn': true,
'expectedLayoutBDT': false,
},
);
final result = await verifier.verifyWavStreaming(
'test.wav',
resetState: true,
);
await verifier.destroy();
Mic Controller #
final controller = await createSpeakerVerificationMicController('speaker-mic');
await controller.create({
'modelPath': 'speaker_model.dm',
'options': {
'decisionThreshold': 0.35,
'frameSize': 1280,
'tailSeconds': 2.0,
'maxTailSeconds': 3.0,
'cmn': true,
'expectedLayoutBDT': false,
},
});
final progressSub = onSpeakerVerificationOnboardingProgress((event) {
// Handle onboarding progress.
});
final doneSub = onSpeakerVerificationOnboardingDone((event) {
// event['enrollmentJsonPath'] is the saved file when savePath was supplied.
// event['enrollmentJson'] remains available for immediate verification.
});
final verifySub = onSpeakerVerificationVerifyResult((event) {
// Handle verification result.
});
final errorSub = onSpeakerVerificationError((event) {
// Handle native speaker verification errors.
});
// Choose an absolute writable path inside the app documents directory.
final documents = await getApplicationDocumentsDirectory(); // path_provider
await controller.beginOnboarding(
'user-1',
3,
savePath: '${documents.path}/speaker_enrollment.json',
);
await controller.getNextEmbeddingFromMic();
await controller.finalizeOnboardingNow();
await controller.setEnrollmentJson('{...}');
await controller.startVerifyFromMic();
await controller.startEndlessVerifyFromMic(
hopSeconds: 0.5,
stopOnMatch: false,
resetState: true,
);
await controller.stop();
await controller.destroy();
await progressSub.cancel();
await doneSub.cancel();
await verifySub.cancel();
await errorSub.cancel();
Platform Notes #
Native support differs by platform and by the bundled native library version.
iOS currently exposes the broader wake-word, VAD, audio routing, recording, and speaker verification APIs through the bundled xcframework.
Android supports the core wake-word APIs and the Android native methods exposed
by the bundled AAR. APIs that are not available in the Android native library
return Flutter's platform notImplemented response.
Example App #
Example project:
https://github.com/frymanofer/Flutter_WakeWordDetection/
FAQ #
What is a wake word? #
A wake word is a keyword that activates your device, like "Hey Siri" or "OK Google".
How accurate is the platform? #
The native DaVoice wake word engine is designed for high accuracy in varied environments.
Topics #
Flutter wake word detection, custom wake words, keyword spotting, hotword detection, phrase spotting, voice activity detection, VAD, speaker verification, speaker identification, speaker recognition, voice authentication, enrollment, voice biometrics, Android wake word detection, iOS wake word detection, DaVoice.