Skip to content

Instantly share code, notes, and snippets.

@malceore
Created June 7, 2018 01:01
Show Gist options
  • Select an option

  • Save malceore/f41ca1059a9e4efac81c2d064712aecb to your computer and use it in GitHub Desktop.

Select an option

Save malceore/f41ca1059a9e4efac81c2d064712aecb to your computer and use it in GitHub Desktop.
Last Updated June 7th 2018
This Gist assumes that you are looking to run an always listening voice assitant client on a raspberry pi with a microphone/webcam
and then host the actual transcription service on something more beefy like a private server or VPS with which the raspberry pi
communicates. Going to extend this model and add a bunch of runtime flags for both whisper and assistant mock up, but later.
1. On a fresh Rasbian image run this Gist/Script to set everything up: https://gist.github.com/malceore/21477f76665001f119d6ab01236e0660
2. Then on your home server you will need to install Whisper: https://github.com/malceore/whisper .
3. Next you can put this Python client script in /<where-ever-you-installed-it>/snowboy/examples/Python/ on your Raspberry Pi as main.py :
#============================================
import pyaudio
import wave
import time
import os
import subprocess
from websocket import create_connection
import snowboydecoder
import sys
import signal
# Globals
INTER = False
CHUNK = 2048
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000
THRESHOLD = 2500
WS = create_connection("ws://<whispers-servers-IP>:9001")
def transcribe():
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("Starting Transcrition..")
WS.send("start")
subprocess.call(["aplay", "/home/pi/snowboy/resources/ding.wav", ">", "/dev/null", "2>&1"])
# Just added 4 seconds as test can make variable in a snap.
t_end = time.time() + 4
while time.time() < t_end:
WS.send_binary(stream.read(CHUNK))
WS.send("stop")
command_handler(WS.recv())
stream.close()
p.terminate()
def command_handler(commands):
c = commands.split(':')
print(c)
subprocess.call(["aplay", "/home/pi/snowboy/resources/ding.wav", ">", "/dev/null", "2>&1"])
def signal_handler(signal, frame):
global INTER
INTER = True
def interrupt_callback():
global INTER
return INTER
if len(sys.argv) == 1:
print("Error: need to specify model name")
print("Usage: python demo.py your.model")
sys.exit(-1)
model = sys.argv[1]
# capture SIGINT signal, e.g., Ctrl+C
signal.signal(signal.SIGINT, signal_handler)
detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
print('Listening... Press Ctrl+C to exit')
detector.start(detected_callback=transcribe,
interrupt_check=interrupt_callback,
sleep_time=0.03)
WS.close()
detector.terminate()
#================================
This uses Snowboy Hotword detector which requires a model, thankfully you can just make one for any word and download from
their website for free: https://snowboy.kitt.ai/ When you call the client it takes the path to your model as the only param.
When it hears your trigger word it will play a sound that comes with snowboy, then send four seconds of audio back to Whisper.
Finally whisper sends transcribed words back down the same websocket and you can act on them in command_handle function, by
default the client just prints out what it heard. I use mine to look for the word 'lights' and a number then make API calls.
Note: Default Whisper only detects the follow words: ADDONS, ALARM, ASSISTANT, AWAKEN, BACK, CALIBRATE, CANCEL, DOWN, EIGHT, EIGHTEEN
ELEVEN, FIFTEEN, FIVE, FOUR, FOURTEEN, GO, GOOD, GOODNIGHT, HALF, HOME, HOUR, LEFT, LIGHT, MORNING, MUTE, NINE, ONE, PAUSE, PLAY, RESTART, RIGHT
SELECT, SET, SETTINGS, SEVEN, SEVENTEEN, SIX, SIXTEEN, SLEEP, STOP, TEN, THIRTEEN, THREE, TO, TWELVE, TWO, UNMUTE, UP
Extras:
I would sugguest you add whisper to startup.
Here is a simple script I put on a cronjob running every so many minutes, means it will continue to restart if the process fails to
connect to whisper.
#!/bin/sh
ps aux | grep main.py | grep -v grep
if [ $? != 0 ]
then
/usr/bin/python /home/pi/snowboy/examples/Python/main.py /home/pi/lights.pmdl >> /home/pi/assistant.log &
fi
Please comment and let me know if this was useful or have sugguestions to change it. I offer no warranty or support. ;P
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment