【问题标题】:WebRTC vs WebSockets server to client/s (one to many) live video streaming from IP cameraWebRTC 与 WebSockets 服务器到客户端(一对多)来自 IP 摄像机的实时视频流
【发布时间】:2022-01-02 09:41:17
【问题描述】:

我找不到明确的答案,假设我有一个服务器从 IP 摄像机接收 RTSP 源,这个流将被广播到多个客户端,连接总是由客户端初始化。

我想知道在这种情况下使用 WebSockets 而不是 WebRTC 来广播媒体流是否会更好,因为据我所知,webRTC 服务器实现无论如何都不支持媒体通道,所以我需要使用数据通道,并通过将流打包为与 MediaSource 兼容,就像配置 Signaling、TURN 和 STUN 服务器一样,当我可以使用 WebSockets 做同样的事情时,我是否遗漏了什么,或者在这种情况下 WebSockets 真的会更好,就像 WebRTC 是否有任何特性可以让通过 WebSockets 实现它的开销值得?

编辑:忘了说客户端是网络浏览器。

【问题讨论】:

    标签: websocket webrtc video-streaming live-streaming mediastream


    【解决方案1】:

    一些注意事项和其他需要考虑的事项:

    ……据我所知,webRTC 服务器实现无论如何都不支持媒体通道,所以我需要使用数据通道……

    可以在服务器端运行 WebRTC 媒体频道,但您是对的,因为可用的软件有限。实际上,我最终经常在服务器上使用无头 Chromium,因为它很简单,但这不适用于您的用例,因为您的流是通过 RTSP 进入的。

    如果您采用 WebRTC 路线,我建议您在服务器端使用 GStreamer。它拥有its own implementation WebRTC 所需的一切。您可以使用它来获取现有的流和复用器,并根据 WebRTC 的需要进行流和转码。

    我也可以使用 WebSockets 做同样的事情

    你可以,但我建议此时只使用常规 HTTP。您的流只是单向的,从服务器到客户端。无需 Web Sockets 的开销和麻烦。事实上,如果你做对了,你甚至不需要在客户端做任何特别的事情。只是一个视频元素:

    <video src="https://streams.example.com/your-stream-id" preload="none" controls></video>
    

    服务器需要设置所有视频初始化数据,然后放入直播流中。客户端只会播放流没有问题。

    我已经使用轻量级 Node.js 服务器走了这条路线,包装了 FFmpeg。这样,从源中获取视频就很简单了。当我这样做时,我实际上使用了 WebM。第一个Cluster element之前的所有数据都可以作为初始化数据。然后,假设每个集群都以一个关键帧开始(通常是这种情况),您可以稍后放入流的任何部分。 (另见:https://stackoverflow.com/a/45172617/362536

    换句话说,从 FFmpeg 获取 WebM/Matroska 输出并对其进行缓冲,直到看到 0x1F43B675。在此之前的所有内容,作为初始化数据保留。当客户端连接时,发送该初始化数据,然后在看到下一个0x1F43B675 时立即启动“实时”流。 (这是一个帮助您入门的快速摘要,但如果您在实施过程中遇到困难,请发布一个新问题。)

    现在,你应该怎么做?

    这归结为一些权衡。

    • 如果您需要低延迟端到端(必须使用 WebRTC。
      整个堆栈虽然复杂,但已构建尽可能低的延迟。在编码、解码、网络,无处不在。这意味着较低的媒体质量。这意味着当数据包丢失时,所做的一切都是为了跳过客户端转发而不是缓冲以尝试获取丢失的数据。但是,如果您需要低延迟,所有这些都需要完成。

    • 如果您想要最简单的实现每个来源拥有大量客户,或者想要使用现有的CDN,并且您不介意更高的延迟,考虑 HLS
      通过每个源的简单 FFmpeg 命令,您可以让所有输入的实时流一直在运行,并且当客户端连接时,它们只会接收播放列表和媒体片段。这是将源端与服务端和客户端隔离的好方法,并允许您重用大量现有基础架构。缺点当然是增加了延迟,而且你真的应该让源流一直运行。否则,最初启动流时会有相对较长的延迟。此外,HLS 很容易为您提供自适应比特率,只需花费更多 CPU 进行转码。

    • 如果您每个来源的客户端数很少并且不需要 ABR,请考虑使用 HTTP 渐进式流代理
      这基本上可以是大约 10 行从客户端接收流请求的 Node.js 服务器。当有请求进来时,立即执行FFmpeg连接源,FFmpeg输出WebM流。这与我上面所说的类似,但是由于每个客户端都有一个单独的 FFmpeg 进程,因此您不需要缓冲直到 Cluster 元素或任何东西。只需将 FFmpeg 输出直接通过管道传输到客户端。这实际上使您的延迟非常低。我已经得到它低至约 300 毫秒的玻璃到玻璃延迟。缺点是,如果丢包,客户端肯定会尝试缓冲,然后就会落后。您始终可以通过查看buffered time ranges 并决定是寻找还是提高播放速度来跳过客户端前面的播放器。 (这正是 HLS 播放器在实时落后时所做的事情。)否则,客户端只是一个视频元素。

    这是一个相当广泛的话题,因此希望这个答案可以为您提供更多可供考虑的选项,以便您可以决定最适合您的特定用例的选项。没有一个正确的答案,但肯定存在技术和易于开发的权衡。

    【讨论】:

    • 这太棒了,谢谢! Web 套接字背后的原因是我可能需要客户端向服务器发送命令,例如:移动相机,但我绝对可以将命令逻辑和流逻辑分开。
    • @ThabetSabha 如果用户可以控制相机,他们会希望立即看到这些控制的结果。因此,我会在您的情况下推荐 WebRTC。您的控件可以通过同一对等连接上的数据通道发送。另外,请在此处查看我的答案:stackoverflow.com/a/37475943/362536 与您的用例有点不同,但有一些相似之处。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    相关资源
    最近更新 更多