summaryrefslogtreecommitdiff
path: root/client/stt.py
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2014-10-06 16:59:36 +0200
committerschneefux <schneefux+commit@schneefux.xyz>2014-10-06 16:59:36 +0200
commitedca8b7407d7c9b1497ba1722d1b66ffa4b4c234 (patch)
treed544987379415ac557751401ea0b0c7de81530b7 /client/stt.py
parent890a5798fcf7f9b9dc06529aa4bc7fe903d7ca1a (diff)
parent804da384bff556d3caedf9ad01d57f2460aee151 (diff)
downloadjasper-client-edca8b7407d7c9b1497ba1722d1b66ffa4b4c234.tar.gz
jasper-client-edca8b7407d7c9b1497ba1722d1b66ffa4b4c234.zip
Merge pull request #217 from Holzhaus/style-fixes
Style fixes
Diffstat (limited to 'client/stt.py')
-rw-r--r--client/stt.py104
1 files changed, 71 insertions, 33 deletions
diff --git a/client/stt.py b/client/stt.py
index c5caf99..cfaced6 100644
--- a/client/stt.py
+++ b/client/stt.py
@@ -16,16 +16,18 @@ import jasperpath
The default Speech-to-Text implementation which relies on PocketSphinx.
"""
+
class TranscriptionMode:
NORMAL, KEYWORD, MUSIC = range(3)
+
class AbstractSTTEngine(object):
"""
Generic parent class for all STT engines
"""
__metaclass__ = ABCMeta
-
+
@classmethod
def get_config(cls):
return {}
@@ -39,14 +41,18 @@ class AbstractSTTEngine(object):
def transcribe(self, fp, mode=TranscriptionMode.NORMAL):
pass
+
class PocketSphinxSTT(AbstractSTTEngine):
SLUG = 'sphinx'
- def __init__(self, lmd=jasperpath.config("languagemodel.lm"), dictd=jasperpath.config("dictionary.dic"),
- lmd_persona=jasperpath.data("languagemodel_persona.lm"), dictd_persona=jasperpath.data("dictionary_persona.dic"),
+ def __init__(self, lmd=jasperpath.config("languagemodel.lm"),
+ dictd=jasperpath.config("dictionary.dic"),
+ lmd_persona=jasperpath.data("languagemodel_persona.lm"),
+ dictd_persona=jasperpath.data("dictionary_persona.dic"),
lmd_music=None, dictd_music=None,
- hmm_dir="/usr/local/share/pocketsphinx/model/hmm/en_US/hub4wsj_sc_8k"):
+ hmm_dir="/usr/local/share/pocketsphinx/model/hmm/en_US/" +
+ "hub4wsj_sc_8k"):
"""
Initiates the pocketsphinx instance.
@@ -54,7 +60,8 @@ class PocketSphinxSTT(AbstractSTTEngine):
speaker -- handles platform-independent audio output
lmd -- filename of the full language model
dictd -- filename of the full dictionary (.dic)
- lmd_persona -- filename of the 'Persona' language model (containing, e.g., 'Jasper')
+ lmd_persona -- filename of the 'Persona' language model (containing,
+ e.g., 'Jasper')
dictd_persona -- filename of the 'Persona' dictionary (.dic)
"""
@@ -67,25 +74,35 @@ class PocketSphinxSTT(AbstractSTTEngine):
import pocketsphinx as ps
self._logfiles = {}
- with tempfile.NamedTemporaryFile(prefix='psdecoder_music_', suffix='.log', delete=False) as f:
+ with tempfile.NamedTemporaryFile(prefix='psdecoder_music_',
+ suffix='.log', delete=False) as f:
self._logfiles[TranscriptionMode.MUSIC] = f.name
- with tempfile.NamedTemporaryFile(prefix='psdecoder_keyword_', suffix='.log', delete=False) as f:
+ with tempfile.NamedTemporaryFile(prefix='psdecoder_keyword_',
+ suffix='.log', delete=False) as f:
self._logfiles[TranscriptionMode.KEYWORD] = f.name
- with tempfile.NamedTemporaryFile(prefix='psdecoder_normal_', suffix='.log', delete=False) as f:
+ with tempfile.NamedTemporaryFile(prefix='psdecoder_normal_',
+ suffix='.log', delete=False) as f:
self._logfiles[TranscriptionMode.NORMAL] = f.name
self._decoders = {}
if lmd_music and dictd_music:
- self._decoders[TranscriptionMode.MUSIC] = ps.Decoder(hmm=hmm_dir, lm=lmd_music, dict=dictd_music, logfn=self._logfiles[TranscriptionMode.MUSIC])
- self._decoders[TranscriptionMode.KEYWORD] = ps.Decoder(hmm=hmm_dir, lm=lmd_persona, dict=dictd_persona, logfn=self._logfiles[TranscriptionMode.KEYWORD])
- self._decoders[TranscriptionMode.NORMAL] = ps.Decoder(hmm=hmm_dir, lm=lmd, dict=dictd, logfn=self._logfiles[TranscriptionMode.NORMAL])
+ self._decoders[TranscriptionMode.MUSIC] = \
+ ps.Decoder(hmm=hmm_dir, lm=lmd_music, dict=dictd_music,
+ logfn=self._logfiles[TranscriptionMode.MUSIC])
+ self._decoders[TranscriptionMode.KEYWORD] = \
+ ps.Decoder(hmm=hmm_dir, lm=lmd_persona, dict=dictd_persona,
+ logfn=self._logfiles[TranscriptionMode.KEYWORD])
+ self._decoders[TranscriptionMode.NORMAL] = \
+ ps.Decoder(hmm=hmm_dir, lm=lmd, dict=dictd,
+ logfn=self._logfiles[TranscriptionMode.NORMAL])
def __del__(self):
for filename in self._logfiles.values():
os.remove(filename)
@classmethod
- def get_config(cls): #FIXME: Replace this as soon as we have a config module
+ def get_config(cls):
+ # FIXME: Replace this as soon as we have a config module
config = {}
# HMM dir
# Try to get hmm_dir from config
@@ -101,13 +118,16 @@ class PocketSphinxSTT(AbstractSTTEngine):
if 'dictd' in profile['pocketsphinx']:
config['dictd'] = profile['pocketsphinx']['dictd']
if 'lmd_persona' in profile['pocketsphinx']:
- config['lmd_persona'] = profile['pocketsphinx']['lmd_persona']
+ config['lmd_persona'] = \
+ profile['pocketsphinx']['lmd_persona']
if 'dictd_persona' in profile['pocketsphinx']:
- config['dictd_persona'] = profile['pocketsphinx']['dictd_persona']
+ config['dictd_persona'] = \
+ profile['pocketsphinx']['dictd_persona']
if 'lmd_music' in profile['pocketsphinx']:
config['lmd'] = profile['pocketsphinx']['lmd_music']
if 'dictd_music' in profile['pocketsphinx']:
- config['dictd_music'] = profile['pocketsphinx']['dictd_music']
+ config['dictd_music'] = \
+ profile['pocketsphinx']['dictd_music']
return config
def transcribe(self, fp, mode=TranscriptionMode.NORMAL):
@@ -116,7 +136,8 @@ class PocketSphinxSTT(AbstractSTTEngine):
Arguments:
audio_file_path -- the path to the audio file to-be transcribed
- PERSONA_ONLY -- if True, uses the 'Persona' language model and dictionary
+ PERSONA_ONLY -- if True, uses the 'Persona' language model and
+ dictionary
MUSIC -- if True, uses the 'Music' language model and dictionary
"""
decoder = self._decoders[mode]
@@ -129,7 +150,7 @@ class PocketSphinxSTT(AbstractSTTEngine):
decoder.start_utt()
decoder.process_raw(data, False, True)
decoder.end_utt()
-
+
result = decoder.get_hyp()
with open(self._logfiles[mode], 'r+') as f:
if mode == TranscriptionMode.KEYWORD:
@@ -158,11 +179,16 @@ Speech-To-Text implementation which relies on the Google Speech API.
This implementation requires a Google API key to be present in profile.yml
To obtain an API key:
-1. Join the Chromium Dev group: https://groups.google.com/a/chromium.org/forum/?fromgroups#!forum/chromium-dev
-2. Create a project through the Google Developers console: https://console.developers.google.com/project
-3. Select your project. In the sidebar, navigate to "APIs & Auth." Activate the Speech API.
-4. Under "APIs & Auth," navigate to "Credentials." Create a new key for public API access.
-5. Add your credentials to your profile.yml. Add an entry to the 'keys' section using the key name 'GOOGLE_SPEECH.' Sample configuration:
+1. Join the Chromium Dev group:
+ https://groups.google.com/a/chromium.org/forum/?fromgroups#!forum/chromium-dev
+2. Create a project through the Google Developers console:
+ https://console.developers.google.com/project
+3. Select your project. In the sidebar, navigate to "APIs & Auth." Activate
+ the Speech API.
+4. Under "APIs & Auth," navigate to "Credentials." Create a new key for public
+ API access.
+5. Add your credentials to your profile.yml. Add an entry to the 'keys' section
+ using the key name 'GOOGLE_SPEECH.' Sample configuration:
6. Set the value of the 'stt_engine' key in your profile.yml to 'google'
@@ -181,7 +207,8 @@ class GoogleSTT(AbstractSTTEngine):
SLUG = 'google'
- def __init__(self, api_key=None): #FIXME: get init args from config
+ def __init__(self, api_key=None):
+ # FIXME: get init args from config
"""
Arguments:
api_key - the public api key which allows access to Google APIs
@@ -192,7 +219,8 @@ class GoogleSTT(AbstractSTTEngine):
self.http = requests.Session()
@classmethod
- def get_config(cls): #FIXME: Replace this as soon as we have a config module
+ def get_config(cls):
+ # FIXME: Replace this as soon as we have a config module
config = {}
# HMM dir
# Try to get hmm_dir from config
@@ -206,8 +234,8 @@ class GoogleSTT(AbstractSTTEngine):
def transcribe(self, fp, mode=TranscriptionMode.NORMAL):
"""
- Performs STT via the Google Speech API, transcribing an audio file and returning an English
- string.
+ Performs STT via the Google Speech API, transcribing an audio file and
+ returning an English string.
Arguments:
audio_file_path -- the path to the .wav file to be transcribed
@@ -217,8 +245,9 @@ class GoogleSTT(AbstractSTTEngine):
frame_rate = wav.getframerate()
wav.close()
- url = "https://www.google.com/speech-api/v2/recognize?output=json&client=chromium&key=%s&lang=%s&maxresults=6&pfilter=2" % (
- self.api_key, "en-us")
+ url = (("https://www.google.com/speech-api/v2/recognize?output=json" +
+ "&client=chromium&key=%s&lang=%s&maxresults=6&pfilter=2") %
+ (self.api_key, "en-us"))
data = fp.read()
@@ -231,7 +260,8 @@ class GoogleSTT(AbstractSTTEngine):
response_parts = response_read.strip().split("\n")
decoded = json.loads(response_parts[-1])
if decoded['result']:
- texts = [alt['transcript'] for alt in decoded['result'][0]['alternative']]
+ texts = [alt['transcript'] for alt in
+ decoded['result'][0]['alternative']]
if texts:
print "==================="
print "JASPER: " + ', '.join(texts)
@@ -256,17 +286,25 @@ Arguments:
engine_type - one of "sphinx" or "google"
kwargs - keyword arguments passed to the constructor of the STT engine
"""
+
+
def get_engines():
- return [stt_engine for stt_engine in AbstractSTTEngine.__subclasses__() if hasattr(stt_engine, 'SLUG') and stt_engine.SLUG]
+ return [stt_engine for stt_engine in AbstractSTTEngine.__subclasses__()
+ if hasattr(stt_engine, 'SLUG') and stt_engine.SLUG]
+
def newSTTEngine(stt_engine, **kwargs):
- selected_engines = filter(lambda engine: hasattr(engine, "SLUG") and engine.SLUG == stt_engine, get_engines())
+ selected_engines = filter(lambda engine: hasattr(engine, "SLUG") and
+ engine.SLUG == stt_engine, get_engines())
if len(selected_engines) == 0:
raise ValueError("No STT engine found for slug '%s'" % stt_engine)
else:
if len(selected_engines) > 1:
- print("WARNING: Multiple STT engines found for slug '%s'. This is most certainly a bug." % stt_engine)
+ print(("WARNING: Multiple STT engines found for slug '%s'. This " +
+ "is most certainly a bug.") % stt_engine)
engine = selected_engines[0]
if not engine.is_available():
- raise ValueError("STT engine '%s' is not available (due to missing dependencies, missing dependencies, etc.)" % stt_engine)
+ raise ValueError(("STT engine '%s' is not available (due to " +
+ "missing dependencies, missing dependencies, " +
+ "etc.)") % stt_engine)
return engine(**engine.get_config())