直播:node-media-server + Dash.js 配置为实时低延迟

Live streaming: node-media-server + Dash.js configured for real-time low latency

我们正在开发一款应用程序,可以实时监控您的后院。 每个客户端都有一个连接到互联网的摄像头,流式传输到我们的 public node.js 服务器。

我正在尝试使用 node-media-server 发布 MPEG-DASH(或 HLS)流,以供我们的应用程序客户端在全球不同的网络、带宽和分辨率下使用。

我们的目标是让尽可能接近生活"real-time",这样您就可以立即监控后院发生的事情。

已经完成的技术流程是:

  1. 我们服务器上的 ffmpeg 进程处理传入的摄像头流(每个摄像头的单独子进程)并通过本地机器上的 RTSP 发布流供节点媒体服务器用作 'input'(我们也在保存分段文件,生成缩略图等)。负责的 ffmpeg 命令是:

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

  2. node-media-server 是 运行 我发现 '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. 据我了解,开箱即用的 NMS(节点媒体服务器)以多种输出格式发布它获得的输入流:flv、mpeg-dash、hls。 对于这些格式的各种在线播放器,我可以使用本地主机上的 url 访问和流式传输。使用 mpeg-dash 和 hls 我得到的延迟在 10-15 秒之间,甚至更多。


我现在的目标是实现本地客户端 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) 添加缺少的配置?

作为标准,HLS 和 MPEG DASH 的延迟并不是特别低,您得到的数字并不罕见。

公开可用的 DASH 论坛文档(链接如下)中的一些示例包括:

以这些机构的资源来看,你们取得的成绩还不错!

目前流媒体行业非常关注降低延迟,目标是尽可能接近传统广播延迟。

分块自适应比特率(ABR,请参阅此答案了解更多信息:)延迟的一个关键组成部分是播放器需要在接收和解码视频的一个或多个片段之前它可以显示它。传统上,播放器必须先接收到整个片段,然后才能开始解码和显示它。下面第一个链接的开源参考中的图表说明了这一点:

低延迟 DASH 和 HLS 利用 CMAF,'Common Media Application Format' 将片段(例如可能为 6 秒长)分解为每个片段中更小的 'chunks'。这些块旨在让播放器在收到完整片段之前解码并开始播放它们。

典型直播流中的其他延迟来源包括从一种格式到另一种格式的任何转码,以及流媒体服务器从您的网络摄像头接收提要以及对其进行编码和打包以进行流式传输的任何延迟。

目前有很多关于低延迟流的有用信息,包括来自标准机构和开源讨论的信息,我认为这将真正帮助您理解这些问题(所有链接在撰写本文时都是最新的)。来自开源和标准讨论:

来自供应商:

注意 - 广播界经常引用的一个常见用例是,观看比赛等现场活动的人可能会在他们自己看到之前听到他们的邻居庆祝进球或达阵,因为他们的信息流具有更高的延迟比他们的邻居。虽然这是低延迟的驱动程序,但这实际上是一个同步问题,如果 'perfectly' 同步解决方案是目标,则需要其他解决方案。

如您所见,低延迟流式传输不是一个简单的挑战,您可能需要根据用例的详细信息考虑其他方法,包括您有多少订阅者,是否会出现一些质量损失为降低延迟等进行公平权衡。正如@user1390208 在评论中提到的,更实时的视频通信技术,如 WebRTC 可能更适合您的目标解决方案。

如果您想提供一种既提供生活流媒体又提供录音的服务,您可能需要考虑使用实时协议进行直播,并 HLS/DASH 为任何通过录音回顾的人使用流媒体延迟可能不重要,但质量可能更重要。

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

但是在 NMS 的情况下,也有一种开箱即用的方法来获取 websocket-flv 流。 只是为了测试,通过在 github site 处使用他们的播放器解决方案,我现在只实现了 4-4.5 秒的延迟。 也许这些信息会有用。