Objectif
Un court article pour montrer comment trainer Deepspeech un peu plus rapidement.
Nous allons utiliser un script qui va lire un fichier qui contient toutes nos phrases (sentences2.txt)
Le script va automatiquement créer les fichiers vocabulary.txt & voices.csv
Côté serveur, on va utiliser un autre script qui va se connecter à notre client (Raspberry pi) et il va aller chercher tous les fichiers dont il a besoin pour lancer un training.
NOTE
Après avoir copié les scripts, veuillez transformer les tabs en espaces.
Matériel Nécessaire
- J'utilise le serveur précédemment créé Tensorflow & Deepspeech
- Un raspberry pi 3 avec Stretch
- Un micro array Matrix Voice
Partie 1 : Configurer le Serveur
Le script
#!/usr/bin/env python # -*- coding: utf-8 -*- # Auteur : Tommy Gingras # Date : 2018-02-21 import paramiko import scp import os from paramiko import SSHClient from scp import SCPClient ## VARIABLES DEFINITONS ## server='1.1.1.1' port='22' user='pi' password='PAssWORD' ## FUNCTIONS DEFINITIONS def clear(): os.system('clear') def progress(filename, size, sent): clear() print filename + " " + str(size) def createSSHClient(server, port, user, password): client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(server, port, user, password) return client def clean_vocabulary(filename): os.system("sed -i -e 's/\xc2\xa0/ /' "+filename) os.system("sed -i -e '/^$/d' "+filename) ## 'MAIN' ## ssh = createSSHClient(server, port, user, password) # Sanitize to authorize widlcard scp = SCPClient(ssh.get_transport(), sanitize=lambda x: x, progress=progress) scp.get('/home/pi/john/vocabulary.txt', '/home/tgingras/vocal/data/new/') scp.get('/home/pi/john/voice.csv', '/home/tgingras/vocal/data/new/') scp.get("/home/pi/john/voices/valid/*", '/home/tgingras/vocal/data/audio/', recursive=True) # Already existant vocabulary file open read file vocabulary_file=open('/home/tgingras/vocal/data/vocabulary.txt','r+') _vocabulary = vocabulary_file.readlines() # File to append vocabulary new_vocabulary = open('/home/tgingras/vocal/data/new/vocabulary.txt', 'r+') _new_vocabulary = new_vocabulary.readlines() append_array = [] # create the append list (vocabulary) for line in _new_vocabulary: if line in _vocabulary: print('line already present') else: append_array.append(line.decode('string_escape')) # check voice file new_voice_file = open('/home/tgingras/vocal/data/new/voice.csv', 'r+') voice = open('/home/tgingras/vocal/data/voice.csv','a') new_voice = new_voice_file.readlines() voice_file=open('/home/tgingras/vocal/data/voice.csv','r+') _voice=voice_file.readlines() append_voice=[] # create the append list (voice) for line in new_voice: if line in _voice: print('voice already present') else: append_voice.append(line.decode('string_escape')) _vocabulary = vocabulary_file.readlines() # open existant vocabulary file in append mode vocabulary = open('/home/tgingras/vocal/data/vocabulary.txt','a') # for each element in the array, append it for item in append_array: vocabulary.write("%s" % item) vocabulary.close() for item in append_voice: voice.write("%s" % item) voice.close() clean_vocabulary('/home/tgingras/vocal/data/vocabulary.txt') os.system("sed -i -e 's/\xc2\xa0/ /' /home/tgingras/vocal/data/voice.csv") os.system("sed -i -e '/^$/d' /home/tgingras/vocal/data/voice.csv") os.system("/home/tgingras/vocal/kenlm/build/bin/./lmplz --text /home/tgingras/vocal/data/vocabulary.txt --arpa /home/tgingras/vocal/data/words.arpa --o 5") os.system("/home/tgingras/vocal/kenlm/build/bin/./build_binary -T -s /home/tgingras/vocal/data/words.arpa /home/tgingras/vocal/data/lm.binary") os.system("/home/tgingras/vocal/tfv1/tensorflow/bazel-bin/native_client/generate_trie /home/tgingras/vocal/data/alphabet.txt /home/tgingras/vocal/data/lm.binary /home/tgingras/vocal/data/vocabulary.txt /home/tgingras/vocal/data/trie") print("From there we can launch the training script")
Explication du script
Pour le moment tout est 'Hard codé'. N'oubliez pas de modifier chaque chemin pour refléter votre setup.
Sinon le script se connecte au Raspberry Pi et va chercher les fichiers audios puis les fichiers voices.csv et vocabulary.txt. ensuite il recrée les fichiers : lm.binary, trie et words.arpa
Pour lancer le script, il faut seulement l'enregistrer : auto_prepare.py et lancer python auto_prepare.py
Partie 2 : Configurer le Client
Le Script
#!/usr/bin/env python # -*- coding: utf-8 -*- import os import pyaudio import wave import subprocess import time last_entry = 0 start_point = 0 location = '' validLocation = '' trainingPath = '' def clear(): os.system('clear') def get_prefix(): filename = raw_input("\n >> Please enter the file prefix( e.g. 'tom-18-02-17-near-' ) ?? : ") return filename def set_sentences_file(): user_link = raw_input("\n >> Please enter the text sentences path (Default : /home/pi/john/sentences2.txt) [ENTER] to select default : ") if user_link == '': return '/home/pi/john/sentences2.txt' else: return user_link def load_sentences(): text_link = set_sentences_file() text = open(text_link) return text.readlines() def print_header(sentences_file): clear() print('Sentences to read : '+str(len(sentences_file))+' lines') raw_input('\n\nPress [ENTER] to continue') def preparation_question(): global last_entry global start_point user_last_entry = raw_input("\n\n >> Which is the last entry recorded ? (If no record = 0, Otherwise check the Excel): [0]") if user_last_entry == '': last_entry=0 else: last_entry = int(user_last_entry) user_start_point = raw_input("\n\n >> Which line from the sentences file you want to read ? (0 = First one): [0]") if user_start_point == '': start_point=0 else: start_point = int(user_start_point) def folders_structure(prefix): global location global validLocation global trainingPath location = raw_input("\n >> Where to save the temporary record ?? : [/home/pi/john/voices/]") if location == '': location = '/home/pi/john/voices/'+prefix validLocation = raw_input("\n >> Where to save the validated record ?? : [/home/pi/john/voices/valid/]") if validLocation == '': validLocation = '/home/pi/john/voices/valid/' trainingPath = raw_input("\n >> Where is the training path (Deepspeech server) ?? : ['/home/tgingras/vocal/data/audio/']") if trainingPath == '': trainingPath = '/home/tgingras/vocal/data/audio/' def read(sentences_file, data): index = data print('▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒') print(' Read this sentence : '+str(sentences_file[index]))+' Index: '+str(index+1) print('▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒') return def record(data): index = data print('▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒') print(' WAIT BEFORE READING') print('▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒') os.system('killall -9 arecord') time.sleep(1) print('▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒') print(' LISTENING ...') print('▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒') os.system('arecord --fatal-error -r 16000 -c 1 -f S16_LE --device=mic_channel8 -t wav '+index+'.wav') print('\n saved to : '+str(index)+'.wav') return def recording_process(sentences_file, last_entry, start_point, prefix, location, validLocation, trainingPath): a=(len(sentences_file)) for value in range(last_entry, (a)): read(sentences_file, (value-last_entry)+start_point) record(location+str(value+1)) while True: keyboard = raw_input('Keep : [ENTER]\nRetry : [r] \nKeep And Exit : [k] \nPlay : [p] \n ') if keyboard == '' or keyboard == 'k': # KEEP clear() print('Processing ...') # Process to save the sample. vocalCSV = open('voice.csv', 'a') doneSentences = open(prefix+'_sentences.csv', 'a') doneSentences.write(str(sentences_file[(value-last_entry)+start_point])) doneSentences.close() name=prefix+str(value+1)+'.wav' newFile=location+str(value+1)+'.wav' newFile_p=validLocation+prefix+str(value+1)+'.wav' # SILENCE is optional, maube it will cause bugs os.system('sox -c 1 -r 16k -t wav ' + newFile + ' '+ newFile_p + ' silence -l 1 0.1 1% -1 2.0 1%') print('Processing ....') os.system('rm ' + newFile) filesize=subprocess.check_output("ls -l "+newFile_p+" | awk '{print $5}'", shell=True).strip() vocalCSV.write(trainingPath+name+','+str(filesize)+','+str(sentences_file[(value-last_entry)+start_point])) vocalCSV.close() vocabularyCSV=open('vocabulary.txt','a') vocabularyCSV.write(str(sentences_file[(value-last_entry)+start_point])) vocabularyCSV.close() print('OK.') if keyboard == 'k': #print("Last entry : " + str(last_entry) + " & Line from the sentence file : " + str(start_point)) print('Bye Bye') return 'Bye Bye !' break if keyboard == 'r': print(' Try Again\n') read(sentences_file, (value-last_entry)+start_point) record(location+str(value+1)) clear() if keyboard == 'p': print('Plug a speaker !') os.system('aplay ' + location+str(value+1)+'.wav') else: print('\nplease be Careful.') clear() if __name__ == "__main__": clear() # Get the prefic for final files. prefix = get_prefix() # Load the sentences that needs to be read. sentences_file = load_sentences() print_header(sentences_file) preparation_question() folders_structure(prefix) print(location) print(validLocation) print(trainingPath) start = recording_process(sentences_file, last_entry, start_point, prefix, location, validLocation, trainingPath)
Explication du script
Vous devez fournir un fichier qui contient toutes les phrases à lire. (sentences2.txt)
Répondre aux question selon ce que vous voulez faire.
Précision sur la question du 'training path' : lorsque le serveur va effectuer le training, il se sert du fichier voice.csv pour faire l'association des fichiers et de leur contenu. Alors il est important de mettre le chemin complet où le serveur va stocker les données.
Pour l'exécuter : nano record.py & python record.py
Partie 3 : Utilisation du script Client
remplir toutes les questions. puis suivre les instructions à l'écran.
Pour arrêter l'enregistrement, (Après avoir lu la phrase.) Appuyer sur CTRL+C
[p] Vous pouvez écouter votre échantillon avant de la sauvegarder.
[enter] permet de sauvegarder et de passer à la prochaine phrase.
[k] permet de sauvegarder et de quitter.
[r] permet de recommencer l'enregistrement.
NOTE
Après avoir enregistrer plus d'un heure, j'ai remarquer que certain enregistrement était trop bruyant ou qui manquait des mots. Alors il est très important, pour obtenir un résultat optimal d'écouter et de valider manuellement chaque enregistrement et de mettre à jour les fichiers voice.csv et vocabulary.txt en conséquence.
Partie 4 : Utilisation du script Serveur
Lorsque la session d'enregistrement est terminé sur le client, vous pouvez lancer le script. Il ira automatiquement chercher tous les fichiers nécessaires. ensuite vous pouvez manuellement partir le training.