microwakeword

package module
v0.0.0-...-bfaf384 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 30, 2026 License: MIT Imports: 6 Imported by: 0

README

microwakeword

CI GoDoc Go Report Card

Pure Go streaming wake-word detection using microWakeWord v2 TFLite models. No CGo, no external C/C++ dependencies.

How it works

PCM 16 kHz ─► Audio Frontend ─► TFLite Interpreter ─► Sliding Avg ─► detected?
              (mel features)     (quantised int8)       (probability)
  1. Audio frontend — 30 ms Hann window, 10 ms step, 512-point FFT, 40-channel mel filterbank (125–7500 Hz), spectral noise reduction, PCAN gain control, log scaling, int8 quantisation.
  2. TFLite interpreter — executes quantised int8 models with stateful resource variables (streaming). Supports the op subset used by MWW v2 models: Conv2D, DepthwiseConv2D, FullyConnected, Logistic, Quantize, Reshape, Concatenation, StridedSlice, SplitV, VarHandle, ReadVariable, AssignVariable, CallOnce.
  3. Sliding-window detection — averages the last N inference probabilities and compares against a cutoff threshold.

Install

go get github.com/zserge/microwakeword@latest

Usage

package main

import (
	"fmt"
	"log"

	mww "github.com/zserge/microwakeword"
)

func main() {
	det, err := mww.NewDetector(mww.Config{
		ModelPath:         "hey_jarvis.tflite",
		ProbabilityCutoff: 0.85,
		SlidingWindowSize: 5,
		FeaturesStepMs:    10,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Feed 16 kHz 16-bit signed PCM in any chunk size.
	for chunk := range audioChunks() {
		if det.ProcessAudio(chunk) {
			fmt.Println("wake word detected")
			det.Reset()
		}
	}
}

Models

Download .tflite models from the micro-wake-word-models repository. Use v2 models (input shape [1, 3, 40], int8).

Available wake words include: alexa, hey_jarvis, hey_mycroft, okay_nabu, and others.

CLI tools

detect — offline WAV detection
go run ./cmd/detect -model hey_jarvis.tflite -wav test.wav

Prints per-frame probabilities and reports detection time.

mic — live microphone detection
cd cmd/mic && go run . -model ../../testdata/hey_jarvis.tflite

Separate module (own go.mod) to isolate the malgo dependency from the core library. Listens on the default capture device and prints when the wake word is detected.

Testing

go test ./...

Tests require .tflite model files and .wav audio samples in testdata/. Tests are skipped automatically if the files are not present.

Benchmarks

go test -bench=. -benchmem

On Mac M1 it's 50x faster than real-time (20ms to process 1s of audio).

Project structure

microwakeword.go        main API: Detector, Config, NewDetector, ProcessAudio
audiofrontend/          mel-spectrogram feature extraction (FFT, filterbank)
model/                  TFLite FlatBuffer parser
interpreter/            quantised TFLite interpreter (MWW op subset)
cmd/detect/             offline WAV detection CLI
cmd/mic/                live microphone detection CLI (separate go.mod)
testdata/               test models and audio samples

License

MIT

Documentation

Overview

Package microwakeword is a pure Go streaming wake-word detector compatible with microWakeWord v2 TFLite models (https://github.com/kahrendt/microWakeWord).

It implements the full detection pipeline: audio feature extraction (mel-spectrogram), quantised TFLite model inference, and sliding-window probability averaging. No CGo or external C/C++ dependencies.

Basic usage:

det, err := microwakeword.NewDetector(microwakeword.Config{
    ModelPath:         "hey_jarvis.tflite",
    ProbabilityCutoff: 0.85,
    SlidingWindowSize: 5,
    FeaturesStepMs:    10,
})
if err != nil { log.Fatal(err) }

for chunk := range audioSource {
    if det.ProcessAudio(chunk) {
        fmt.Println("wake word detected")
    }
}
Example
package main

import (
	"encoding/binary"
	"fmt"
	"log"
	"os"

	"github.com/zserge/microwakeword"
)

func main() {
	det, err := microwakeword.NewDetector(microwakeword.Config{
		ModelPath:         "testdata/hey_jarvis.tflite",
		ProbabilityCutoff: 0.85,
		SlidingWindowSize: 5,
		FeaturesStepMs:    10,
	})
	if err != nil {
		log.Fatal(err)
	}

	// Load a WAV file (skip 44-byte header).
	data, err := os.ReadFile("testdata/hey_jarvis.wav")
	if err != nil {
		log.Fatal(err)
	}
	pcm := data[44:]
	samples := make([]int16, len(pcm)/2)
	for i := range samples {
		samples[i] = int16(binary.LittleEndian.Uint16(pcm[i*2:]))
	}

	// Feed 10 ms chunks (160 samples at 16 kHz).
	const chunk = 160
	for i := 0; i+chunk <= len(samples); i += chunk {
		if det.ProcessAudio(samples[i : i+chunk]) {
			fmt.Printf("detected at %.2fs\n", float64(i)/16000)
			return
		}
	}
	fmt.Println("not detected")
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// ModelPath is the path to a .tflite model file.
	ModelPath string

	// ProbabilityCutoff is the sliding-window average threshold (0-1).
	// A higher value reduces false positives at the cost of sensitivity.
	ProbabilityCutoff float64

	// SlidingWindowSize is the number of recent inference results averaged
	// for the detection decision.
	SlidingWindowSize int

	// FeaturesStepMs is the audio frontend step size in milliseconds.
	// Typical values are 10 or 20. Zero defaults to 20.
	FeaturesStepMs int
}

Config holds the parameters for creating a Detector.

func ConfigFromJSON

func ConfigFromJSON(jsonPath string) (Config, error)

ConfigFromJSON reads a microWakeWord JSON config file and returns a Config with all fields populated. The JSON format follows the micro-wake-word-models convention.

type Detector

type Detector struct {

	// OnInference, if non-nil, is called after each model inference with
	// the invocation count, the raw uint8 probability (0-255), and the
	// current sliding-window average (0-1). Useful for debugging.
	OnInference func(invocation int, rawProb uint8, slidingAvg float64)
	// contains filtered or unexported fields
}

Detector is a streaming wake-word detector. It is not safe for concurrent use; protect with a mutex if shared across goroutines.

func NewDetector

func NewDetector(cfg Config) (*Detector, error)

NewDetector loads a TFLite model and creates a ready-to-use detector.

func (*Detector) ProcessAudio

func (d *Detector) ProcessAudio(samples []int16) bool

ProcessAudio feeds PCM audio samples into the detector and returns true when the wake word is detected. Samples must be 16 kHz, 16-bit signed, mono. Any chunk size is accepted; the detector buffers internally.

func (*Detector) ProcessFeatures

func (d *Detector) ProcessFeatures(frames [][]int8) bool

ProcessFeatures feeds pre-extracted int8 features (40 per frame) directly into the model, bypassing the audio frontend.

func (*Detector) Reset

func (d *Detector) Reset()

Reset clears all internal state so the detector can be reused on a new audio stream. The loaded model is kept.

func (*Detector) SlidingAverage

func (d *Detector) SlidingAverage() float64

SlidingAverage returns the current sliding-window average probability (0-1). Useful for debugging and visualisation.

Directories

Path Synopsis
Package audiofrontend implements the audio feature extraction pipeline used by microWakeWord models.
Package audiofrontend implements the audio feature extraction pipeline used by microWakeWord models.
cmd
detect command
Command detect loads a microWakeWord v2 model and a WAV file, runs detection frame-by-frame, and prints each inference result.
Command detect loads a microWakeWord v2 model and a WAV file, runs detection frame-by-frame, and prints each inference result.
Package model parses TFLite FlatBuffer (.tflite) model files into Go structures.
Package model parses TFLite FlatBuffer (.tflite) model files into Go structures.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL