[PYTHON] Speichern Sie die vom Browser erfassten Sprachdaten im WAV-Format auf dem Server

Dies ist ein Memo des Ergebnisses verschiedener Untersuchungen, um festzustellen, ob es möglich ist, über das an den PC angeschlossene Mikrofon problemlos Audio an den Server zu senden.

Es handelt sich um ein kleines Tool für den internen Gebrauch. Es handelt sich also um eine Spezifikation, die "vorerst nur die neueste Version von Google Chrome verwendet".

Es ist fast mein eigenes Memorandum und ich habe wenig Kenntnisse über JavaScript. Python wird häufig auf der Serverseite und zur Datenanalyse verwendet.

Vielleicht gibt es eine gute JS-Bibliothek für die Sprachkommunikation, und die unten beschriebenen Arbeiten können auf einmal abgeschlossen werden. Wenn Sie wissen, lassen Sie es uns in den Kommentaren wissen!

Holen Sie sich Audio mit einem Browser und senden Sie es mit einem Web-Socket

Dies ist Googles Artikel für WEB-Entwickler "Audiodaten von Benutzern abrufen" War hilfreich.

<script>  
  var handleSuccess = function(stream) {
    var context = new AudioContext();
    var input = context.createMediaStreamSource(stream)
    var processor = context.createScriptProcessor(1024, 1, 1);

    //WebSocket-Verbindung
    var connection = new WebSocket('wss://hogehoge.com:8000/websocket');

    input.connect(processor);
    processor.connect(context.destination);

    processor.onaudioprocess = function(e) {
      var voice = e.inputBuffer.getChannelData(0);
      connection.send(voice.buffer); //Senden per Web-Socket
    };
  };

  navigator.mediaDevices.getUserMedia({ audio: true, video: false })
      .then(handleSuccess)
</script>

1. So senden Sie weiterhin Audio an den Server

Es scheint drei Möglichkeiten zu geben, Audio an den Server zu senden:

  1. Umfrage mit http / https
  2. Senden Sie zeitweise über die WebSocket-Kommunikation (ws / wss).
  3. Verwenden Sie WebRTC

Hier Qiitas Artikel "Technologie zum Senden vom Server an den Client - Fokussierung auf WebSocket" und "Technologieeinführung von WebSocket / WebRTC ”war hilfreich.

"Es ist eine Schande, es häufig über http-Kommunikation zu senden, und es scheint schwierig zu sein, WebRTC zu verwenden, obwohl keine bidirektionale Sprachkommunikation erforderlich ist", entschied ich mich, den Sprachpuffer vorerst weiterhin mit Websocket zu senden. tat. WebSocket scheint in der Lage zu sein, Binärdateien oder Zeichenfolgen zu senden und zu empfangen.

2. AudioContext.createScriptProcessor bestimmt die Größe des gleichzeitig zu sendenden Audios

Weitere Informationen finden Sie in diesem Dokument.

Die Größe des Puffers in Einheiten von Beispielrahmen. Wenn angegeben, muss es einer der folgenden Werte sein: 256, 512, 1024, 2048, 4096, 8192, 16384. Wenn nicht angegeben oder 0 angegeben wird, wird der optimale Wert für die Umgebung festgelegt. Dieser Wert wird verwendet, solange der Knoten überlebt und sein Wert 2 darüber liegt.

Dieser Wert bestimmt, wie oft Audioprozessereignisse auftreten und wie groß der für jedes Ereignis übergebene Beispielrahmen ist. Die Angabe eines kleinen Werts führt zu einer geringen Latenz, und die Angabe eines großen Werts vermeidet Audio-Beschädigungen und Störungen. Es wird empfohlen, dass Sie diesen Wert nicht selbst festlegen, sondern von der Implementierung in Bezug auf Verzögerung und Qualität entscheiden lassen.

Ich kenne die genaue Bedeutung des Wortes "Erlaube der Implementierung, eine gute Puffergröße auszuwählen" nicht, aber sollte ich es auf 0 setzen?

Es wird auch in This Stack Overflow (2013) erläutert.

3. Holen Sie sich Audio mit AudioBuffer.getChannelData

Lesen Sie auch die Dokumentation. Wir haben es hier mit Mono-Sound zu tun, und wenn Sie Stereo-Sound benötigen, müssen Sie ihn anscheinend entwickeln.

Der Aufrufpuffer gibt Audiodaten vom Typ Float32Array zurück, dh reelle Zahlen im Bereich von -1 bis +1. Es ist zu beachten, dass WAV-Dateien (obwohl es mehrere Formate zu geben scheint) durch 16-Bit-Ganzzahlen mit Vorzeichen dargestellt werden, dh Werte zwischen -32768 und 32767.

Als WAV-Datei auf dem Server speichern

Ich habe Python 3.6 verwendet, an das ich gewöhnt bin.

Ich habe Tornado verwendet, ein leichtes WEB-Framework, das sich gut für die asynchrone Verarbeitung von Python eignet.

import tornado.ioloop
import tornado.web
import tornado.websocket

import wave
import numpy as np


SAMPLE_SIZE = 2
SAMPLE_RATE = 48000
PATH = '/path/to/output.wav'


class WebSocketHandler(tornado.websocket.WebSocketHandler):
    def open(self):
        self.voice = []
        print("opened")

    def on_message(self, message):
        self.voice.append(np.frombuffer(message, dtype='float32'))

    def on_close(self):
        v = np.array(self.voice)
        v.flatten()

        #In binäre in 16-Bit-Ganzzahl konvertieren und speichern
        arr = (v * 32767).astype(np.int16)
        with wave.open(PATH, 'wb') as wf:
            wf.setnchannels(1)
            wf.setsampwidth(SAMPLE_SIZE)
            wf.setframerate(SAMPLE_RATE)
            wf.writeframes(arr.tobytes('C'))
        
        self.voice.clear()
        print("closed")


app = tornado.web.Application([
    (r"/websocket", WebSocketHandler)
])

if __name__ == "__main__":
    app.listen(8000)
    tornado.ioloop.IOLoop.instance().start()

1. Über Tornado

Die Dokumentation für den WebSocket-Server, der Tornado verwendet, ist hier.

Andere Frameworks wie Flask, Bottle und Django sind berühmt, aber Tornado wurde übernommen, weil es sich gut für asynchrone Verarbeitung wie node.js eignet. Außerdem schien es viel Code zu geben, der im Vergleich zu anderen Frameworks als Referenz verwendet werden konnte.

2. Einfach zu lesender Binpy

Mit numpy, einer Bibliothek zur numerischen Berechnung in Python, können Sie die übergebenen Daten einfach lesen und als Array von numpy lesen.

Weitere Informationen finden Sie unter numpy.frombuffer Reference.

3. Über WAV-Dateien

Es ist zu beachten, dass WAV-Dateien (obwohl es mehrere Formate zu geben scheint) durch 16-Bit-Ganzzahlen mit Vorzeichen dargestellt werden, dh Werte zwischen -32768 und 32767.

Der Wert für die Abtastrate (48000) hängt auch von der Implementierung auf der JavaScript-Seite ab. Überprüfen Sie daher AudioContext.sampleRate. ..

Ich hatte Probleme, weil ich die Spezifikationen der WAV-Datenstruktur nicht verstanden habe, aber "Soundprogrammierung ab C-Sprache - Signalverarbeitung von Soundeffekten" Ich habe studiert, indem ich die Erklärung in Kapitel 1 gelesen habe.

Immerhin habe ich es geschafft, indem ich wave verwendet habe, eine Standard-Python-Bibliothek.

Zusammenfassung

das ist alles.

Von hier aus können Sie an die Sprach-API verschiedener Cloud-Dienste senden, die Sprachverarbeitung mit Python durchführen usw. Außerdem habe ich keine Zertifizierung gemacht, also muss ich es richtig machen.

Der Grund für die Verwendung von WebSocket ist, dass es interessant wäre, vom Server auf den Client (Browser) zu übertragen und die Ergebnisse der Sprachanalyse-API und der Sprachverarbeitung in Echtzeit zurückzugeben.

Recommended Posts

Speichern Sie die vom Browser erfassten Sprachdaten im WAV-Format auf dem Server
Festkomma-Beobachtung bestimmter Daten im Web durch automatische Ausführung des Webbrowsers auf dem Server (Ubuntu16.04) (1) -Webbrowser-Installation-
Exportieren Sie die von der Twitter Streaming API erfassten Inhalte im JSON-Format
Festpunktbeobachtung bestimmter Daten im Web durch automatische Ausführung eines Webbrowsers auf dem Server (Ubuntu16.04) (2) -Web Scraping-
Speichern Sie den von Bio.Phylos Funktion draw_ascii gezeichneten phylogenetischen Baum im Textformat
Führen Sie Aufgaben im Hintergrund auf dem Server aus, an den Sie gesendet haben
Festkomma-Beobachtung bestimmter Daten im Web durch automatische Ausführung des Webbrowsers auf dem Server (Ubuntu16.04) (3) ~ Cron automatische Ausführung ~
Beseitigen Sie verstümmelte japanische Zeichen in JSON-Daten, die von der API erfasst wurden.
Test.py wird auf dem Webserver in Python3 nicht angezeigt.
So deaktivieren Sie den Browser-Cache auf dem einfachen HTTP-Server von Python
Hinweise zur Farbfärbung im Matplotlib-Streudiagramm
So geben Sie die im Django-Modell enthaltenen Daten im JSON-Format zurück und ordnen sie der Broschüre zu
Gzip komprimiert Daten durch Streaming
Schreiben Sie Daten im HDF-Format
Von Django erfasste Daten wurden weitergegeben