#はじめに
クライアント側ではなくサーバ側でgetUserMediaを保存したい!
サンプルソースはこちら
https://github.com/sinkunvv/qiita-samples/tree/master/Nodejs-wav
今回の実装で使用したライブラリは以下の通り
{
"name": "wav-encode",
"version": "1.0.0",
"dependencies": {
"express": "^3.3.8",
"socket.io": "^2.1.0",
"wav-encoder": "^1.3.0"
}
}
#1. getUserMediaを使用して音声データを取得する
まずはクライアント側の実装例
録音ボタン等にrecord()を紐づけてgetUserMediaで音声データを取得する
let buffer = 2048;
let context;
let processor;
let input;
let globalStream;
var audioData = [];
const property = {
audio: true,
video: false
};
function record() {
context = new AudioContext();
processor = context.createScriptProcessor(buffer, 1, 1);
processor.connect(context.destination);
context.resume();
var recording = function(stream) {
globalStream = stream;
input = context.createMediaStreamSource(stream);
input.connect(processor);
processor.onaudioprocess = function(audio) {
audioStream(audio);
};
};
navigator.mediaDevices.getUserMedia(property).then(recording);
}
function audioStream(audio) {
var input = audio.inputBuffer.getChannelData(0);
var bufferData = new Float32Array(buffer);
for (var i = 0; i < buffer; i++) {
bufferData[i] = input[i];
}
audioData.push(bufferData);
}
2. サーバに音声データを送信する
今回はストリーミングで音声認識をする必要があったためsocket.ioを使用していた。
bufferデータを送ることができれば他の方法を使用しても良いはず。(未確認)
function stop() {
startButton.disabled = false;
stopButton.disabled = true;
socket.emit('stop', audioData);
let track = globalStream.getTracks()[0];
track.stop();
audioData = [];
input.disconnect(processor);
processor.disconnect(context.destination);
context.close().then(function() {
input = null;
processor = null;
context = null;
startButton.disabled = false;
});
}
録音停止したタイミングで蓄積した音声データを送る。
3.Node.jsで音声データを受け取り、WAVにエンコードする
socket.ioでstopイベントを受け取ったらそのデータをexportWAVに送る
// 録音終了
socket.on('stop', function(data) {
exportWAV(data, sampleRateHertz);
console.log('stop record');
});
const WavEncoder = require('wav-encoder');
const fs = require('fs');
// jsonの要素数
function Objlen(data) {
return Object.keys(data).length;
}
//
function exportWAV(data, sampleRate) {
var mergeBuffers = function(data) {
var sampleLength = 0;
for(var i = 0; i < data.length; i++) {
sampleLength += Objlen(data[i]);
}
var samples = new Float32Array(sampleLength);
var sampleIndex = 0;
for(var i = 0; i < data.length; i++) {
for(var j = 0; j < Objlen(data[i]); j++) {
samples[sampleIndex] = data[i][j]
sampleIndex++;
}
}
return samples;
};
var audioData = {
sampleRate: 44100,
channelData: [mergeBuffers(data)]
};
WavEncoder.encode(audioData).then((buffer) => {
fs.writeFile('demo.wav', Buffer.from(buffer), function(e) {
if (e) {
console.log(e)
} else {
console.log("Success")
}
});
});
}
#終わり
音声認識での機械学習用にデータを収集したかったが
クライアント側でwavに変換してダウンロードする的なのは多くまとめられていたけれど
サーバ側で保存するが中々見つからなかったのでまとめてみた。
wav-encoderには助けられた...
誰かの足がかりになればと。
#参考サイト
getUserMediaで録音したデータをWAVファイルとして保存する - Qiita
Media Capture and Streams と Web Audio API で実現する録画・録音・ WAVファイルの生成 | CYOKODOG
javascript - Node.js can´t create Blobs? - Stack Overflow