从decklink卡流向浏览器的解决方案(Gstreamer - > TCP MJPEG - >?)

时间:2014-04-29 08:43:54

标签: http browser gstreamer live-streaming mjpeg

我需要从decklink卡直播到浏览器。我也必须能够使用非常差的网络链接(128kbits / s ...),因此我需要能够以非常低的fps(1 fps很好)和非常低的图像质量进行流式传输。 / p>

目前我正在使用GStreamer从卡中获取视频,将其转码为MJPEG,并使用TCP流式传输。这部分非常有效,但现在我需要将此tcp流管理到HTTP流。

我可以使用VLC执行此操作,并且它在“正常”帧速率(15 fps - > 0.5秒延迟)下工作良好。但是如果我用1 fps的流为VLC提供信息,它会引入大约11秒的延迟,这对我来说并不合适。

所以,现在我正在寻找VLC的替代品。我看到了3种方法:

  • 使用GStreamer的souphttpclientsink流式传输到HTTP流媒体服务器

  • 创建我自己的HTTP服务器,它会监听TCP流并将其重新流式传输到客户端。我尝试使用Python和Node.js,它几乎可以工作,但是我希望有一个比前一个更强大的解决方案

  • 更加棘手:创建我自己的HTTP服务器,监听TCP流并使用websockets将数据发送到客户端,然后解码然后流客户端......

然后,我的问题是:

  • 您知道哪些HTTP流服务器(如果可能的话免费)可以与souphttpclientsink(或tcpclientsink)一起使用吗?

  • 您还有其他想法将GStreamer流流式传输到浏览器吗?

感谢阅读!

1 个答案:

答案 0 :(得分:6)

我得到了websockets解决方案,感谢节点Dicer模块(感谢this post上的mscdex)。

所以这就是我所做的:

1°)使用GStreamer通过TCP流式传输我的Decklink卡的视频:

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°)使用Node收听此流,并通过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°)听取客户端上的websocket:

<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>

如果我得到其他解决方案,我会更新这篇文章(但我可以选择这个)。