node:提供唯一的音频流,导致可能的EventEmitter内存泄漏错误

时间:2013-11-25 23:06:54

标签: javascript html5 node.js audio-streaming

在下面的示例中,我尝试做的是为连接到服务器的每个客户端初始化一个唯一的流,并通过html5的音频标记将该流提供给客户端。因为我想要实时体验,我试图将最新的缓冲区从我的转码中写入音频流的输出。出于测试目的,我抓住NPR的公共流,通过transcode.sh将其转码为speex,并将其提供给我的客户。

问题在于,当我连接时,转码后的流不会通过音频标签播放。如果我尝试使用localhost:3002 / stream通过vlc打开流,节点会多次输出以下错误消息,并且也不会播放该流。

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
    at ServerResponse.EventEmitter.addListener (events.js:160:15)
    at Stream.pipe (stream.js:121:8)
    at CustomEmitter.<anonymous> (~/nodejs/audio_stream/sample.js:62:5)
    at CustomEmitter.EventEmitter.emit (events.js:95:17)
    at CustomEmitter.stream (~/nodejs/audio_stream/sample.js:23:7)
    at Socket.<anonymous> (~/nodejs/audio_stream/sample.js:32:11)
    at Socket.EventEmitter.emit (events.js:95:17)
    at Socket.<anonymous> (_stream_readable.js:720:14)
    at Socket.EventEmitter.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:392:10)

我猜我的问题与我写给/ stream的方式有关,但我并不确定。我究竟做错了什么?

以下是示例代码:

transcode.sh:

#!/bin/bash
ffmpeg -i "$1" -f ogg -acodec libspeex -ar 8000 -af 'volume=5.0' 2>/dev/null pipe:1

sample.js:

// contents of transcode.sh script:
// #!/bin/bash
// ffmpeg -i "$1" -f ogg -acodec libspeex -ar 8000 -af 'volume=5.0' 2>/dev/null pipe:1

var express = require('/usr/local/lib/node_modules/express');
var http = require('http');
var spawn = require('child_process').spawn;
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var stream = require('stream');

var app = express();
var webServer = http.createServer(app);
var audServer = http.createServer(app);

function CustomEmitter() {
    EventEmitter.call(this);
}
util.inherits(CustomEmitter, EventEmitter);

CustomEmitter.prototype.stream = function(data) {
    this.emit('stream', data);
};

var emitter = new CustomEmitter();

function getStream(arg1,arg2) {
    var cmd = spawn(arg1,arg2);
    //cmd.stdout.setEncoding('utf8');
    cmd.stdout.on('data', function(data) {
        emitter.stream(data);
    });
}

app.get('/', function(req, res){
    res.send(
    "<script src='/socket.io/socket.io.js'></script>\n"+
    "<script>var socket=io.connect('http://127.0.0.1:3000');</script>\n"+
    "<script>\n"+
    "\tsocket.on('id', function(data) {\n"+
    "\t\taudio = document.getElementById('webStream');\n"+
    "\t\taudio.setAttribute(\"src\",'http://127.0.0.1:3002/stream);\n"+
    "\t});\n"+
    "</script>\n"+
    "<audio id='webStream' autoplay=\"autoplay\" controls=\"controls\"></audio>"
    );
});
webServer.listen(3000);

app.get('/stream', function(req, res){
    getStream('./transcode.sh',['http://nprdmp.ic.llnwd.net/stream/nprdmp_live01_mp3']);

    res.header('Content-Type', "audio/ogg");
    res.header('Transfer-Encoding', 'chunked');

    var s = new stream.Stream();
    s.readable = true;

    emitter.on('stream', function(data) {
        s.emit('data', data);
        s.pipe(res);
    });
});
audServer.listen(3002);

1 个答案:

答案 0 :(得分:1)

代码结构对我来说不正确。主要问题是如何使用emitter/stream处理程序中的代码不断地在stream事件上添加侦听器,并且永远不会删除它。所以它是一种JavaScript内存泄漏。我认为更好的方法可能是通过方法getStream返回事件发射器并将事件处理程序附加到它。