diff options
| author | schneefux <schneefux+commit@schneefux.xyz> | 2014-10-06 16:59:36 +0200 |
|---|---|---|
| committer | schneefux <schneefux+commit@schneefux.xyz> | 2014-10-06 16:59:36 +0200 |
| commit | edca8b7407d7c9b1497ba1722d1b66ffa4b4c234 (patch) | |
| tree | d544987379415ac557751401ea0b0c7de81530b7 /client/stt.py | |
| parent | 890a5798fcf7f9b9dc06529aa4bc7fe903d7ca1a (diff) | |
| parent | 804da384bff556d3caedf9ad01d57f2460aee151 (diff) | |
| download | jasper-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.py | 104 |
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()) |
