3

(unnecessary backstory) I have a nodejs server with expressjs framework that's proxy streaming a webcam feed. The reason I need this is because the mjpg stream must come from this server due to complex CORS issues.

//proxy from webcam server to avoid CORS complaining
app.get('/stream1',function(req,res){
    var url="http://camera.nton.lviv.ua/mjpg/video.mjpg"
    request(url).pipe(res);
});

question : The issue is simple. request(url).pipe(res) never closes, because the source is mjpeg which literally never ends. I need to find a way to force close this pipe when the client(browser; the destination) is no longer available - as in, closes the window.

enter image description here

Gyuhyeon Lee
  • 878
  • 1
  • 9
  • 20
  • You will need to use a websocket or some long pooling method to check if the client is still available. – mattdevio Oct 28 '16 at 13:37

3 Answers3

2

The other answers did not work for me. This line var pipe=request(url).pipe(res); returns the pipe instead of the request object. So I needed to break the line up.

The request object is needed to abort. Calling the .end() didn't work either, but the .abort() did the trick. It took me hours to find the answer that worked for me, so I thought I would share.

   app.get('/cam/frontdoor',function(req,res){

        var request_options = {
            auth: {
                user: '',
                pass: ''},
            url: 'http:/xx.xx.xx.xx/mjpg/video.mjpg',
        };

        var req_pipe = request(request_options);
        req_pipe.pipe(res);

        req_pipe.on('error', function(e){
            console.log(e)
        });
        //client quit normally
        req.on('end', function(){
            console.log('end');
            req_pipe.abort();

        });
        //client quit unexpectedly
        req.on('close', function(){
            console.log('close');
            req_pipe.abort()

        })


    })
twitzel
  • 21
  • 2
1

I have found out a simpler way. Add a event listener for client connection closing, and force close the pipe when it happens.

app.get('/stream1',function(req,res){
    var url="http://camera.nton.lviv.ua/mjpg/video.mjpg"
    var pipe=request(url).pipe(res);
    pipe.on('error', function(){
        console.log('error handling is needed because pipe will break once pipe.end() is called')
    }
    //client quit normally
    req.on('end', function(){
        pipe.end();
    }
    //client quit unexpectedly
    req.on('close', function(){
        pipe.end();
    }
});
Gyuhyeon Lee
  • 878
  • 1
  • 9
  • 20
  • Does this work fine for you? In my case, the proxied stream is extremely slow (unlike the original mjpg stream). – ecdeveloper Apr 02 '18 at 06:17
  • @ecdeveloper hi, this is sort of a necro - it's been 2 years so I'm not sure. I've never had the problem of proxied stream being slow. However, the biggest issue was that CORS problem kept popping up even if `Access-Control-Allow-Origin = *` was set correctly. I'd recommend reconsidering the decision to proxy that mjpeg stream(The file format itself is really old, and browsers don't seem to maintain support for it very much anymore. mjpeg files don't work with CORS headers - it's a chrome browser bug. Maybe you're trying to proxy it instead to get around this but I don't recommend.) – Gyuhyeon Lee Apr 02 '18 at 07:03
  • In summary, I'm not sure why your stream is slow(maybe slow server?) && I'm not sure what would be the best way to proxy the mjpeg stream in node.js && I'm sure CORS issue will be a problem if you try to fetch it directly from the browser in order to use stuff like p5js to process that image with client side javascript, && I suggest looking for alternatives(different file format, etc. mjpeg is just really slow and laggy because it's sending multiple jpegs continuously) – Gyuhyeon Lee Apr 02 '18 at 07:06
0

Use socket.io to monitor the remote connection

// install it on your project
npm install socket.io

// require it on server side
var socket = require('socket.io');

// listen for sockets from your server
var mysocks = socket.listen(myexpressappvar);

// keep collection of sockets for use if needed
// its good practice
var connectedSockets = [];

// add event handelers on server side
mysocks.sockets.on("connection", function(socket){
    
    // add socket to our collection
    connectedSockets.push(socket);
  
    // you will need to bind their stream id here.
    exe.....
    
    // listen for disconnected
    socket.on("disconnect", function(){
       // remove socket from collection 
       connections.splice(connections.indexOf(socket), 1);
       // destory stream here
       exe...
    });   
});
  
// last thing, is add socket.io to the client side.
<script src="/socket.io/socket.io.js"></script>

// then call connect from client side js file
var socket = io.connect();
mattdevio
  • 2,319
  • 1
  • 14
  • 28