httpbrowsergstreamerlive-streamingmjpeg

Solutions to stream from a decklink card to browsers (Gstreamer -> TCP MJPEG -> ?)


I need to live stream from a decklink card to a browser. I also must be able to do it with a very poor network link (128kbits/s...), so I need to be able to stream at a very low fps (1 fps is fine) and a very low image quality.

At the moment I'm using GStreamer to get the video from the card, to transcode it to MJPEG, and to stream it with TCP. This part is perfectly working, but now I need to tube this tcp stream to an HTTP stream.

I can do this with VLC and it works well at a "normal" framerate (15 fps -> 0.5 sec of latency). But if I feed VLC with a 1 fps stream, it introduces a latency of around 11 sec, which is not fine for my purpose.

So, now I'm looking for a replacement of VLC. I see 3 ways of doing it :

Then, my questions are :

Thanks for reading !


Solution

  • I got the websockets solution working, thanks to the node Dicer module (and thanks to mscdex on this post ).

    So here is what I did :

    1°) Stream my Decklink card's video over TCP whith GStreamer :

    gst-launch -v decklinksrc mode=10 connection=0 ! deinterlace ! videorate ! videoscale ! video/x-raw-yuv, framerate=1/5, width=256, height=144 ! jpegenc quality=20 ! multipartmux  boundary="--videoboundary" ! tcpserversink host=<TCP src stream IP address> port=<TCP src stream port>
    

    2°) Listen to this stream with Node and send each image via socket.io :

    
        // ------------------------------------------------
        // Constants :
        // ------------------------------------------------
        
        var srcHost = "<TCP src stream IP address>";
        var srcPort = "<TCP src stream port>";
        var srcBoundary = "--videoboundary";
        
        var destHost = "<dest IP address>";
        var destPort = "<dest port>";
        
        // ------------------------------------------------
        // ------------------------------------------------
        // ------------------------------------------------
        
        
        
        // ------------------------------------------------
        // Includes :
        // ------------------------------------------------
        var Http = require('http');
        var Net = require('net');
        var Dicer = require('dicer');
        var SocketIO = require('socket.io');
        // ------------------------------------------------
        // ------------------------------------------------
        // ------------------------------------------------
        
        
        
        // ------------------------------------------------
        // TCP socket :
        // ------------------------------------------------
        
        var socket = Net.Socket();
        
        socket.connect(srcPort, srcHost, function() {
        
            // Init socket IO :
            var io = SocketIO.listen(Http.createServer().listen(destPort, destHost), { log: false });
        
            // Init Dicer :
            var dicer = new Dicer({ boundary: srcBoundary });
        
            dicer.on('part', function(part) {
        
                var frameEncoded = '';
                part.setEncoding('base64');
        
                part.on('header', function(header) { });
                part.on('data', function(data) { frameEncoded += data; });
                part.on('end', function() { io.sockets.emit('image', frameEncoded); });
            });
        
            // Handle streams closing :
            dicer.on('finish', function() { console.log('Dicer stream finished'); });
            socket.on('close', function() { console.log('TCP socket closed'); });
        
            // Pipe :
            socket.pipe(dicer);
        });
        // ------------------------------------------------
        // ------------------------------------------------
        // ------------------------------------------------
    

    3°) Listen to the websocket on the client :

        <html>
            <head>
        
                <script src="jquery-1.9.1.js"></script>
                <script src="socket.io-client/socket.io.min.js"></script>
        
                <script>
                var socket = io.connect('http://<dest IP address>:<dest port>');
                socket.on('image', function (data) {
                    
                    $("#video").attr("src", "data:image/jpeg;base64," + data.toString("base64") );
                });
                </script>
            </head>
            
            <body>
            
            <img id="video" style="display:block; width:400px; height:auto;" src="" />
            
            </body>
        </html>
    

    I will update this post if I get other solutions working (but I may go with this one).