首页 > 解决方案 > 如何确定视频帧是否已准备好进行合成?

问题描述

我在 Stackoverflow 上发现了一些类似的问题,但它并没有真正解决我的问题。

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

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

纹理更新为:

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 将给我 100-200 条警告,显示之前的视频帧。

我见过requestVideoFrameCallback但它没有我需要的覆盖范围(iOS Safari 甚至没有计划很快)。

如果视频帧尚未准备好进行合成,我会尝试避免更新纹理,但找不到可靠的方法来确定何时准备好。

非常感谢任何帮助!

标签: javascripthtml5-videowebgltexture2d

解决方案


好吧,我找到了一个解决播放事件的方法。

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

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


推荐阅读