Récemment, je suis entré dans Ameft (NFL). Cependant, je ne comprends pas l'anglais. .. .. Même si vous ne comprenez pas la voix, pouvez-vous la déchiffrer d'une manière ou d'une autre en l'écrivant? En réfléchissant, j'ai lancé le défi de créer un texte vocal d'interviews de joueurs avec Raspberry Pi 3 × Julius × Watson (Speech to Text)
L'image ressemble à ceci Getting robots to listen: Using Watson’s Speech to Text service
Ce qui suit est supposé être prêt. Pour référence, indiquez le lien du site auquel j'ai fait référence
Julius semble avoir un fichier de lecture et un fichier de grammaire pour accélérer l'authentification. Après avoir essayé les deux, j'ai décidé d'utiliser le fichier de grammaire cette fois.
Veuillez consulter Raspberry Pi 3 x Julius (fichier de lecture et fichier de grammaire) pour les résultats de la vérification.
Lorsque Julius est démarré en mode module (*), l'audio est renvoyé en XML. Si vous dites «Démarrer Watson», vous obtiendrez le code XML suivant.
<RECOGOUT>
<SHYPO RANK="1" SCORE="-2903.453613" GRAM="0">
<WHYPO WORD="Watson" CLASSID="Watson" PHONE="silB w a t o s o N silE" CM="0.791"/>
</SHYPO>
</RECOGOUT>
<RECOGOUT>
<SHYPO RANK="1" SCORE="-8478.763672" GRAM="0">
<WHYPO WORD="Watson a commencé" CLASSID="Watson a commencé" PHONE="silB w a t o s o N k a i sh i silE" CM="1.000"/>
</SHYPO>
</RECOGOUT>
Par conséquent, pour le mot parlé, analysez le XML et décrivez le processus à exécuter. (Ce n'est pas bon, mais c'est solide ...)
#Juger et traiter la voix
def decision_word(xml_list):
watson = False
for key, value in xml_list.items():
if u"Tarte Razz" == key:
print u"Oui. Qu'Est-ce que c'est?"
if u"Watson" == key:
print u"Bien reçu. préparer."
watson = True
return watson
Modifié pour démarrer le serveur Julius dans le sous-processus
#Démarrer le serveur Julius
def invoke_julius():
logging.debug("invoke_julius")
# -Interdire la sortie du journal avec l'option nolog
reccmd = ["/usr/local/bin/julius", "-C", "./julius-kits/grammar-kit-v4.1/hmm_mono.jconf", "-input", "mic", "-gram", "julius_watson","-nolog"]
p = subprocess.Popen(reccmd, stdin=None, stdout=None, stderr=None)
time.sleep(3.0)
return p
#Serveur Julius
JULIUS_HOST = "localhost"
JULIUS_PORT = 10500
#Connectez-vous avec Julius
def create_socket():
logging.debug("create_socket")
# TCP/Connectez-vous à Julius avec IP
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((JULIUS_HOST, JULIUS_PORT))
sock_file = sock.makefile()
return sock
Comme mentionné ci-dessus, XML est renvoyé par Julius, alors récupérez les balises , une erreur se produira lors de l'analyse XML, donc un traitement autre que </ s> est inclus.
#Extraire la balise spécifiée des données obtenues de julius
def extract_xml(tag_name, xml_in, xml_buff, line):
xml = False
final = False
if line.startswith("<RECOGOUT>"):
xml = True
xml_buff = line
elif line.startswith("</RECOGOUT>"):
xml_buff += line
final = True
else:
if xml_in:
xml_buff += escape(line)
xml = True
return xml,xml_buff,final
# <s>Balises supprimées (correspondant car une erreur s'est produite lors de l'analyse XML)
def escape(line):
str = line.replace("<s>",'')
str = str.replace('</s>','')
return str
#Analyser le XML des résultats de l'analyse Julius
def parse_recogout(xml_data):
#Obtenez le mot du résultat de la reconnaissance
#Enregistrer les résultats dans le dictionnaire
word_list = []
score_list = []
xml_list = {}
for i in xml_data.findall(".//WHYPO"):
word = i.get("WORD")
score = i.get("CM")
if ("[s]" in word) == False:
word_list.append(word)
score_list.append(score)
xml_list = dict(izip(word_list, score_list))
return xml_list
C'est un peu long, mais le tout de 1.1 à 1.3 ressemble à ceci.
#Extraire la balise spécifiée des données obtenues de julius
def extract_xml(tag_name, xml_in, xml_buff, line):
xml = False
final = False
if line.startswith("<RECOGOUT>"):
xml = True
xml_buff = line
elif line.startswith("</RECOGOUT>"):
xml_buff += line
final = True
else:
if xml_in:
xml_buff += escape(line)
xml = True
return xml,xml_buff,final
# <s>Balises supprimées (correspondant car une erreur s'est produite lors de l'analyse XML)
def escape(line):
str = line.replace("<s>",'')
str = str.replace('</s>','')
return str
#Analyser le XML des résultats de l'analyse Julius
def parse_recogout(xml_data):
#Obtenez le mot du résultat de la reconnaissance
#Enregistrer les résultats dans le dictionnaire
word_list = []
score_list = []
xml_list = {}
for i in xml_data.findall(".//WHYPO"):
word = i.get("WORD")
score = i.get("CM")
if ("[s]" in word) == False:
word_list.append(word)
score_list.append(score)
xml_list = dict(izip(word_list, score_list))
return xml_list
#Juger et traiter la voix
def decision_word(xml_list):
watson = False
for key, value in xml_list.items():
if u"Tarte Razz" == key:
print u"Oui. Qu'Est-ce que c'est?"
if u"Watson" == key:
print u"Bien reçu. préparer."
watson = True
return watson
#Serveur Julius
JULIUS_HOST = "localhost"
JULIUS_PORT = 10500
#Démarrer le serveur Julius
def invoke_julius():
logging.debug("invoke_julius")
# -Interdire la journalisation avec l'option nolog
#Bientôt,-Exportez le journal dans un fichier avec l'option logfile, etc.
reccmd = ["/usr/local/bin/julius", "-C", "./julius-kits/grammar-kit-v4.1/hmm_mono.jconf", "-input", "mic", "-gram", "julius_watson","-nolog"]
p = subprocess.Popen(reccmd, stdin=None, stdout=None, stderr=None)
time.sleep(3.0)
return p
#déconnecter le serveur julius
def kill_process(julius):
logging.debug("kill_process")
julius.kill()
time.sleep(3.0)
#Connectez-vous avec Julius
def create_socket():
logging.debug("create_socket")
# TCP/Connectez-vous à Julius avec IP
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((JULIUS_HOST, JULIUS_PORT))
sock_file = sock.makefile()
return sock
#Connexion étroite avec Julius
def close_socket(sock):
logging.debug("close_socket")
sock.close()
#Traitement principal
def main():
#Démarrer le serveur Julius
julius = invoke_julius()
#Connectez-vous à Julius
sock = create_socket()
julius_listening = True
bufsize = 4096
xml_buff = ""
xml_in = False
xml_final = False
watson = False
while julius_listening:
#Obtenez les résultats d'analyse de Julius
data = cStringIO.StringIO(sock.recv(bufsize))
#Obtenez une ligne du résultat de l'analyse
line = data.readline()
while line:
#Seule la ligne affichant le résultat de l'analyse de la voix est extraite et traitée.
#Extraire et traiter uniquement la balise RECOGOUT.
xml_in, xml_buff, xml_final = extract_xml('RECOGOUT', xml_in, xml_buff, line)
if xml_final:
#Analyser mxl
logging.debug(xml_buff)
xml_data = fromstring(xml_buff)
watson = decision_word( parse_recogout(xml_data))
xml_final = False
#Si le résultat est "Watson", accédez à l'authentification vocale
if watson:
julius_listening = False #Julius a terminé
break
#Obtenez une ligne du résultat de l'analyse
line = data.readline()
#Fermer la prise
close_socket(sock)
#Déconnecter julius
kill_process(julius)← L'authentification vocale de watson "Speech to text" enregistre en utilisant un enregistrement, donc Julius se déconnecte (parce que le microphone entre en collision, ...)
if watson:
speechToText()← Si on vous dit "Watson", exécutez les processus ③ et ④
def initial_setting():
#Paramètres du journal
logging.basicConfig(filename='websocket_julius2.log', filemode='w', level=logging.DEBUG)
logging.debug("initial_setting")
if __name__ == "__main__":
try:
#Processus d'initialisation
initial_setting()
#Traitement principal
main()
except Exception as e:
print "error occurred", e, traceback.format_exc()
finally:
print "websocket_julius2...end"
Démarrez le processus d'enregistrement vocal (exécutez la commande arecord) en multi-thread. Envoyez des données binaires à watson chaque fois que vous enregistrez afin de pouvoir convertir l'audio en texte en temps réel. (*. L'échange de données vers watson sera décrit plus tard)
def opened(self):
self.stream_audio_thread = threading.Thread(target=self.stream_audio)
self.stream_audio_thread.start()
#Démarrer le processus d'enregistrement
def stream_audio(self):
# -Masquer le message avec l'option q
reccmd = ["arecord", "-f", "S16_LE", "-r", "16000", "-t", "raw", "-q"]
p = subprocess.Popen(reccmd,stdout=subprocess.PIPE)
print 'Prêt. Veuillez exprimer'
while self.listening:
data = p.stdout.read(1024)
try:
self.send(bytearray(data), binary=True)← Passer des données binaires à watson
except ssl.SSLError: pass
Utilisez la version webSocket de Speech to Text pour convertir l'audio en texte en temps réel. Pour la parole en texte, veuillez également vous référer à J'ai essayé l'authentification vocale Watson (parole à texte).
Implémenté en référence à cette source d'exemple Getting robots to listen: Using Watson’s Speech to Text service
Connectez-vous à watson à l'aide de la bibliothèque pour watson (watson-developer-cloud-0.23.0)
class SpeechToTextClient(WebSocketClient):
def __init__(self):
ws_url = "wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize"
username = "XXXXXXX"
password = "XXXXXXX"
auth_string = "%s:%s" % (username, password)
base64string = base64.encodestring(auth_string).replace("\n", "")
self.listening = False
try:
WebSocketClient.__init__(self, ws_url,headers=[("Authorization", "Basic %s" % base64string)])
self.connect()
except: print "Failed to open WebSocket."
# websocket(Lien)
def opened(self):
self.send('{"action":"start","content-type": "audio/l16;rate=16000","continuous":true,"inactivity_timeout":10,"interim_results":true}')
Le résultat de l'exécution (données vocales) de la commande arecord exécutée dans le multi-thread décrit ci-dessus est envoyé à watson. C'est un peu long, mais ... 2. Enregistrement vocal-3. Quand j'ai mis en place la connexion de Raspberry Pi 3 à watson (Speech to Text), cela ressemble à ceci.
class SpeechToTextClient(WebSocketClient):
def __init__(self):
ws_url = "wss://stream.watsonplatform.net/speech-to-text/api/v1/recognize"
username = "XXXXXXX"
password = "XXXXXXX"
auth_string = "%s:%s" % (username, password)
base64string = base64.encodestring(auth_string).replace("\n", "")
self.listening = False
try:
WebSocketClient.__init__(self, ws_url,headers=[("Authorization", "Basic %s" % base64string)])
self.connect()
except: print "Failed to open WebSocket."
# websocket(Lien)
def opened(self):
self.send('{"action":"start","content-type": "audio/l16;rate=16000","continuous":true,"inactivity_timeout":10,"interim_results":true}')
self.stream_audio_thread = threading.Thread(target=self.stream_audio)
self.stream_audio_thread.start()
#Démarrer le processus d'enregistrement
def stream_audio(self):
while not self.listening:
time.sleep(0.1)
# -Masquer le message avec l'option q
reccmd = ["arecord", "-f", "S16_LE", "-r", "16000", "-t", "raw", "-q"]
p = subprocess.Popen(reccmd,stdout=subprocess.PIPE)
print 'Prêt. Veuillez exprimer'
while self.listening:
data = p.stdout.read(1024)
try:
self.send(bytearray(data), binary=True)
except ssl.SSLError: pass
Lors de la connexion avec webSocket, il semble que le résultat de l'analyse de watson puisse être reçu dans l'événement receive_message.
# websockt(Recevoir un message)
def received_message(self, message):
print message
Le résultat de l'analyse semble être renvoyé sous la forme d'un objet json.
Comme ça, j'ai pu convertir la voix en texte en temps réel.
PostScript 2017/4/16 J'ai fait une vidéo comme celle-ci. https://youtu.be/IvWaHISF6nY
Impression que la voix ne peut pas être bien authentifiée lorsque vous parlez à plusieurs personnes ou lorsqu'il y a de la musique. Pourtant, je pensais que c'était tout simplement incroyable que la voix devienne un texte en temps réel. Je veux jouer de plus en plus avec l'authentification vocale.
Recommended Posts