def set_profile_password(path, value): global _profile _logger = logging.getLogger(__name__) if (isinstance(path, str)): path = [path] # Encrypt value first_id = hashlib.sha256( run_command("cat /etc/machine-id".split(), capture=1).stdout).hexdigest() second_id = hashlib.sha256( run_command("hostid".split(), capture=1).stdout).hexdigest() try: third_idb1 = run_command("blkid".split(), capture=1).stdout.decode().strip() third_id = hashlib.sha256( run_command("""grep -oP 'UUID="\\K[^"]+'""".split(), capture=4, stdin=third_idb1).stdout).hexdigest() except FileNotFoundError: _logger.warning(" ".join([ "Package not installed: 'blkid'", "Please install it manually or run apt_requirements.sh again" ])) third_id = "" salt = get_profile_key() kdf = PBKDF2HMAC(algorithm=hashes.SHA512(), length=32, salt=salt, iterations=100000, backend=default_backend()) password = ''.join([first_id, second_id, third_id]).encode() key = base64.urlsafe_b64encode(kdf.derive(password)) cipher_suite = Fernet(key) cipher_text = cipher_suite.encrypt(value.encode("utf-8")).decode("utf-8") set_profile_var(path, cipher_text)
def generate_scorer(directory, phrases): print("Generating scorer: {}".format(directory)) languagemodel_path = get_languagemodel_path(directory) with open(languagemodel_path, "w") as f: f.writelines(line_generator(phrases)) version = "v{}".format(deepspeech.version()) sourcedir_name = "STT{}".format(version) sourcedir_path = paths.sub(os.path.join("sources", sourcedir_name)) kenlm_sourcedir = paths.sub(os.path.join("sources", "kenlm")) kenlm_bins = os.path.join(kenlm_sourcedir, 'build', 'bin') cmd = [ 'python', os.path.join(sourcedir_path, 'data', 'lm', 'generate_lm.py'), '--input_txt', languagemodel_path, '--output_dir', directory, '--kenlm_bins', kenlm_bins, '--binary_type', 'trie', '--top_k', '500000', '--arpa_order', '5', '--max_arpa_memory', '10%', '--arpa_prune', '0|0|1', '--binary_a_bits', '255', '--binary_q_bits', '8', '--discount_fallback' ] completed_process = run_command(cmd, 2) if (completed_process.returncode == 0): # There should be an additional step here where the # default values of alpha and beta are generated by # lm_optimizer. However, that involves building a # dev set from data in the audiolog. # Generate the scorer package # I'm still trying to figure out where to get the # generate_scorer_package binary. I found mine in the # ~/.cache/bazel folder after running bazel build # on //native_client:generate_scorer_package # I think there are binary packages available on # github, but you have to know your processor type, # and since I am testing on Raspbianx86, I have to # build it. x86_64 or rpi are available on Github. print("Generating scorer package") binarydir_name = "native_client{}".format(version) binarydir_path = paths.sub( os.path.join("sources", binarydir_name, "generate_scorer_package")) cmd = [ binarydir_path, '--alphabet', os.path.join(sourcedir_path, 'data', 'alphabet.txt'), '--lm', os.path.join(directory, 'lm.binary'), '--vocab', os.path.join(directory, 'vocab-500000.txt'), '--package', os.path.join(directory, 'scorer'), '--default_alpha', '0.931289105002', '--default_beta', '1.18341375810284' ] completed_process = run_command(cmd, 2) if (completed_process.returncode != 0): print(completed_process.stderr.decode("UTF-8")) else: print(completed_process.stderr.decode("UTF-8")) print(os.path.join(directory, 'scorer')) return os.path.join(directory, 'scorer')
def check_pocketsphinx_model(directory): # Start by assuming the files exist. If any file is found to not # exist, then set this to False FilesExist = True if (not os.path.isfile(os.path.join(directory, "mdef.txt"))): if (os.path.isfile(os.path.join(directory, "mdef"))): command = [ "pocketsphinx_mdef_convert", "-text", os.path.join(directory, "mdef"), os.path.join(directory, "mdef.txt") ] completedprocess = run_command(command) print("Command {} returned {}".format( " ".join(completedprocess.args), completedprocess.returncode)) if (not os.path.isfile(os.path.join(directory, "mdef.txt"))): FilesExist = False if (not os.path.isfile(os.path.join(directory, "means"))): FilesExist = False if (not os.path.isfile(os.path.join(directory, "mixture_weights"))): FilesExist = False if (not os.path.isfile(os.path.join(directory, "sendump"))): FilesExist = False if (not os.path.isfile(os.path.join(directory, "variances"))): FilesExist = False return FilesExist
def say(self, phrase): cmd = [ 'espeak', '-v', self.voice, '-p', self.pitch_adjustment, '-s', self.words_per_minute, '--stdout', phrase ] cmd = [str(x) for x in cmd] self._logger.debug('Executing %s', ' '.join([pipes.quote(arg) for arg in cmd])) data = run_command(cmd, 1).stdout return data
def get_voices(self): output = run_command(['espeak', '--voices'], 1).stdout.decode("UTF-8") output += run_command(['espeak', '--voices=mbrola'], 1).stdout.decode("UTF-8") voices = [] for pty, lang, gender, name, other in RE_PATTERN.findall(output): voices.append( Voice(name=name, gender=gender, priority=int(pty), language=lang)) if len(other) > 0: for lang2, pty2 in RE_OTHER.findall(other): voices.append( Voice(name=name, gender=gender, priority=int(pty2), language=lang2)) return sorted(voices, key=lambda voice: voice.priority)
def settings(self): _ = self.gettext try: tz = run_command(["/bin/cat", "/etc/timezone"], capture=1).stdout.decode('utf-8').strip() except OSError: tz = None return OrderedDict({ ('timezone', ): { "title": _("What is your timezone?"), "description": _("Please enter a timezone from the list located in the TZ* column at http://en.wikipedia.org/wiki/List_of_tz_database_time_zones" ), "default": tz } })
def __init__(self, *args, **kwargs): """ Create Plugin Instance """ plugin.STTPlugin.__init__(self, *args, **kwargs) # Check that we have the correct project source downloaded # Currently we are only using this for the generate_lm.py # script. version = "v{}".format(deepspeech.version()) sourcedir_name = "STT{}".format(version) sourcedir_path = paths.sub(os.path.join("sources", sourcedir_name)) if (not os.path.isdir(sourcedir_path)): # use git to download the appropriate source directory print( "Downloading (cloning) Mozilla DeepSpeech Source to {}".format( sourcedir_path)) cmd = [ 'git', 'clone', '-b', version, 'https://github.com/mozilla/STT', sourcedir_path ] completed_process = run_command(cmd, 2) if (completed_process.returncode != 0): self._logger.error(completed_process.stderr.decode("UTF-8")) exit(1) # Download the release binaries. We need to get the # generate_scorer_package from here. binarydir_name = "native_client{}".format(version) binarydir_path = paths.sub(os.path.join("sources", binarydir_name)) if (not os.path.isdir(binarydir_path)): os.makedirs(binarydir_path) binary_url = None if (platform.machine() == "x86_64"): arch = "amd64" binary_url = 'https://github.com/mozilla/DeepSpeech/releases/download/{}/native_client.{}.cpu.linux.tar.xz'.format( version, arch) if (platform.machine() == "armv7l"): arch = "rpi3" binary_url = 'https://github.com/mozilla/DeepSpeech/releases/download/{}/native_client.{}.cpu.linux.tar.xz'.format( version, arch) # Unfortunately, it does not appear that the native client is # compiled for x86 machines, so Raspbianx86 users are out of luck # for right now. if (binary_url is None): print( "Architecture not recognized. Please add it to {}".format( __file__)) else: print("Downloading native client binaries from {}".format( binary_url)) cmd = [ 'wget', binary_url, '--directory-prefix={}'.format(binarydir_path), '--output-document={}'.format( os.path.join(binarydir_path, 'native_client.tar.xz')) ] print(" ".join(cmd)) completed_process = run_command(cmd, 2) if (completed_process.returncode == 0): # unzip the archive into the binarydir_path directory cmd = [ 'tar', 'Jxvf', os.path.join(binarydir_path, 'native_client.tar.xz'), '-C', binarydir_path ] completed_process = run_command(cmd, 2) if (completed_process.returncode != 0): print(completed_process.stderr.decode("UTF-8")) else: print(completed_process.stderr.decode("UTF-8")) kenlm_sourcedir = paths.sub(os.path.join("sources", "kenlm")) if (not os.path.isdir(kenlm_sourcedir)): # use git to download kenlm print("Cloning KenLM") cmd = [ 'git', 'clone', 'https://github.com/kpu/kenlm.git', kenlm_sourcedir ] completed_process = run_command(cmd, 2) if (completed_process.returncode == 0): # build kenlm print("Building KenLM") build_dir = os.path.join(kenlm_sourcedir, "build") if (not os.path.isdir(build_dir)): os.makedirs(build_dir) os.chdir(build_dir) cmd = ['cmake', '..'] completed_process = run_command(cmd, 2, cwd=build_dir) if (completed_process.returncode == 0): cmd = ['make'] completed_process = run_command(cmd, 2, cwd=build_dir) if (completed_process.returncode != 0): self._logger.error( completed_process.stderr.decode("UTF-8")) exit(1) else: self._logger.error( completed_process.stderr.decode("UTF-8")) exit(1) else: self._logger.error(completed_process.stderr.decode("UTF-8")) exit(1) # Beam width used in the CTC decoder when building candidate # transcriptions self._BEAM_WIDTH = profile.get(['deepspeech', 'beam_width'], 500) # Only 16KHz files are currently supported self._FS = profile.get(['deepspeech', 'fs'], 16000) # These are paths. They are required. # Path to the model (protocol buffer binary file) working_dir = os.path.expanduser( profile.get(['deepspeech', 'working_dir'])) if (not os.path.isdir(working_dir)): os.makedirs(working_dir) download_url = 'https://github.com/mozilla/DeepSpeech/releases/download/{}/deepspeech-{}-models.pbmm'.format( version, deepspeech.version()) self._MODEL = os.path.join(working_dir, "model_{}.pbmm".format(version)) if (platform.machine() == 'armv7l'): download_url = 'https://github.com/mozilla/DeepSpeech/releases/download/{}/deepspeech-{}-models.tflite'.format( version, deepspeech.version()) self._MODEL = os.path.join(working_dir, "model_{}.tflite".format(version)) self._logger.info("Model: {}".format(self._MODEL)) if (not os.path.isfile(self._MODEL)): print("Downloading {}".format(download_url)) # FIXME it would be good to have a progress indicator here. # This can take a long time depending on your bandwidth. self._MODEL = app_utils.download_file(download_url, self._MODEL) print("Saved as {}".format(self._MODEL)) print("Download completed") self._ds = deepspeech.Model(self._MODEL) scorer_file = os.path.join(self.compile_vocabulary(generate_scorer), "scorer") self._ds.enableExternalScorer(scorer_file)
def get_profile_password(path, default=None): """ Get a value from the profile, whether it exists or not If the value does not exist in the profile, returns either the default value (if there is one) or None. """ _logger = logging.getLogger(__name__) allowed = [] allowed.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'app_utils.py')) allowed.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'commandline.py')) allowed.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'application.py')) filename = inspect.getframeinfo(sys._getframe(1))[0] if (filename in allowed): if (isinstance(path, str)): path = [path] first_id = hashlib.sha256( run_command("cat /etc/machine-id".split(), capture=1).stdout).hexdigest() second_id = hashlib.sha256( run_command("hostid".split(), capture=1).stdout).hexdigest() try: third_idb1 = run_command("blkid".split(), capture=1).stdout.decode().strip() third_id = hashlib.sha256( run_command("""grep -oP 'UUID="\\K[^"]+'""".split(), capture=4, stdin=third_idb1).stdout).hexdigest() except FileNotFoundError: _logger.warning(" ".join([ "Package not installed: 'blkid'", "Please install it manually or run apt_requirements.sh again" ])) third_id = "" salt = get_profile_key() kdf = PBKDF2HMAC(algorithm=hashes.SHA512(), length=32, salt=salt, iterations=100000, backend=default_backend()) password = ''.join([first_id, second_id, third_id]).encode() key = base64.urlsafe_b64encode(kdf.derive(password)) cipher_suite = Fernet(key) response = get_profile_var(path, None) try: if (hasattr(response, "encode")): response = cipher_suite.decrypt( response.encode("utf-8")).decode("utf-8") except InvalidToken: response = None if response is None: response = default else: print( "Access to encrypted profile elements not allowed from {}".format( filename)) _logger.warn( "Access to encrypted profile elements not allowed from {}".format( filename)) response = None return response
def HandleCommand(self, command, description): try: conn = sqlite3.connect(self.audiolog_db) c = conn.cursor() response = [] continue_next = True nextcommand = "" if (command == ""): response.append( "<h2>Preparing to adapt Pocketsphinx model</h2>") description.append( "Adapting standard {} pocketsphinx model".format( self.language)) nextcommand = "checkenviron" if (command == "checkenviron"): # Now run through the steps to adapt the standard model # Start by checking to see if we have a copy of the standard # model for this user's chosen language and download it if not. # Check for the files we need if (not check_pocketsphinx_model(self.standard_dir)): # Check and see if we already have a copy of the standard # language model cmd = [ 'git', 'clone', '-b', self.language, 'https://github.com/NaomiProject/CMUSphinx_standard_language_models.git', self.standard_dir ] completedprocess = run_command(cmd) response.append( process_completedprocess(completedprocess, output='html')) if (completedprocess.returncode != 0): continue_next = False response.append("Environment configured") nextcommand = "prepareworkingdir" if (command == "prepareworkingdir"): # At this point, we should have the standard model we need if (check_pocketsphinx_model(self.standard_dir)): # FIXME It might be safest to remove the working dir at this # point if it already exists if not os.path.isdir(self.model_dir): # Copy the sphinx model into model_dir shutil.copytree(self.standard_dir, self.model_dir) if (check_pocketsphinx_model(self.model_dir)): query = " ".join([ "select", " rowid,", " case", " when length(trim(verified_transcription))>0", " then (length(trim(verified_transcription))-length(replace(trim(verified_transcription),' ','')))+1", " else 0", " end as WordCount,", " filename,", " upper(trim(replace(replace(verified_transcription,'?',''),',',''))) as transcription", "from audiolog", "where type in('active','passive') and reviewed!=''" ]) df = pd.read_sql_query(query, conn) # Take the above and create naomi.fileids and naomi.transcription # fileids: description.append("on {} wav files".format( str(df.shape[0]))) response.append("Adapting on {} wav files".format( df.shape[0])) with open( os.path.join(self.working_dir, "naomi.fileids"), "w+") as f: for filename in df['filename']: # No need to copy file, just leave it in audiolog f.write("{}\n".format( filename.rsplit(".", 1)[0])) with open( os.path.join(self.working_dir, "naomi.transcription"), "w+") as f: for t in df['transcription']: f.write("<s> {} </s>\n".format(t.lower())) nextcommand = "featureextraction" else: response.append( "Error: failed to populate working model") if (command == "featureextraction"): cmd = [ 'sphinx_fe', '-argfile', os.path.join(self.model_dir, 'feat.params'), '-samprate', '16000', '-c', os.path.join(self.working_dir, 'naomi.fileids'), '-di', self.audiolog_dir, '-do', self.working_dir, '-ei', 'wav', '-eo', 'mfc', '-mswav', 'yes' ] completedprocess = run_command(cmd) response.append( process_completedprocess(completedprocess, output='html')) if (completedprocess.returncode != 0): continue_next = False nextcommand = "buildweights" if (command == "buildweights"): bw = '/usr/lib/sphinxtrain/bw' if os.path.isfile('/usr/local/libexec/sphinxtrain/bw'): bw = '/usr/local/libexec/sphinxtrain/bw' cmd = [ bw, '-hmmdir', self.model_dir, '-moddeffn', os.path.join(self.model_dir, 'mdef.txt'), '-ts2cbfn', '.ptm.', '-feat', '1s_c_d_dd', '-svspec', '0-12/13-25/26-38', '-cmn', 'current', '-agc', 'none', '-dictfn', os.path.join(self.model_dir, 'cmudict.dict'), '-ctlfn', os.path.join(self.working_dir, 'naomi.fileids'), '-lsnfn', os.path.join(self.working_dir, 'naomi.transcription'), '-cepdir', self.working_dir, '-accumdir', self.working_dir ] completedprocess = run_command(cmd) response.append( process_completedprocess(completedprocess, output='html')) if (completedprocess.returncode != 0): continue_next = False nextcommand = "mllr" if (command == "mllr"): # MLLR is a cheap adaptation method that is suitable when the amount of data is limited. It's good for online adaptation. # MLLR works best for a continuous model. It's effect for semi-continuous models is limited. mllr = '/usr/lib/sphinxtrain/mllr_solve' if os.path.isfile('/usr/local/libexec/sphinxtrain/mllr_solve'): mllr = '/usr/local/libexec/sphinxtrain/mllr_solve' cmd = [ mllr, '-meanfn', os.path.join(self.model_dir, 'means'), '-varfn', os.path.join(self.model_dir, 'variances'), '-outmllrfn', os.path.join(self.model_dir, 'mllr_matrix'), '-accumdir', self.working_dir ] completedprocess = run_command(cmd) response.append( process_completedprocess(completedprocess, output='html')) if (completedprocess.returncode != 0): continue_next = False nextcommand = "map" if (command == "map"): # Update the acoustic model files with MAP # In this case, unlike MLLR, we don't create a generic transform, but update each parameter in the model # We copy the acoustic model directory and overwrite the new directory with the adapted model files if (os.path.isdir(self.adapt_dir)): # Remove the adapt dir shutil.rmtree(self.adapt_dir) response.append("Cleared adapt directory {}".format( self.adapt_dir)) shutil.copytree(self.model_dir, self.adapt_dir) map_adapt = '/usr/lib/sphinxtrain/map_adapt' if os.path.isfile('/usr/local/libexec/sphinxtrain/map_adapt'): map_adapt = '/usr/local/libexec/sphinxtrain/map_adapt' cmd = [ map_adapt, '-moddeffn', os.path.join(self.model_dir, 'mdef.txt'), '-ts2cbfn', '.ptm.', '-meanfn', os.path.join(self.model_dir, 'means'), '-varfn', os.path.join(self.model_dir, 'variances'), '-mixwfn', os.path.join(self.model_dir, 'mixture_weights'), '-tmatfn', os.path.join(self.model_dir, 'transition_matrices'), '-accumdir', self.working_dir, '-mapmeanfn', os.path.join(self.adapt_dir, 'means'), '-mapvarfn', os.path.join(self.adapt_dir, 'variances'), '-mapmixwfn', os.path.join(self.adapt_dir, 'mixture_weights'), '-maptmatfn', os.path.join(self.adapt_dir, 'transition_matrices') ] completedprocess = run_command(cmd) response.append( process_completedprocess(completedprocess, output='html')) if (completedprocess.returncode != 0): continue_next = False nextcommand = "sendump" if (command == "sendump"): # Recreating the adapted sendump file # a sendump file saves space and is supported by pocketsphinx mk_s2sendump = '/usr/lib/sphinxtrain/mk_s2sendump' if os.path.isfile( '/usr/local/libexec/sphinxtrain/mk_s2sendump'): mk_s2sendump = '/usr/local/libexec/sphinxtrain/mk_s2sendump' cmd = [ mk_s2sendump, '-pocketsphinx', 'yes', '-moddeffn', os.path.join(self.adapt_dir, 'mdef.txt'), '-mixwfn', os.path.join(self.adapt_dir, 'mixture_weights'), '-sendumpfn', os.path.join(self.adapt_dir, 'sendump') ] completedprocess = run_command(cmd) response.append( process_completedprocess(completedprocess, output='html')) if (completedprocess.returncode != 0): continue_next = False nextcommand = "updateprofile" if (command == "updateprofile"): # Format the dictionary # Remove whitespace at the beginning of each line # Remove (#) after first word # collapse multiple whitespaces into a single space # Remove any whitespaces from the end with open(os.path.join(self.adapt_dir, "cmudict.dict"), "r") as in_file: with open(self.formatteddict_path, "w+") as out_file: for line in in_file: # Remove whitespace at beginning and end line = line.strip() # remove the number in parentheses (if there is one) line = re.sub('([^\\(]+)\\(\\d+\\)', '\\1', line) # compress all multiple whitespaces into a single whitespace line = re.sub('\s+', ' ', line) # replace the first whitespace with a tab line = line.replace(' ', '\t', 1) print(line, file=out_file) # Use phonetisaurus to prepare an fst model cmd = [ "phonetisaurus-train", "--lexicon", self.formatteddict_path, "--seq2_del", "--dir_prefix", os.path.join(self.adapt_dir, "train") ] completedprocess = run_command(cmd) response.append( process_completedprocess(completedprocess, output='html')) if (completedprocess.returncode == 0): # Now set the values in profile profile.set_profile_var(['pocketsphinx', 'fst_model'], os.path.join( self.adapt_dir, "train", "model.fst")) profile.set_profile_var(['pocketsphinx', 'hmm_dir'], self.adapt_dir) profile.save_profile() # Also run through the list of words that have been used # that are not the wake word or a command word and make # sure they are all identified so pocketsphinx can match # them and not get confused on word boundaries. # Pull a list of all words spoken from # verified translations query = " ".join([ "with recursive split(", " word,", " rest", ") as (", " select", " ''," " upper(replace(replace(verified_transcription,'?',''),',','')) || ' '", " from audiolog", " where type in ('active','passive') and reviewed!=''", " union all select", " substr(rest, 0, instr(rest,' ')),", " substr(rest,instr(rest,' ')+1)", " from split where rest <> ''" ")", "select word from split where word!='' group by word" ]) c.execute(query) words_used = [x[0].upper() for x in c.fetchall()] # Pull the list of words from the local standard phrases keywords = profile.get_profile_var(['keyword']) if (isinstance(keywords, str)): keywords = [keywords] phrases = [keyword.upper() for keyword in keywords] custom_standard_phrases_dir = paths.sub( os.path.join("data", "standard_phrases")) custom_standard_phrases_file = os.path.join( custom_standard_phrases_dir, "{}.txt".format(self.language)) if (os.path.isfile(custom_standard_phrases_file)): with open(custom_standard_phrases_file, mode="r") as f: for line in f: phrase = line.strip().upper() if phrase: phrases.append(phrase) # Get all the phrases that the plugins are looking for ps = pluginstore.PluginStore() ps.detect_plugins("speechhandler") for info in ps.get_plugins_by_category("speechhandler"): try: plugin = info.plugin_class(info, profile.get_profile()) # get_phrases is vestigial now if (hasattr(plugin, "get_phrases")): for phrase in plugin.get_phrases(): phrases.extend([ word.upper() for word in phrase.split() ]) # get the phrases from the plugin intents if (hasattr(plugin, "intents")): intents = plugin.intents() for intent in intents: for template in intents[intent]['locale'][ self.language]['templates']: phrases.extend([ word.upper() for word in template.split() ]) except Exception as e: message = "Unknown" if hasattr(e, "message"): message = e.message response.append( "Plugin {} skipped! (Reason: {})".format( info.name, message)) self._logger.warning( "Plugin '{}' skipped! (Reason: {})".format( info.name, message), exc_info=True) # Get the set of all words in words_used that do not appear # in phrases print("Phrases:") print(phrases) new_phrases = [ word for word in words_used if word not in phrases ] response.append("{} new phrases detected".format( len(new_phrases))) description.append("adding {} new phrases".format( len(new_phrases))) if (len(new_phrases) > 0): table = "<table><tr><th>new phrase</th></tr>" # Append the new phrases to the custom # standard_phrases\{language}.txt file if (not os.path.isdir(custom_standard_phrases_dir)): os.makedirs(custom_standard_phrases_dir) with open(custom_standard_phrases_file, mode="a+") as f: for word in new_phrases: table += "<tr><td>{}</td></tr>".format(word) print(word, file=f) table += "</table>" response.append(table) # Finally, force naomi to regenerate all of the # pocketsphinx vocabularies by deleting all the # vocabularies/{language}/sphinx/{}/revision # files: for revision_file in glob.glob( paths.sub('vocabularies', self.language, 'sphinx', "*", "revision")): os.remove(revision_file) # Add the description c.execute('''insert into trainings values(?,?,?)''', (datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 'Adapt Pocketsphinx', " ".join(description))) conn.commit() else: continue_next = False except Exception as e: continue_next = False message = "Unknown" if hasattr(e, "message"): message = e.message self._logger.error("Error: {}".format(message), exc_info=True) response.append('<span class="failure">{}</span>'.format(message)) if not continue_next: nextcommand = "" return response, nextcommand, description
def settings(self): language = profile.get(['language']) # Get the defaults for settings # hmm_dir hmm_dir = profile.get( ['pocketsphinx', 'hmm_dir'] ) if(not hmm_dir): # Make a list of possible paths to check hmm_dir_paths = [ os.path.join( os.path.expanduser("~"), "pocketsphinx-python", "pocketsphinx", "model", "en-us", "en-us" ), os.path.join( os.path.expanduser("~"), "pocketsphinx", "model", "en-us", "en-us" ), os.path.join( "/", "usr", "share", "pocketsphinx", "model", "en-us", "en-us" ), os.path.join( "/usr", "local", "share", "pocketsphinx", "model", "hmm", "en_US", "hub4wsj_sc_8k" ) ] # see if any of these paths exist for path in hmm_dir_paths: if os.path.isdir(path): hmm_dir = path # fst_model fst_model = profile.get_profile_var(["pocketsphinx", "fst_model"]) if not fst_model: # Make a list of possible paths to check fst_model_paths = [ os.path.join( paths.sub( os.path.join( "pocketsphinx", "adapt", "en-US", "train", "model.fst" ) ) ), os.path.join( os.path.expanduser("~"), "pocketsphinx-python", "pocketsphinx", "model", "en-us", "train", "model.fst" ), os.path.join( os.path.expanduser("~"), "cmudict", "train", "model.fst" ), os.path.join( os.path.expanduser("~"), "CMUDict", "train", "model.fst" ), os.path.join( os.path.expanduser("~"), "phonetisaurus", "g014b2b.fst" ) ] for path in fst_model_paths: if os.path.isfile(path): fst_model = path # If either the hmm dir or fst model is missing, then # download the standard model if not(hmm_dir and os.path.isdir(hmm_dir) and fst_model and os.path.isfile(fst_model)): # Start by checking to see if we have a copy of the standard # model for this user's chosen language and download it if not. # Check for the files we need language = profile.get_profile_var(['language']) base_working_dir = paths.sub("pocketsphinx") if not os.path.isdir(base_working_dir): os.mkdir(base_working_dir) standard_dir = os.path.join(base_working_dir, "standard") if not os.path.isdir(standard_dir): os.mkdir(standard_dir) standard_dir = os.path.join(standard_dir, language) if not os.path.isdir(standard_dir): os.mkdir(standard_dir) hmm_dir = standard_dir fst_model = os.path.join(hmm_dir, "train", "model.fst") formatteddict_path = os.path.join( hmm_dir, "cmudict.formatted.dict" ) if(not check_pocketsphinx_model(hmm_dir)): # Check and see if we already have a copy of the standard # language model print("Downloading and installing the {} pocketsphinx language model".format(language)) cmd = [ 'git', 'clone', '-b', language, 'https://github.com/NaomiProject/CMUSphinx_standard_language_models.git', hmm_dir ] completedprocess = run_command(cmd) self._logger.info(process_completedprocess(completedprocess)) if(not os.path.isfile(formatteddict_path)): print("Formatting the g2p dictionary") with open(os.path.join(standard_dir, "cmudict.dict"), "r") as in_file: with open(formatteddict_path, "w+") as out_file: for line in in_file: # Remove whitespace at beginning and end line = line.strip() # remove the number in parentheses (if there is one) line = re.sub('([^\\(]+)\\(\\d+\\)', '\\1', line) # compress all multiple whitespaces into a single whitespace line = re.sub('\s+', ' ', line) # replace the first whitespace with a tab line = line.replace(' ', '\t', 1) print(line, file=out_file) if(not os.path.isfile(fst_model)): # Use phonetisaurus to prepare an fst model print("Training an FST model") cmd = [ "phonetisaurus-train", "--lexicon", formatteddict_path, "--seq2_del", "--dir_prefix", os.path.join(hmm_dir, "train") ] completedprocess = run_command(cmd) self._logger.info(process_completedprocess(completedprocess)) phonetisaurus_executable = profile.get_profile_var( ['pocketsphinx', 'phonetisaurus_executable'] ) if(not phonetisaurus_executable): if(check_program_exists('phonetisaurus-g2pfst')): phonetisaurus_executable = 'phonetisaurus-g2pfst' else: phonetisaurus_executable = 'phonetisaurus-g2p' _ = self.gettext return OrderedDict( [ ( ('pocketsphinx', 'hmm_dir'), { 'title': _('PocketSphinx hmm file'), 'description': "".join([ _('PocketSphinx hidden markov model directory') ]), 'default': hmm_dir } ), ( ('pocketsphinx', 'fst_model'), { 'title': _('PocketSphinx FST file'), 'description': "".join([ _('PocketSphinx finite state transducer file') ]), 'default': fst_model } ), ( ('pocketsphinx', 'phonetisaurus_executable'), { 'title': _('Phonetisaurus executable'), 'description': "".join([ _('Phonetisaurus is used to build custom dictionaries') ]), 'default': phonetisaurus_executable } ), ] )