Skip to content

Commit

Permalink
initial snowboy functionality
Browse files Browse the repository at this point in the history
First working version of snowboy. For passive stt only
  • Loading branch information
KrawallKurt authored and KrawallKurt committed Aug 7, 2016
1 parent b93dacf commit 2fc4435
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 108 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ __pycache__/

# C extensions
*.so
!_snowboydetect.so

# Distribution / packaging
.Python
Expand Down
6 changes: 3 additions & 3 deletions jasper/mic.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def __init__(self, input_device, output_device,
passive_stt_engine, active_stt_engine,
tts_engine, config, keyword='JASPER'):
self._logger = logging.getLogger(__name__)
self.keyword = keyword
self._keyword = keyword
self.tts_engine = tts_engine
self.passive_stt_engine = passive_stt_engine
self.active_stt_engine = active_stt_engine
Expand Down Expand Up @@ -141,7 +141,7 @@ def check_for_keyword(self, frame_queue, keyword_uttered, keyword):

def wait_for_keyword(self, keyword=None):
if not keyword:
keyword = self.keyword
keyword = self._keyword
frame_queue = queue.Queue()
keyword_uttered = threading.Event()

Expand Down Expand Up @@ -201,7 +201,7 @@ def wait_for_keyword(self, keyword=None):
audioop.rms(b"".join(frames), 2))

def listen(self):
self.wait_for_keyword(self.keyword)
self.wait_for_keyword(self._keyword)
return self.active_listen()

def active_listen(self, timeout=3):
Expand Down
2 changes: 1 addition & 1 deletion plugins/stt/snowboy-stt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# -*- coding: utf-8 -*-
from .snowboy import snowboydecoder
from .snowboy import SnowboySTTPlugin
Binary file added plugins/stt/snowboy-stt/_snowboydetect.so
Binary file not shown.
Binary file added plugins/stt/snowboy-stt/common.res
Binary file not shown.
12 changes: 5 additions & 7 deletions plugins/stt/snowboy-stt/plugin.info
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
[Plugin]
Name = snowboy-stt
Version = 0.0.1
License = APACHE
URL = https://github.com/kitt-ai/snowboy
Description = Snowboy is a customizable hotword detection engine for you to create your own hotword like "OK Google" or "Alexa".
Name = snowboy
Version = 1.0.0
License = MIT
Description = Speech-To-Text implementation which relies on Snowboy.

[Author]
Name = Chrobi
URL = http://github.com/chrobione/
Name = KrawallKurt
121 changes: 24 additions & 97 deletions plugins/stt/snowboy-stt/snowboy.py
Original file line number Diff line number Diff line change
@@ -1,114 +1,41 @@
import logging
import requests
import snowboydetect
from jasper import plugin

# There seems to be no way to get language setting of the defined app
# Last updated: April 06, 2016
SUPPORTED_LANG = (
'de',
'en',
'es',
'et',
'fr',
'it',
'nl',
'pl',
'pt',
'ru',
'sv'
)


class WitAiSTTPlugin(plugin.STTPlugin):
class SnowboySTTPlugin(plugin.STTPlugin):
"""
Speech-To-Text implementation which relies on the Wit.ai Speech API.
Hotword Detection which relies on Snowboy.
Excerpt from sample profile.yml:
This implementation requires an Wit.ai Access Token to be present in
profile.yml. Please sign up at https://wit.ai and copy your instance
token, which can be found under Settings in the Wit console to your
profile.yml:
...
stt_engine: witai-stt
witai-stt:
access_token: ERJKGE86SOMERANDOMTOKEN23471AB
snowboy-stt:
model: Hello_Jasper.pmdl
"""

def __init__(self, *args, **kwargs):
"""
Create Plugin Instance
"""
plugin.STTPlugin.__init__(self, *args, **kwargs)
self._logger = logging.getLogger(__name__)
self.token = self.profile['witai-stt']['access_token']

self.resource_file = "plugins/stt/snowboy-stt/common.res"
self.model = self.profile['snowboy']['model']
try:
language = self.profile['language']
self.sensitivity = self.profile['snowboy']['sensitivity']
except KeyError:
language = 'en-US'
if language.split('-')[0] not in SUPPORTED_LANG:
raise ValueError('Language %s is not supported.',
language.split('-')[0])

@property
def token(self):
"""
Return defined acess token.
"""
return self._token

@property
def language(self):
"""
Returns selected language
"""
return self._language
self.sensitivity = "0.5"

@token.setter
def token(self, value):
"""
Sets property token
"""
self._token = value
self._headers = {'Authorization': 'Bearer %s' % self.token,
'accept': 'application/json',
'Content-Type': 'audio/wav'}

@property
def headers(self):
"""
Return headers
"""
return self._headers
self.detector = snowboydetect.SnowboyDetect(
resource_filename=self.resource_file,
model_str=self.model)
self.detector.SetAudioGain(1)
self.detector.SetSensitivity(self.sensitivity);

def transcribe(self, fp):
"""
transcribes given audio file by uploading to wit.ai and returning
received text from json answer.
"""
fp.seek(44)
data = fp.read()
r = requests.post('https://api.wit.ai/speech?v=20150101',
data=data,
headers=self.headers)
try:
r.raise_for_status()
text = r.json()['_text']
except requests.exceptions.HTTPError:
self._logger.critical('Request failed with response: %r',
r.text,
exc_info=True)
return []
except requests.exceptions.RequestException:
self._logger.critical('Request failed.', exc_info=True)
return []
except ValueError as e:
self._logger.critical('Cannot parse response: %s',
e.args[0])
return []
except KeyError:
self._logger.critical('Cannot parse response.',
exc_info=True)
return []

ans = self.detector.RunDetection(data)

if ans:
return [self._vocabulary_phrases[-1]]
else:
transcribed = [text.upper()]
self._logger.info('Transcribed: %r', transcribed)
return transcribed
return []
143 changes: 143 additions & 0 deletions plugins/stt/snowboy-stt/snowboydetect.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# This file was automatically generated by SWIG (http://www.swig.org).
# Version 3.0.7
#
# Do not make changes to this file unless you know what you are doing--modify
# the SWIG interface file instead.





from sys import version_info
if version_info >= (2, 6, 0):
def swig_import_helper():
from os.path import dirname
import imp
fp = None
try:
fp, pathname, description = imp.find_module('_snowboydetect', [dirname(__file__)])
except ImportError:
import _snowboydetect
return _snowboydetect
if fp is not None:
try:
_mod = imp.load_module('_snowboydetect', fp, pathname, description)
finally:
fp.close()
return _mod
_snowboydetect = swig_import_helper()
del swig_import_helper
else:
import _snowboydetect
del version_info
try:
_swig_property = property
except NameError:
pass # Python < 2.2 doesn't have 'property'.


def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
if (name == "thisown"):
return self.this.own(value)
if (name == "this"):
if type(value).__name__ == 'SwigPyObject':
self.__dict__[name] = value
return
method = class_type.__swig_setmethods__.get(name, None)
if method:
return method(self, value)
if (not static):
if _newclass:
object.__setattr__(self, name, value)
else:
self.__dict__[name] = value
else:
raise AttributeError("You cannot add attributes to %s" % self)


def _swig_setattr(self, class_type, name, value):
return _swig_setattr_nondynamic(self, class_type, name, value, 0)


def _swig_getattr_nondynamic(self, class_type, name, static=1):
if (name == "thisown"):
return self.this.own()
method = class_type.__swig_getmethods__.get(name, None)
if method:
return method(self)
if (not static):
return object.__getattr__(self, name)
else:
raise AttributeError(name)

def _swig_getattr(self, class_type, name):
return _swig_getattr_nondynamic(self, class_type, name, 0)


def _swig_repr(self):
try:
strthis = "proxy of " + self.this.__repr__()
except:
strthis = ""
return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)

try:
_object = object
_newclass = 1
except AttributeError:
class _object:
pass
_newclass = 0


class SnowboyDetect(_object):
__swig_setmethods__ = {}
__setattr__ = lambda self, name, value: _swig_setattr(self, SnowboyDetect, name, value)
__swig_getmethods__ = {}
__getattr__ = lambda self, name: _swig_getattr(self, SnowboyDetect, name)
__repr__ = _swig_repr

def __init__(self, resource_filename, model_str):
this = _snowboydetect.new_SnowboyDetect(resource_filename, model_str)
try:
self.this.append(this)
except:
self.this = this

def Reset(self):
return _snowboydetect.SnowboyDetect_Reset(self)

def RunDetection(self, data):
return _snowboydetect.SnowboyDetect_RunDetection(self, data)

def SetSensitivity(self, sensitivity_str):
return _snowboydetect.SnowboyDetect_SetSensitivity(self, sensitivity_str)

def GetSensitivity(self):
return _snowboydetect.SnowboyDetect_GetSensitivity(self)

def SetAudioGain(self, audio_gain):
return _snowboydetect.SnowboyDetect_SetAudioGain(self, audio_gain)

def UpdateModel(self):
return _snowboydetect.SnowboyDetect_UpdateModel(self)

def NumHotwords(self):
return _snowboydetect.SnowboyDetect_NumHotwords(self)

def SampleRate(self):
return _snowboydetect.SnowboyDetect_SampleRate(self)

def NumChannels(self):
return _snowboydetect.SnowboyDetect_NumChannels(self)

def BitsPerSample(self):
return _snowboydetect.SnowboyDetect_BitsPerSample(self)
__swig_destroy__ = _snowboydetect.delete_SnowboyDetect
__del__ = lambda self: None
SnowboyDetect_swigregister = _snowboydetect.SnowboyDetect_swigregister
SnowboyDetect_swigregister(SnowboyDetect)

# This file is compatible with both classic and new-style classes.


0 comments on commit 2fc4435

Please sign in to comment.