From 0345cf00e6ce6b75f19a21111ee1eec8feed7db1 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Mon, 14 Nov 2022 08:47:20 -0700 Subject: [PATCH] multi hotword support via HOTWORD=xyz bash build.sh --- snowboy-2022/build.sh | 13 ++++++++----- snowboy-2022/main.go | 20 ++++++++++++++------ snowboy-2022/model/hotword.pmdl | Bin 8619 -> 0 bytes snowboy-2022/model/up.pmdl | Bin 0 -> 4683 bytes 4 files changed, 22 insertions(+), 11 deletions(-) delete mode 100644 snowboy-2022/model/hotword.pmdl create mode 100644 snowboy-2022/model/up.pmdl diff --git a/snowboy-2022/build.sh b/snowboy-2022/build.sh index 5693ed3..5dd1a9d 100644 --- a/snowboy-2022/build.sh +++ b/snowboy-2022/build.sh @@ -17,10 +17,12 @@ if ! docker images | grep snowboy-pmdl.*latest &> /dev/null; then popd fi -if [ -n "$TRAIN" ] || [ ! -d ./model ] || [ ! -f ./model/hotword.pmdl ]; then +export HOTWORD="${HOTWORD:-default_hotword}" + +if [ -n "$TRAIN" ] || [ ! -d ./model ] || [ ! -f ./model/$HOTWORD.pmdl ]; then mkdir -p model pushd model - echo "record 3 instances of your hotword" >&2 + echo "record 3 instances of '$HOTWORD'" >&2 for i in 1 2 3; do read -p "ready? ctrl-c when done" rec \ @@ -38,6 +40,7 @@ if [ -n "$TRAIN" ] || [ ! -d ./model ] || [ ! -f ./model/hotword.pmdl ]; then -it \ -v "$(realpath ./model)":/snowboy-master/examples/Python/model \ snowboy-pmdl:latest + mv ./model/hotword.pmdl ./model/$HOTWORD.pmdl fi if false; then @@ -54,7 +57,7 @@ if false; then import snowboydecoder import datetime detected_callback = lambda *args: print(datetime.datetime.now(), "GOTCHA") - d = snowboydecoder.HotwordDetector("../../../model/hotword.pmdl", sensitivity=0.5, audio_gain=1) + d = snowboydecoder.HotwordDetector("../../../model/'"$HOTWORD"'.pmdl", sensitivity=0.5, audio_gain=1) d.start(detected_callback) ' > breel.py echo GO @@ -65,10 +68,10 @@ if false; then python3 ./breel.py else resources="$(realpath snowboy.git.d/resources/common.res)" - hotword="$(realpath ./model/hotword.pmdl)" + hotword="$(realpath ./model/$HOTWORD.pmdl)" GOPROXY= go build -o snowboy if [ -z "$PUSH" ]; then - ./snowboy -model "$hotword" -resources "$resources" -sensitivity 0.5 + ./snowboy -m "$hotword" -r "$resources" -s 0.5 "$@" else echo ' FROM registry-app.eng.qops.net:5001/imported/alpine:3.16 diff --git a/snowboy-2022/main.go b/snowboy-2022/main.go index 41588a8..a309f32 100644 --- a/snowboy-2022/main.go +++ b/snowboy-2022/main.go @@ -11,6 +11,7 @@ import ( "encoding/binary" "flag" "fmt" + "log" "time" "github.com/brentnd/go-snowboy" @@ -74,9 +75,10 @@ func (s *Sound) Read(p []byte) (int, error) { } func main() { - resources := flag.String("resources", "", "path to the .res file") - model := flag.String("model", "", "path to the .?mdl file") - sensitivity := flag.Float64("sensitivity", 0.75, "0..1") + resources := flag.String("r", "", "path to the .res file") + model := flag.String("m", "", "path to the .?mdl file") + sensitivity := flag.Float64("s", 0.45, "0..1") + quiet := flag.Bool("q", false, "emit '1' on detect else silent") flag.Parse() if *resources == "" || *model == "" { @@ -94,16 +96,22 @@ func main() { // set the handlers d.HandleFunc(snowboy.NewHotword(*model, float32(*sensitivity)), func(string) { - fmt.Println(time.Now(), "GOTCHA!") + if !*quiet { + log.Println("GOTCHA!") + } else { + fmt.Printf("1") + } }) d.HandleSilenceFunc(1*time.Second, func(string) { - fmt.Println("...") + if !*quiet { + log.Println("...") + } }) // display the detector's expected audio format sr, nc, bd := d.AudioFormat() - fmt.Printf("sample rate=%d, num channels=%d, bit depth=%d\n", sr, nc, bd) + log.Printf("sample rate=%d, num channels=%d, bit depth=%d\n", sr, nc, bd) // start detecting using the microphone d.ReadAndDetect(mic) diff --git a/snowboy-2022/model/hotword.pmdl b/snowboy-2022/model/hotword.pmdl deleted file mode 100644 index 46618c09ded075026ba86a1205693e4b984ca16a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8619 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 J!}z`B{|~?!IC}s9 diff --git a/snowboy-2022/model/up.pmdl b/snowboy-2022/model/up.pmdl new file mode 100644 index 0000000000000000000000000000000000000000..51646cd907e1931247ab854763b169732706e6d5 GIT binary patch literal 4683 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 literal 0 HcmV?d00001