实时低延迟直播:使用配置的node-media-server和Dash.js。

9
我们正在开发一款应用程序,能够实时监控您的后院。每个客户端都连接到互联网上的摄像头,流式传输到我们的公共node.js服务器。
我正试图使用node-media-server来发布MPEG-DASH(或HLS)流,以供我们的应用客户在不同的网络、带宽和分辨率下使用。
我们的目标是尽可能接近实时,这样您就可以立即监控后院发生的情况。
已经完成的技术流程如下:
  1. ffmpeg process on our server processes the incoming camera stream (separate child process for each camera) and publishes the stream via RTSP on the local machine for node-media-server to use as an 'input' (we are also saving segmented files, generating thumbnails, etc.). the ffmpeg command responsible for that is:

    -c:v libx264 -preset ultrafast -tune zerolatency -b:v 900k -f flv rtmp://127.0.0.1:1935/live/office

  2. node-media-server is running with what I found as the default configuration for 'live-streaming'

    private NMS_CONFIG = {
    server: {
      secret: 'thisisnotmyrealsecret',
    },
    rtmp_server: {
      rtmp: {
        port: 1935,
        chunk_size: 60000,
        gop_cache: false,
        ping: 60,
        ping_timeout: 30,
      },
      http: {
        port: 8888,
        mediaroot: './server/media',
        allow_origin: '*',
      },
      trans: {
        ffmpeg: '/usr/bin/ffmpeg',
        tasks: [
          {
            app: 'live',
            hls: true,
            hlsFlags: '[hls_time=2:hls_list_size=3:hls_flags=delete_segments]',
            dash: true,
            dashFlags: '[f=dash:window_size=3:extra_window_size=5]',
          },
        ],
      },
    },
    

    };

  3. As I understand it, out of the box NMS (node-media-server) publishes the input stream it gets in multiple output formats: flv, mpeg-dash, hls. with all sorts of online players for these formats I'm able to access and the stream using the url on localhost. with mpeg-dash and hls I'm getting anything between 10-15 seconds of delay, and more.


我的目标是实现一个本地客户端的MPEG-DASH播放器,使用dash.js,并将其配置为尽可能接近实时。

我编写了以下代码:

<!doctype html>
<html>
    <head>
        <title>Dash.js Rocks</title>
        <style>
            video {
                width: 640px;
                height: 480px;
            }
        </style>
    </head>
    <body>
        <div>
            <video autoplay="" id="videoPlayer" controls=""></video>
        </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/dashjs/3.0.2/dash.all.min.js"></script>

        <script>
            (function(){
                // var url = "https://dash.akamaized.net/envivio/EnvivioDash3/manifest.mpd";
                var url = "http://localhost:8888/live/office/index.mpd";
                var player = dashjs.MediaPlayer().create();
                
                

                // config
                targetLatency = 2.0;        // Lowering this value will lower latency but may decrease the player's ability to build a stable buffer.
                minDrift = 0.05;            // Minimum latency deviation allowed before activating catch-up mechanism.
                catchupPlaybackRate = 0.5;  // Maximum catch-up rate, as a percentage, for low latency live streams.
                stableBuffer = 2;           // The time that the internal buffer target will be set to post startup/seeks (NOT top quality).
                bufferAtTopQuality = 2;     // The time that the internal buffer target will be set to once playing the top quality.


                player.updateSettings({
                    'streaming': {
                        'liveDelay': 2,
                        'liveCatchUpMinDrift': 0.05,
                        'liveCatchUpPlaybackRate': 0.5,
                        'stableBufferTime': 2,
                        'bufferTimeAtTopQuality': 2,
                        'bufferTimeAtTopQualityLongForm': 2,
                        'bufferToKeep': 2,
                        'bufferAheadToKeep': 2,
                        'lowLatencyEnabled': true,
                        'fastSwitchEnabled': true,
                        'abr': {
                            'limitBitrateByPortal': true
                        },
                    }
                });

                console.log(player.getSettings());

                setInterval(() => {
                  console.log('Live latency= ', player.getCurrentLiveLatency());
                  console.log('Buffer length= ', player.getBufferLength('video'));
                }, 3000);

                player.initialize(document.querySelector("#videoPlayer"), url, true);

            })();

        </script>
    </body>
</html>

通过在线测试视频 (https://dash.akamaized.net/envivio/EnvivioDash3/manifest.mpd),我发现直播延迟值接近2秒(但我无法实际确认。它是一个视频文件流。在我的办公室里,我有一个摄像头,所以我可以比较现实生活和我的视频流之间的延迟)。 然而,在本地使用我的NMS时,似乎这个值不想低于20-25秒。

我做错了什么吗?客户端HTML上是否有任何配置我忘记了? 还是我应该在服务器端(NMS)添加缺少的配置?


2
你的一切都做得很好,除了你最初期望使用这项技术实现低延迟这一点。WebRTC 是你需要使用的。 - user1390208
2个回答

7
HLS和MPEG DASH作为标准协议,并不特别低延迟,因此您得到的数字并不罕见。 一些来自公开可用的DASH论坛文档(在下面链接中提供)的示例包括:

enter image description here

enter image description here

鉴于这些组织的资源,您所取得的成果还不错!
目前,流媒体行业非常注重实现更低的延迟,目标是尽可能接近传统广播延迟。
分块自适应比特率(ABR)的延迟中的一个关键组件(请参见此答案https://dev59.com/d1gQ5IYBdhLWcg3wsGGZ#42365034以获取更多信息)是播放器在能够显示视频之前需要接收和解码一个或多个视频片段。传统上,播放器必须在完全接收整个片段后才能开始解码和显示。下面来自第一个链接的开源参考文献说明了这一点:

enter image description here

低延迟的DASH和HLS利用了CMAF(Common Media Application Format),将可能长达6秒的片段分解成更小的“块”。这些块被设计为允许播放器在接收到完整片段之前对其进行解码和播放。
Typical live stream中其他导致延迟的因素包括从一种格式转换为另一种格式的任何转码,以及流媒体服务器接收来自网络摄像头的视频源并对其进行编码和打包以供流媒体传输时的任何延迟。
目前有很多关于低延迟流媒体的好信息,包括标准机构和开源讨论,我认为这些信息将真正帮助您理解相关问题(所有链接截至撰写本文时均有效)。以下是一些开源和标准化讨论链接:
-DASH:https://dashif.org/docs/Report%20on%20Low%20Latency%20DASH.pdf -HLS:https://github.com/video-dev/hlsjs-rfcs/pull/1

来自供应商:

注意- 广播行业经常引用的一个常见用例是,观看现场比赛的人可能会在看到进球或触地得分之前听到他们的邻居庆祝,因为他们的视频流延迟比邻居的要高。虽然这是低延迟的一个驱动因素,但这实际上是一个同步问题,如果“完美”同步的解决方案是目标,就需要其他解决方案。
正如您所看到的,低延迟流媒体并不是一个简单的挑战,根据您的使用情况的细节,包括您有多少订阅者,是否有一些质量损失作为低延迟的公平交换等,您可能希望考虑其他方法。正如@user1390208在评论中提到的,更加实时的视频通信技术,例如WebRTC,可能更适合您正在针对的解决方案。
如果您想提供既提供实时流媒体又提供录制的服务,您可能希望考虑使用实时协议进行实时流媒体视图,而对于回放记录,可以使用HLS/DASH流媒体,其中延迟可能不重要,但质量可能更为关键。

非常感谢您详细的回答,非常感激。我的一位同事建议使用低延迟HLS(https://www.wowza.com/blog/hls-latency-sucks-but-heres-how-to-fix-it),我们可能能够接近实时,就像我原来的帖子中描述的那样。您对此有什么想法吗? - Maor Barazani
这将取决于您的需求 - 对于广播而言,1-2秒可能被认为是实时的,但对于汽车后视摄像头(例如),任何实时延迟都需要以毫秒为单位进行测量。我认为您将难以通过任何当前的流媒体技术达到1秒的延迟。低延迟方法通常涉及较小的数据块,但也有一些注意事项,其中一些在链接中也提到了。 - Mick

1
我曾经处理类似的任务——尽可能接近实时。研究发现DASH并不是实现实时翻译最快的方法。通过对合作伙伴媒体服务器端和FFmpeg进行一些重大调整,我们可以获得6秒的延迟。这已经足够让用户在系统中查看部分内容了。但对于翻译管理员,我们希望更接近实时。但还有另一个解决方案,我们正在使用它——Websockets/WebRTC。我们主要使用Wowza流媒体引擎作为企业解决方案,并通过一些调整,我们已经实现了2秒的WebRTC延迟。

但是,在NMS的情况下,也有一种方法可以直接获取websocket-flv流。仅供测试,通过使用他们在github网站上的播放器解决方案,我目前只实现了4-4.5秒的延迟。示例图片或许这些信息会有所帮助。


实际上非常有用。经过相当多的研究和产品架构的重新设计,我们也选择了Wowza媒体服务器,使用RTSP协议从我们的服务器和摄像头向其进行流传输,并使用内置的vlc RTSP播放器通过我们的应用将其流式传输给最终用户。 - Maor Barazani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接