Search code examples
node.jsstreampipespawnmplayer

Node.js Error Sending Stream to Mplayer, Sending File Works Fine


I'm trying to spawn mplayer as a child process, sometimes with a file to play and other times with a stream to play. The file works fine, but when I create a stream from the file, I get this error:

events.js:85 throw er; // Unhandled 'error' event ^ Error: read ECONNRESET at exports._errnoException (util.js:746:11) at Pipe.onread (net.js:550:26)

It's not a file permissions problem because I ran it as sudo and still had the same issue.

To test a potential problem with streaming, I created a write stream from the read stream and that worked without a problem.

I'm not really sure what to do next. I'd appreciate any advice or help.

Here's the code:

var fs = require('fs');
var spawn = require('child_process').spawn;
var file = "/usr/local/apps/ha6/web/voice/ga.wav";
var file2 = "/usr/local/apps/ha6/web/voice/ga2.wav";

function filePlay() {
    var mplayer = spawn("mplayer", ["-slave", file], {stdio: ['pipe', 'ignore', 'ignore']});
    mplayer.on("exit", function () {
        console.log("exit");
    });
}

function streamPlay() {
    var str = fs.createReadStream(file).on("error", function (error) {
        console.log("Error creating read stream:" + error);
    });

    var mplayer = spawn("mplayer", ["-slave "], {stdio: ['pipe', 'ignore', 'ignore']}).on("error", function (error) {
        console.log("Spawn error " + error);
    });

    str.pipe(mplayer.stdin);
}


function testPiping() {
    var str = fs.createReadStream(file).on("error", function (error) {
        console.log("Error creating read stream:" + error);
    });
    var str2 = fs.createWriteStream(file2).on("error", function(error) {
        console.log("Error creating write stream:" + error);
    });
    str.pipe(str2);
    console.log("Pipe a success!");
}

filePlay();     // works fine
testPiping();   // works fine
streamPlay();   // ECONNRESET error

Solution

  • I would guess that the reason the error looks so bad is that there's an underlying problem with net.Socket.on as seen here and the code was revised here. So joyent appears to be the code that's in the underlying error. My attempt above was to make a catch-all error trapper that "swallows" the error and puts it into the log.

    What is TCP RST? Read about it here. Sometimes a router or your ISP wants to validate that an open TCP connection is still listening and so they inject a reset. Your app's stack is expected to respond in such a way to satisfy them not to drop the session.

    Shorter answer: try upgrading the joyent module to latest.

    From this answer, "Clean and correct solution: Technically, in node, whenever you emit an 'error' event and no one listens to it, it will throw. To make it not throw, put a listener on it and handle it yourself. That way you can log the error with more information.", the suggestion is to listen (trap) the error so that it doesn't throw an exception. Joyent is throwing the error. If you don't catch it (trap it) then it rises to the level of destruction.