如何使用 node.js 和 socket.io 通过 WebSockets 流式传输 MP3 数据?

Posted

技术标签:

【中文标题】如何使用 node.js 和 socket.io 通过 WebSockets 流式传输 MP3 数据?【英文标题】:How to stream MP3 data via WebSockets with node.js and socket.io? 【发布时间】:2012-02-04 07:13:22 【问题描述】:

我在使用 node.js 和 socket.io 通过 WebSocket 传输 MP3 数据时遇到问题。一切似乎都正常,但 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/');

客户端以字符串类型接收数据,但我想将数据提供给 decodeAudioData,它似乎不喜欢字符串。对 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>

【问题讨论】:

你找到解决这个问题的方法了吗? 我还没有找到使用 socket.io 的解决方案。请参阅我自己的答案以获得没有 socket.io 的解决方案。 Socket.io 1.0 支持二进制,我试过了,但是不行。我也尝试使用 websocket,但错误完全相同。你有一个如何解决这个问题的例子吗?。 @cmarrero01 我当时的解决方案是使用ws而不是Socket.io。但我知道它适用于当前的 Socket.io 版本。在服务器端,我必须明确告诉 ws 发送二进制数据,如ws.send(array, binary: true, mask: true ); 不确定我是否将掩码设置为 true 或 false。 HTH 尝试从createReadStream中删除'encoding': 'binary', 【参考方案1】:

我自己找到了一种通过 Websocket 流式传输 MP3 数据的方法。

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

此外,音频的质量并不完美。我有一些微妙的故障。我可以通过发送更大的 MP3 数据块来改善这一点,但仍然有微小的裂纹。

编辑:我设法提高了音频质量。似乎 Web 音频方法 decodeAudioData 并不是真正设计用于解码连续的 MP3 数据块。

【讨论】:

您能发布您的解决方案吗?我也在尝试将 MP3 数据流式传输到 websocket。 请提供您的解决方案。 对于仍在寻找的人,解决方案在他的 Github 页面上:github.com/polaris/audio-demo @digitxp github 项目没有任何与流媒体相关的内容 你是怎么解决这个问题的?我们正在这样做,但音频声音是失真/静态噪音。【参考方案2】:

在您的情况下 context.decodeAudioData 需要二进制数据的 ArrayBuffer,我建议将您的块转换为 base64 字符串,然后转换为 ArrayBuffer 客户端以获得最可预测的结果。 This script 应该是从分块数据的 base64 进行客户端解码的良好起点。

在获取数据(base-64 编码的字符串)后立即添加一行 data = Base64Binary.decodeArrayBuffer(data); 就可以了...

【讨论】:

感谢您的回答,但我无法使用脚本。结果 ArrayBuffer 比它应该的长。无论如何,我想避免使用 Base64,因为它是开销。我想我自己找到了解决方案。我很快就会在这里发布。 @Fair Dinkum Thinkum 我想知道您的解决方案。 @fyasar 我的解决方案是使用ws 模块而不是socket.io。当时 socket.io 无法处理二进制数据。不确定是否仍然如此。 @Fair Dinkum Thinkum 你能发布你的解决方案吗? @FairDinkumThinkum Socket.io 1.0 支持二进制数据,但我仍然无法使其工作。socket.io/blog/introducing-socket-io-1-0/#binary 你可以分享你的解决方案吗?【参考方案3】:

socket.io 似乎还不支持二进制传输。所以这里可以使用websocket.io。

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

【讨论】:

以上是关于如何使用 node.js 和 socket.io 通过 WebSockets 流式传输 MP3 数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何实现 Laravel、node.js、socket.io 和 redis 以使用数据库创建实时聊天/通知

如何使用 node.js 和 socket.io 通过 WebSockets 流式传输 MP3 数据?

如何使用 node.js 和 socket.io 将文件从 iPhone 发送到另一台 iPhone?

如何使用 Socket.io 和 Node.js 开发大型聊天应用程序 [关闭]

Socket.io 使用 node.js,根本没有 express?

node.js、socket.io 和 SSL