お世話になります。
現在webRTCとNodeを利用した開発を行っておりまして、
ブラウザから録音(setTimeoutで4秒だけ録音)したデータをNodeにsocketでemitしNodeで受け取り、
受け取ったデータをとあるAPIに投げてそのレスポンスをブラウザにsocketのemitで返す。。。
という想定の処理を作っており、録音からAPIレスポンスまでの実装は出来動いてはいるのですが、
なぜか録音データが4秒だけの録音のはずなのに15秒の音声データとなってしまいます。。。
setTimeoutが原因かと思い手動で録音を停止する処理をかましても変わらず録音時間が膨れる状況です。。。
ソースは以下の通りですが何が原因でしょうか。。。※一部情報は伏せております。
webRTCは初めて利用しますので困っています。
ご教示頂けますと大変助かります。
宜しくお願い致します。
ejs
1<!-- クライアント側 --> 2<!DOCTYPE html> 3<html lang="ja"> 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <script type="text/javascript" src="/socket.io/socket.io.js"></script> 8 <link rel="stylesheet" href="css/index.css"> 9 <title>webRTC録音テスト</title> 10</head> 11<body> 12 <div id="containt"> 13 <ul> 14 <li><img id="greeting" src='<%= img %>'></li> 15 <li><input type="image" id="start" src="img/mic.png" /></li> 16 </ul> 17 </div> 18 <div id="result"> 19 </div> 20 <script> 21 var socket = io.connect(); 22 socket.on('respons', function(body) { 23 console.log(body); 24 }); 25 26 // for DOM 27 const downloadLink = document.getElementById('download'); 28 const startButton = document.getElementById('start'); 29 30 let buffer = 2048; 31 let context; 32 let processor; 33 let input; 34 let globalStream; 35 var audioData = []; 36 const property = { 37 audio: true, 38 video: false 39 }; 40 41 function record() { 42 context = new AudioContext(); 43 processor = context.createScriptProcessor(buffer, 1, 1); 44 processor.connect(context.destination); 45 context.resume(); 46 47 var recording = function(stream) { 48 globalStream = stream; 49 input = context.createMediaStreamSource(stream); 50 input.connect(processor); 51 processor.onaudioprocess = function(audio) { 52 audioStream(audio); 53 }; 54 setTimeout(function() { stop() }, 4000); 55 }; 56 navigator.mediaDevices.getUserMedia(property).then(recording); 57 } 58 59 function audioStream(audio) { 60 var input = audio.inputBuffer.getChannelData(0); 61 var bufferData = new Float32Array(buffer); 62 63 for (var i = 0; i < buffer; i++) { 64 bufferData[i] = input[i]; 65 } 66 audioData.push(bufferData); 67 } 68 69 function stop() { 70 startButton.disabled = false; 71 socket.emit('stop', audioData); 72 let track = globalStream.getTracks()[0]; 73 track.stop(); 74 audioData = []; 75 input.disconnect(processor); 76 processor.disconnect(context.destination); 77 context.close().then(function() { 78 input = null; 79 processor = null; 80 context = null; 81 startButton.disabled = false; 82 }); 83 alert('録音終了'); 84 } 85 86 // スタートボタン処理 87 startButton.addEventListener('click', function () { 88 record(); 89 }); 90 91 </script> 92</body> 93</html>
js
1// サーバ側 2var fs = require('fs'); 3var WavEncoder = require('wav-encoder'); 4var webclient = require("request"); 5var express = require("express"); 6var app = express(); 7 8// ejs 各種設定 9app.set("view engine", "ejs"); 10app.use(express.static('views')); 11 12app.get("/", function (req, res) { 13 const img = GreetingTime(); 14 15 // レンダリングを行う 16 res.render("./index.ejs", {img: img}); 17}); 18 19var io = require('socket.io').listen(app.listen(3000, () => console.log('app listening on port 3000!'))); 20// 録音終了を検知して処理を開始 21io.on('connection', function(socket) { 22 socket.on('stop', function(data) { 23 console.log('Socket Catch'); 24 25 var mergeBuffers = function(data) { 26 var sampleLength = 0; 27 for(var i = 0; i < data.length; i++) { 28 sampleLength += Objlen(data[i]); 29 } 30 31 var samples = new Float32Array(sampleLength); 32 var sampleIndex = 0; 33 34 for(var i = 0; i < data.length; i++) { 35 for(var j = 0; j < Objlen(data[i]); j++) { 36 samples[sampleIndex] = data[i][j] 37 sampleIndex++; 38 } 39 } 40 return samples; 41 }; 42 43 // サンプルレート調整 44 var audioData = { 45 sampleRate: 11025, 46 channelData: [mergeBuffers(data)] 47 }; 48 49 // WAVエンコード~APIにデータを投げる 50 WavEncoder.encode(audioData).then((buffer) => { 51 52 fs.writeFile('demo.wav', Buffer.from(buffer), function(e) { 53 if (e) { 54 console.log(e) 55 } else { 56 console.log("Success") 57 } 58 }); 59 60 let url = '※※※'; 61 let formData = { 62 'apikey' : '※※※', 63 'wav': Buffer.from(buffer), 64 'timeout': '100000' //milliseconds 65 }; 66 67 // API へ投げる 68 webclient.post({url:url, formData:formData}, function (error, response, body){ 69 socket.emit('respons',body); 70 console.log(body); 71 }); 72 }); 73 }); 74}); 75 76// jsonの要素数 77function Objlen(data) { 78 return Object.keys(data).length; 79} 80 81// 時間帯別に画像urlを返す 82function GreetingTime() { 83 require('date-utils'); 84 85 let dt = new Date(); 86 let time = dt.toFormat('HH24'); 87 if (time > 0 && time < 12 ) { 88 greeting = 'img/ohayou.png'; 89 } else if (time > 12 && time < 18) { 90 greeting = 'img/konnitiha.png'; 91 } else if(time > 18 || (time > 0 && time < 7)) { 92 greeting = 'img/konbanha.png'; 93 } 94 95 return greeting; 96} 97
◆追記
要件として、音声仕様は 16bit wavファイル 11025hz である事が必須です。
あなたの回答
tips
プレビュー