【发布时间】:2014-11-03 07:38:32
【问题描述】:
我正在制作一个应用程序,我希望用户使用他们的麦克风(在他们的手机上)并能够在游戏大厅中相互交谈。然而,事实证明这不仅仅是困难。
我正在使用 Node JS 套接字 io 和套接字 io 流
在我的客户端上,我使用音频 api 来获取我的麦克风输入(我并不太担心这一切,因为我将把它变成一个原生 IOS 应用程序)
navigator.getUserMedia = ( navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
if (navigator.getUserMedia) {
navigator.getUserMedia (
// constraints
{
video: false,
audio: true
},
function(localMediaStream) {
var video = document.querySelector('audio');
video.src = window.URL.createObjectURL(localMediaStream);
lcm = localMediaStream;
var audioContext = window.AudioContext;
var context = new audioContext();
var audioInput = context.createMediaStreamSource(localMediaStream);
var bufferSize = 2048;
// create a javascript node
var recorder = context.createScriptProcessor(bufferSize, 1, 1);
// specify the processing function
recorder.onaudioprocess = recorderProcess;
// connect stream to our recorder
audioInput.connect(recorder);
// connect our recorder to the previous destination
recorder.connect(context.destination);
},
// errorCallback
function(err) {
console.log("The following error occured: " + err);
$("video").remove();
alert("@#");
}
);
} else {
console.log("getUserMedia not supported");
}
function recorderProcess(e) {
var left = e.inputBuffer.getChannelData(0);
window.stream.write(convertFloat32ToInt16(left));
//var f = $("#aud").attr("src");
var src = window.URL.createObjectURL(lcm);
ss(socket).emit('file', src, {size: src.size});
ss.createBlobReadStream(src).pipe(window.stream);
//ss.createReadStream(f).pipe(widnow.stream);
}
function convertFloat32ToInt16(buffer)
{
l = buffer.length;
buf = new Int16Array(l);
while (l--) {
buf[l] = Math.min(1, buffer[l])*0x7FFF;
}
return buf.buffer;
}
});
ss(socket).on('back', function(stream, data) {
//console.log(stream);
var video = document.querySelector('audio');
video.src = window.URL.createObjectURL(stream);
console.log("getting mic data");
});
我可以成功地在麦克风上听到我的自言自语。我正在使用流套接字创建一个 blob 以上传到我的服务器...
index.ss(socket).on('file', function(stream, data) {
console.log("getting stream");
var filename = index.path.basename(data.name);
//var myfs = index.fs.createWriteStream(filename);
var fileWriter = new index.wav.FileWriter('demo.wav', {
channels: 1,
sampleRate: 48000,
bitDepth: 16
});
var streams = index.ss.createStream();
streams.pipe(fileWriter);
index.ss(socket).emit('back', fileWriter, {size: fileWriter.size});
});
我无法将流写入文件甚至临时缓冲区,然后流回客户端,以便我可以实时播放或“流式传输”音频。一段时间后,服务器崩溃并说管道不可写。
有没有其他人遇到过这种情况?
【问题讨论】:
-
可以在本地播放创建的blob吗?
-
通过 usig : var src = window.URL.createObjectURL(lcm);我可以播放我的麦克风。但是我不知道套接字 io 何时创建 blob 是否是正确的 blob 文件,因为它将它发送到服务器,并且我找不到将其保留在本地客户端 @dandavis 的方法
-
2 件事:1,您可以将 blob 转换为 dataURL 并发送它(性能有所降低,但工作总比没有快 100%)。 2、可以使用Chrome devtools network tab来监控socket流量,在network tab的url list的item details页面的frames tab上。
-
其传输正确。我肯定知道。我的问题是我想知道解决此解决方案的最佳方法是如何跨多个平台向客户端提供音频数据。如果我有很多客户端,我认为数据 URL 的可扩展性不高。这也将与实际游戏同时运行,所以我必须高效
-
dataURL 只会增加约 33% 的开销。您应该能够使用 socket.io 发出一个 blob。混合是可能的:在节点中捕获 dataURL,转换为 blob,然后广播 blob。如果 dataURL 转换或只是捆绑通常很慢,您可以使用工作线程来保持游戏循环流畅。尝试获取节点广播本地的真实文件作为要调试的 blob。
标签: javascript node.js audio socket.io streaming