[PYTHON] Sprachauthentifizierung und Transkription mit Raspberry Pi 3 x Julius x Watson (Rede zu Text)

Geschichte

Kürzlich bin ich zu Ameft (NFL) gekommen. Ich kann jedoch kein Englisch verstehen. .. .. Selbst wenn Sie die Stimme nicht verstehen, können Sie sie irgendwie entziffern, indem Sie sie schreiben? Als ich nachdachte, forderte ich mich heraus, einen Sprachtext von Spielerinterviews mit Raspberry Pi 3 × Julius × Watson (Speech to Text) zu erstellen.

Was du machen willst

img20170324_14192489.jpg

Das Bild sieht so aus Getting robots to listen: Using Watson’s Speech to Text service

Umgebung

Annahme

Es wird davon ausgegangen, dass Folgendes bereit ist. Listen Sie als Referenz den Link der Site auf, auf die ich verwiesen habe

Verfahren

  1. Sprechen Sie mit Julius mit Raspberry Pi 3 (Bilder ①②)
  2. Sprachaufnahme (Bild ③)
  3. Stellen Sie eine Verbindung zwischen Raspberry Pi3 und Watson her (Speech to Text) (Bild ④).
  4. Text Ihres Tube-Player-Interviews mit Raspberry Pi 3 x Watson (Bild ⑤)

■ Sprechen Sie mit Julius mit Raspberry Pi 3

Julius scheint eine Lesedatei und eine Grammatikdatei zu haben, um die Authentifizierung zu beschleunigen. Nachdem ich beide ausprobiert hatte, entschied ich mich, diesmal die Grammatikdatei zu verwenden.

Die Überprüfungsergebnisse finden Sie unter Raspberry Pi 3 x Julius (Lese- und Grammatikdatei).

1.1 Überblick über die Sprachanalyseverarbeitung

Wenn Julius im Modulmodus gestartet wird (*), wird das Audio in XML zurückgegeben. Wenn Sie "Watson starten" sagen, erhalten Sie das folgende XML.

<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 fing an" CLASSID="Watson fing an" PHONE="silB w a t o s o N k a i sh i silE" CM="1.000"/>
  </SHYPO>
</RECOGOUT>

Analysieren Sie daher für das gesprochene Wort das XML und beschreiben Sie den auszuführenden Prozess. (Es ist nicht gut, aber es ist solide ...)

#Stimme beurteilen und verarbeiten
def decision_word(xml_list):
    watson = False
    for key, value in xml_list.items():
        if u"Razz Pie" == key:
            print u"Ja. Was ist es?"
        if u"Watson" == key:
            print u"Verstanden. bereiten."
            watson = True
    return watson

1.2 Starten Sie den Julius-Server und stellen Sie von der Clientseite aus eine Verbindung zum Julius-Server her

Geändert, um den Julius-Server im Unterprozess zu starten

#Starten Sie den Julius Server
def invoke_julius():
    logging.debug("invoke_julius")
    # -Verbieten Sie die Protokollausgabe mit der 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

#Julius Server
JULIUS_HOST = "localhost"
JULIUS_PORT = 10500

#Verbinde dich mit Julius
def create_socket():
    logging.debug("create_socket")
    # TCP/Verbinde dich mit Julius mit IP
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((JULIUS_HOST, JULIUS_PORT))
    sock_file = sock.makefile()

    return sock

1.3 Sprachanalyse (XML-Analyse)

Wie oben erwähnt, wird XML von Julius zurückgegeben. Holen Sie sich also die Tags to </ RECOGOUT> und analysieren Sie sie. *. Wenn ein -Tag vorhanden ist, tritt beim XML-Parsing ein Fehler auf, sodass eine andere Verarbeitung als </ s> enthalten ist.

#Extrahieren Sie das angegebene Tag aus den Daten von 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>Tags entfernt (entsprechend, weil beim XML-Parsing ein Fehler aufgetreten ist)
def escape(line):
    str = line.replace("<s>",'')
    str = str.replace('</s>','')
    return str
    
#Analysieren Sie das XML der Julius-Analyseergebnisse
def parse_recogout(xml_data):

    #Holen Sie sich das Wort des Erkennungsergebnisses
    #Ergebnisse im Wörterbuch speichern
    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

1.4 Insgesamt

Es ist ein bisschen lang, aber das Ganze von 1.1 bis 1.3 sieht so aus.

#Extrahieren Sie das angegebene Tag aus den Daten von 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>Tags entfernt (entsprechend, weil beim XML-Parsing ein Fehler aufgetreten ist)
def escape(line):
    str = line.replace("<s>",'')
    str = str.replace('</s>','')

    return str
    
#Analysieren Sie das XML der Julius-Analyseergebnisse
def parse_recogout(xml_data):

    #Holen Sie sich das Wort des Erkennungsergebnisses
    #Ergebnisse im Wörterbuch speichern
    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

#Stimme beurteilen und verarbeiten
def decision_word(xml_list):
    watson = False
    for key, value in xml_list.items():
        if u"Razz Pie" == key:
            print u"Ja. Was ist es?"
        if u"Watson" == key:
            print u"Verstanden. bereiten."
            watson = True
    return watson

#Julius Server
JULIUS_HOST = "localhost"
JULIUS_PORT = 10500

#Starten Sie den Julius Server
def invoke_julius():
    logging.debug("invoke_julius")
    # -Verbieten Sie die Protokollierung mit der Option nolog
    #Demnächst,-Geben Sie das Protokoll in eine Datei mit der Option logfile usw. aus.
    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

#Julius Server trennen
def kill_process(julius):
    logging.debug("kill_process")
    julius.kill()
    time.sleep(3.0)

#Verbinde dich mit Julius
def create_socket():
    logging.debug("create_socket")
    # TCP/Verbinde dich mit Julius mit IP
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((JULIUS_HOST, JULIUS_PORT))
    sock_file = sock.makefile()

    return sock

#Enge Verbindung mit Julius
def close_socket(sock):
    logging.debug("close_socket")
    sock.close()

#Hauptverarbeitung
def main():
    #Starten Sie den Julius Server
    julius = invoke_julius()
    #Verbinde dich mit Julius
    sock = create_socket()

    julius_listening = True
    bufsize = 4096

    xml_buff = ""
    xml_in = False
    xml_final = False
    watson = False

    while julius_listening:            
        #Holen Sie sich Analyseergebnisse von Julius
        data = cStringIO.StringIO(sock.recv(bufsize))
        #Holen Sie sich eine Zeile aus dem Analyseergebnis
        line = data.readline()
        while line:
            #Nur die Zeile mit dem Analyseergebnis der Stimme wird extrahiert und verarbeitet.
            #Extrahieren und verarbeiten Sie nur das RECOGOUT-Tag.
            xml_in, xml_buff, xml_final = extract_xml('RECOGOUT', xml_in, xml_buff, line)
            if xml_final:
                #Mxl analysieren
                logging.debug(xml_buff)
                xml_data = fromstring(xml_buff)
                watson = decision_word( parse_recogout(xml_data))
                xml_final = False
                #Wenn das Ergebnis "Watson" ist, wechseln Sie zur Sprachauthentifizierung
                if watson:
                    julius_listening = False #Julius war fertig
                    break
            #Holen Sie sich eine Zeile aus dem Analyseergebnis
            line = data.readline()

    #Steckdose schließen
    close_socket(sock)
    #Julius trennen
    kill_process(julius)← Watsons Sprachauthentifizierung "Speech to Text" zeichnet mit Arecord auf, sodass Julius die Verbindung trennt (weil das Mikrofongerät kollidiert, ...)
    if watson:
        speechToText()← Wenn Ihnen "Watson" mitgeteilt wird, führen Sie die Prozesse ③ und ④ aus

def initial_setting():
    #Protokolleinstellungen
    logging.basicConfig(filename='websocket_julius2.log', filemode='w', level=logging.DEBUG)
    logging.debug("initial_setting")
if __name__ == "__main__":
    try:
        #Initialisierungsprozess
        initial_setting()
        #Hauptverarbeitung
        main()

    except Exception as e:
        print "error occurred", e, traceback.format_exc()
    finally:
        print "websocket_julius2...end"

■ Sprachaufnahme

Starten Sie den Sprachaufzeichnungsprozess (führen Sie den Befehl arecord aus) im Multithread. Senden Sie bei jeder Aufnahme Binärdaten an Watson, damit Sie das Audio in Echtzeit in Text umwandeln können. (* .Datenaustausch mit Watson wird später beschrieben)

def opened(self):
    self.stream_audio_thread = threading.Thread(target=self.stream_audio)
    self.stream_audio_thread.start() 

#Starten Sie den Aufnahmevorgang
def stream_audio(self):
    # -Nachricht mit q-Option ausblenden
    reccmd = ["arecord", "-f", "S16_LE", "-r", "16000", "-t", "raw", "-q"]
    p = subprocess.Popen(reccmd,stdout=subprocess.PIPE)
    print 'Bereit. Bitte Stimme'
    while self.listening:
        data = p.stdout.read(1024)
        try: 
            self.send(bytearray(data), binary=True)← Binärdaten an Watson übergeben
        except ssl.SSLError: pass

■ Stellen Sie eine Verbindung zwischen Raspberry Pi3 und Watson her (Speech to Text).

Verwenden Sie die webSocket-Version von Speech to Text, um Audio in Echtzeit in Text umzuwandeln. Informationen zum Sprechen in Text finden Sie auch unter Ich habe die Watson-Sprachauthentifizierung (Sprechen in Text) ausprobiert.

Implementiert mit Bezug auf diese Beispielquelle Getting robots to listen: Using Watson’s Speech to Text service

3.1 Verbindung zu Watson herstellen (Speech to Text)

Stellen Sie über die Bibliothek für Watson (Watson-Developer-Cloud-0.23.0) eine Verbindung zu Watson her.

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."

3.2 Stellen Sie mit webSocket eine Verbindung zu Watson her.

    # websocket(Verbindung)
    def opened(self):
        self.send('{"action":"start","content-type": "audio/l16;rate=16000","continuous":true,"inactivity_timeout":10,"interim_results":true}')

3.3 Watson-Sprachauthentifizierung

Das Ausführungsergebnis (Sprachdaten) des in dem oben beschriebenen Multithread ausgeführten Arecord-Befehls wird an Watson gesendet. Es ist ein bisschen lang, aber ... 2. Sprachaufnahme-3. Wenn ich die Verbindung von Raspberry Pi 3 zu Watson (Speech to Text) zusammenstelle, sieht es so aus.

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(Verbindung)
    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() 
        
    #Starten Sie den Aufnahmevorgang
    def stream_audio(self):
        while not self.listening:
            time.sleep(0.1)

        # -Nachricht mit q-Option ausblenden
        reccmd = ["arecord", "-f", "S16_LE", "-r", "16000", "-t", "raw", "-q"]
        p = subprocess.Popen(reccmd,stdout=subprocess.PIPE)
        print 'Bereit. Bitte Stimme'
        while self.listening:
            data = p.stdout.read(1024)
            try: 
                self.send(bytearray(data), binary=True)
            except ssl.SSLError: pass

■ Text Ihres Tube-Player-Interviews mit Raspberry Pi 3 x Watson

4.1 Implementierung von receive_message

Bei der Verbindung mit webSocket scheint das Analyseergebnis von Watson im Ereignis receive_message empfangen zu werden.

    # websockt(Erhalte Nachricht)
    def received_message(self, message):
        print message 

4.2 Ergebnisse der Watson-Analyse

Das Analyseergebnis scheint als JSON-Objekt zurückgegeben zu werden.

Auf diese Weise konnte ich die Stimme in Echtzeit in Text umwandeln.

キャプチャ.PNG

2017/4/16 Nachtrag Ich habe so ein Video gemacht. https://youtu.be/IvWaHISF6nY

Schließlich

Eindruck, dass die Stimme nicht gut authentifiziert werden kann, wenn mit mehreren Personen gesprochen wird oder wenn Musik vorhanden ist. Trotzdem fand ich es einfach erstaunlich, dass die Stimme in Echtzeit zu Text wurde. Ich möchte immer mehr mit Sprachauthentifizierung spielen.

Recommended Posts

Sprachauthentifizierung und Transkription mit Raspberry Pi 3 x Julius x Watson (Rede zu Text)
Ich habe Watson Voice Authentication (Speech to Text) ausprobiert.
Melden Sie sich mit ssh ohne Passwort bei Raspberry PI an (Schlüsselauthentifizierung)
Englische Spracherkennung mit Python [Rede zu Text]
Raspberry Pi 3 x Julius (Lese- und Grammatikdatei)
Automatische Sprachtranskription mit Google Cloud Speech API
Konvertieren Sie Sprache mit dem Azure Speech SDK in Text
Stellen Sie mit Python auf Raspberry Pi eine Verbindung zu MySQL her
Einfaches IoT, um mit Raspeye und MESH zu beginnen
Stellen wir uns den Raum mit Raspeltorte vor, Teil 1
Verwenden Sie raspberryPi und Julius (Spracherkennung). ③ Wörterbucherstellung
GPGPU mit Raspberry Pi
DigitalSignage mit Raspberry Pi
Einfache Einführung in Home Hack mit Raspberry Pi und discord.py
Aktualisieren Sie Raspberry Pi Python mit pyenv auf 3.7 oder höher
Ich habe versucht, Pilze Pepper x IBM Bluemix Text to Speech
Erstellen Sie LCD-Spiele (16x2) mit Raspberry Pi und Python
Verbinden Sie Raspberry Pi mit "Python" mit der Alibaba Cloud IoT Platform
Mutter pflanzt mit Raspberry Pi
Ich habe mit Raspberry Pi gesprochen
Einführung von PyMySQL in Himbeer-Pi3
Sprechen mit Python [Text zu Sprache]
Ich habe versucht, die Bewässerung des Pflanzgefäßes mit Raspberry Pi zu automatisieren
Ich habe mit Razpai einen Webserver erstellt, um Anime zu schauen