Javascript 如何使用 node.js 和 socket.io 通过 WebSockets 流式传输 MP3 数据?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8759842/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to stream MP3 data via WebSockets with node.js and socket.io?
提问by Jan Deinhard
I have problems streaming MP3 data via WebSocket with node.js and socket.io. Everything seems to work but decodeAudioData doesn't play fair with me.
我在使用 node.js 和 socket.io 通过 WebSocket 流式传输 MP3 数据时遇到问题。一切似乎都有效,但 decodeAudioData 对我不公平。
This is my toy server:
这是我的玩具服务器:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(8081);
function handler (req, res) {
res.writeHead(200, {
'Content-Type': 'text/html',
});
res.end('Hello, world!');
}
io.configure('development', function() {
io.set('log level', 1);
io.set('transports', [ 'websocket' ]);
});
io.sockets.on('connection', function (socket) {
console.log('connection established');
var readStream = fs.createReadStream("test.mp3",
{'flags': 'r',
'encoding': 'binary',
'mode': 0666,
'bufferSize': 64 * 1024});
readStream.on('data', function(data) {
console.log(typeof data);
console.log('sending chunk of data')
socket.send(data);
});
socket.on('disconnect', function () {
console.log('connection droped');
});
});
console.log('Server running at http://127.0.0.1:8081/');
The client receives the data as type string but I want to feed the data to decodeAudioData and it seems it doesn't like strings. The call to decodeAudioData results in the following error message:
客户端以字符串类型接收数据,但我想将数据提供给 decodeAudioData 并且它似乎不喜欢字符串。对 decodeAudioData 的调用导致以下错误消息:
Uncaught Error: SYNTAX_ERR: DOM Exception 12
I think decodeAudioData needs the data stored in an ArrayBuffer. Is there a way to convert the data?
我认为 decodeAudioData 需要存储在 ArrayBuffer 中的数据。有没有办法转换数据?
This is the client code:
这是客户端代码:
<script src="http://127.0.0.1:8081/socket.io/socket.io.js"></script>
<script>
var audioBuffer = null;
var context = null;
window.addEventListener('load', init, false);
function init() {
try {
context = new webkitAudioContext();
} catch(e) {
alert('Web Audio API is not supported in this browser');
}
}
function decodeHandler(buffer) {
console.log(data);
}
var socket = io.connect('http://127.0.0.1:8081');
socket.on('message', function (data) {
// HERE IS THE PROBLEM
context.decodeAudioData(data, decodeHandler, function(e) { console.log(e); });
});
</script>
采纳答案by Jan Deinhard
I've found a way to stream MP3 data via Websockets myself.
我自己找到了一种通过 Websockets 传输 MP3 数据的方法。
One problem was the chunk size of the MP3 data. It seems that the Web Audio API needs to be fed with valid MP3 chunks to be able to decode the data. Probably not surprising. In my demo app I provide a set of MP3 chunk files.
一个问题是 MP3 数据的块大小。似乎网络音频 API 需要提供有效的 MP3 块才能解码数据。可能并不奇怪。在我的演示应用程序中,我提供了一组 MP3 块文件。
Also the quality of the audio is not perfect. I have some subtle glitches. I was able to improve that by sending larger chunks of MP3 data but there are still tiny crackles.
此外,音频的质量并不完美。我有一些微妙的故障。我能够通过发送更大的 MP3 数据块来改善这一点,但仍然有微小的噼啪声。
EDIT: I managed to improve the audio quality. It seems the Web Audio method decodeAudioData isn't really designed to decode continuos chunks of MP3 data.
编辑:我设法提高了音频质量。似乎网络音频方法 decodeAudioData 并不是真正设计用于解码连续的 MP3 数据块。
回答by Tracker1
In your case context.decodeAudioData expects an ArrayBuffer of the binary data, I would suggest converting your chunk to a base64 string, then to an ArrayBuffer client-side for the most predictable results. This scriptshould be a good starting point for the client-side decode from base64 of the chunked data.
在您的情况 context.decodeAudioData 需要二进制数据的 ArrayBuffer,我建议将您的块转换为 base64 字符串,然后转换为 ArrayBuffer 客户端以获得最可预测的结果。对于从分块数据的 base64 进行客户端解码,此脚本应该是一个很好的起点。
Adding a line with data = Base64Binary.decodeArrayBuffer(data);
right after getting your data (base-64 encoded string) would do the trick...
data = Base64Binary.decodeArrayBuffer(data);
在获取数据(base-64 编码的字符串)后添加一行就可以了……
回答by Anant Gupta
It seems that socket.io still doesn't support Binary transfer. So websocket.iocan be used here.
似乎socket.io 仍然不支持二进制传输。所以这里可以使用websocket.io。