如何确定视频帧是否已准备好合成?

How to determine if video frame is ready for composition?

我在 Whosebug 上找到了一些 similar question,但它并没有真正解决我的问题。

我正在将多个视频一个接一个地播放到 WebGL 纹理中。它基于用户输入,类似于基于 Web 的 VJ 工具。

复制很容易完成,我的内部时钟与我正在播放的视频(例如 30fps)同步,并且帧更新正确。完全像上述问题中提供的答案之一。一切正常。

纹理更新为:

gl.texSubImage2D(gl.TEXTURE_2D,0,0,0,this.gl.RGBA,this.gl.UNSIGNED_BYTE,video);

我的问题是如何检测第一帧何时可用于合成。视频在真实环境中不会立即开始播放(例如平均 4G,CDN 上的视频),但有时需要 1s 或更长时间才能开始播放(以缓冲足够的数据)。

如果我尝试在第一帧可用之前开始更新纹理,则会抛出 WebGL 错误:

WebGL: INVALID_VALUE: texSubImage2D: no video

我知道可以提前调用的 video.load(); 方法(例如在用户交互时),但是我有大约 50 个视频文件需要播放(顺序未知,因为它取决于用户输入)和旧手机(如 iPhone 7)在我这样做时性能会大幅下降,以至于 Safari 有时会崩溃。

我正在寻找一种可靠的方法来确定视频何时开始实际播放。 onplay 等事件似乎不会在第一帧可用时触发,而是更早。

我也试过 ontimeupdate 事件,但是当第一帧可用于合成时,那个事件似乎不会触发,但也会更早,就像 onplay 一样。我可以看到事件被触发,并且我在第一次触发时开始更新纹理,但在更新开始时它会生成 WebGL 错误(大约 0.5-1 秒,具体取决于网络速度),直到视频实际显示第一帧。缓冲后,不会抛出任何错误。

此问题在 4G/移动网络中更为明显。还在 Chrome 中以节流速度进行了测试。未节流的速度会在显示第一帧之前让我收到 1-4 WebGL 警告,而例如。 12mbps throttled 会给我 100-200 个警告,显示之前的视频帧。

我看过 requestVideoFrameCallback 但它没有我需要的覆盖范围(iOS Safari 近期甚至没有计划)。

我试图避免在视频帧尚未准备好合成时更新纹理,但无法找到确定何时准备就绪的可靠方法。

非常感谢任何帮助!

好的,我在监听 on playing 事件中找到了解决方案。

我在听 on playon timeupdate,没想到 on playing 如此不同。

它确实在第一帧可用于合成后触发,现在我再也没有那些 WebGL 错误了。在 Android 10 设备以及 iOS 14.5 iPhone 7 设备上进行了测试。