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!
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>
Es scheint drei Möglichkeiten zu geben, Audio an den Server zu senden:
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.
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.
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.
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()
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.
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.
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.
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