帧应该如何打包到实时 WebM 流中?

How should frames be packed in a live WebM stream?

我正在通过 libvpx 使用 VP9 对实时流进行编码,并希望将其流式传输到 HTML5 播放器。我已经阅读了 Matroska specification and W3C WebM Byte Stream Format 并检查了几个由 libvpx 的 vpxenc 工具生成的 WebM 文件。一切看起来都不错,但是我找不到任何关于如何在 W3C 规范中描述的媒体段内打包编码视频帧的严格规则或指南。

据我所知,我必须发出包含内部块元素的簇的媒体段。据我了解,我可以为从编码器获得的每一帧使用一个简单的块元素,因为它只有一个时间戳。但是如何组织集群呢?对我来说,用一个简单的块条目为每个帧发出一个集群以减少缓冲和延迟是有意义的。这种方法被认为是正常的还是这样做有任何缺点,我应该缓冲一段时间,然后发出一个包含多个简单块元素的集群,覆盖缓冲的时间段?

更新

所以我实施了所描述的方法(使用单个简单块条目发射集群)并且视频似乎滞后很多所以大概这不是要走的路。

我认为答案取决于您要查找的延迟类型。您描述的方法会起作用,但会引入延迟。这对于直播来说通常不是问题,因为直播的目标不是低延迟,而是直接传输。 (事实上​​,在某些情况下,延迟是想要的,即使它仍然是直播。)

如果低延迟是目标,您应该研究 RTP 之类的东西。并不是说 webm 容器不可能,但这不是容器的目标,所以你会发现大多数工具以不关心低延迟的方式实现 webm,因为你不会使用它为了这个目的;你会改用 RTP。

(如果相反,通过延迟,你的意思是它结结巴巴,请务必提及它,因为这表明发生了一些不同的事情。)

所以我终于成功地混合了正在工作的直播流。

似乎我描述的初始方法(有一个集群和一个 SimpleBlock)实际上是这样工作的,但它有几个缺点:

Key frames SHOULD be placed at the beginning of clusters

  • 如果使用curl或其他方式将直播流存储在本地文件中,则可以解决可能的问题。根据我的理解,一个集群应该由一个完整的 GOP 组成。

我最初的假设之一是集群不能有 "unknown" 大小,但在实践中似乎 Chrome,VLC 和 ffplay 对此很满意,因此没有必要缓冲完整的 GOP 以确定大小,并且可以即时发射集群。

另一个重要方面是 SimpleBlock 元素中的时间戳是带符号的 16 位整数,因此您基本上可以在其中编码从簇时间码到 32767 的偏移量。因此,如果您使用默认时间刻度,其中 1 个刻度为 1 毫秒,这意味着集群不能超过 32 秒。如果 GOP 大小很大,则在决定是否发出新集群时也必须考虑此标准。

最后,here 是一个 link 直播流("Big Buck Bunny" 预告片,但采用直播格式)似乎适用于所有玩家并生成为根据上面的描述。

希望这些信息对大家有所帮助。