如何通过带有node.js和socket.io的WebSocketsstream式传输MP3数据?

我有问题通过WebSocket与node.js和socket.iostreamMP3数据。 一切似乎工作,但decodeAudioData不公平对我来说。

这是我的玩具服务器:

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/'); 

客户端接收数据typesstring,但我想喂数据decodeAudioData,它似乎不喜欢string。 decodeAudioData调用导致以下错误信息:

 Uncaught Error: SYNTAX_ERR: DOM Exception 12 

我认为decodeAudioData需要存储在ArrayBuffer中的数据。 有没有办法转换数据?

这是客户端代码:

 <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> 

我已经find了一种通过Websockets自己来传输MP3数据的方法。

一个问题是MP3数据的块大小。 看来,Web Audio API需要有效的MP3块才能解码数据。 可能不奇怪。 在我的演示程序中,我提供了一组MP3文件。

audio的质量也不完美。 我有一些微妙的故障。 我能够通过发送更大的MP3数据块来改善这种情况,但仍然存在一些微小的crack啪声。

编辑:我设法改善audio质量。 看来,Web Audio方法decodeAudioData并不是专门用来解码连续的MP3数据块的。

在你的情况下,context.decodeAudioData需要二进制数据的ArrayBuffer,我build议将你的chunk转换成base64string,然后转换到ArrayBuffer客户端,以获得最可预测的结果。 这个脚本应该是分块数据的base64客户端解码的一个很好的起点。

添加一行data = Base64Binary.decodeArrayBuffer(data); 获取您的数据(base-64编码的string)后,就可以做的伎俩…

看来,socket.io仍然不支持二进制传输。 所以websocket.io可以在这里使用。

  1. https://github.com/LearnBoost/socket.io/issues/511#issuecomment-2370129
  2. https://github.com/LearnBoost/socket.io/issues/680#issuecomment-3083490