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.39
Then run:
flutter pub get
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()
}
}
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.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.removeListeners()
KeyWordFlutterPC.removeAllRNBridgeListeners()
KeyWordFlutterPC.setWakewordAudioRoutingConfig(AudioRoutingConfig config)
Top-level helpers:
pauseDetection(String instanceId, {bool stopMic = false})
unPauseDetection(String instanceId)
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.
await setWakewordAudioRoutingConfig(
AudioRoutingConfig(
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) {
// Handle enrollment JSON/result.
});
final verifySub = onSpeakerVerificationVerifyResult((event) {
// Handle verification result.
});
final errorSub = onSpeakerVerificationError((event) {
// Handle native speaker verification errors.
});
await controller.beginOnboarding('user-1', 3);
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.