WebRTC 与 WebSockets 服务器到 client/s(一对多)来自 IP 摄像机的实时视频流

WebRTC vs WebSockets server to client/s (one to many) live video streaming from IP camera

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

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

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

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

…from what I've seen webRTC server implementations don't support media channels anyways, so I will need to use Data Channels…

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

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

I could just do the same using WebSockets

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

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

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

我已经使用轻量级 Node.js 服务器走了这条路,包装了 FFmpeg。这样从源头获取视频就很简单了。当我这样做时,我实际上使用了 WebM。第一个Cluster element can be treated as initialization data. And then, assuming each Cluster starts with a keyframe (which is usually the case), you can drop into any part of the stream later. (See also: )

之前的所有数据

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

现在,你该怎么办?

这归结为一些权衡。

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

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

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

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