WebRTC 与 WebSockets 服务器到客户端(一对多)从 IP 摄像机的实时视频流

Tha*_*bha 6 video-streaming websocket live-streaming webrtc mediastream

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

我想知道在这种情况下使用 WebSockets 而不是 WebRTC 来广播媒体流是否会更好,因为从我所看到的 webRTC 服务器实现无论如何都不支持媒体通道,所以我需要使用数据通道,并通过将流打包为与 MediaSource 兼容,以及配置信令、TURN 和 STUN 服务器,当我可以使用 WebSockets 执行相同操作时,我是否遗漏了某些内容,或者在这种情况下 WebSockets 真的会更好吗? WebRTC 是否有任何功能可以让通过 WebSocket 实现它的开销变得值得?

编辑:忘记提及客户端是网络浏览器。

Bra*_*rad 8

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

\n
\n

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

\n
\n

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

\n

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

\n
\n

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

\n
\n

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

\n
<video src="https://streams.example.com/your-stream-id" preload="none" controls></video>\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

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

\n

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

\n

现在,你应该做什么?

\n

这归结为一些权衡。

\n
    \n
  • 如果您需要端到端低延迟(<2秒),则必须使用 WebRTC
    整个堆栈虽然复杂,但却是围绕尽可能低的延迟构建的。在编码、解码、网络等各个方面都进行了权衡。这意味着媒体质量较低。这意味着当数据包丢失时,会尽一切努力跳过客户端前进,而不是缓冲以尝试获取丢失的数据。但是,如果您需要低延迟,则所有这些都需要完成。

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

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

    \n
  • \n
\n

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

\n