javascript - 如何确定视频帧是否已准备好进行合成?
问题描述
我在 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 甚至没有计划很快)。
如果视频帧尚未准备好进行合成,我会尝试避免更新纹理,但找不到可靠的方法来确定何时准备好。
非常感谢任何帮助!
解决方案
好吧,我找到了一个解决播放事件的方法。
我在听on play
,on timeupdate
没想到on playing
会如此不同。
它在第一帧可用于合成后触发,现在我不再有那些 WebGL 错误。在 Android 10 设备以及 iOS 14.5 iPhone 7 设备上进行了测试。
推荐阅读
- arrays - 在 C 中传递混合的 const 整数 ASCII 值和 const char 数组,并在没有先前声明的情况下传递 const int
- bash - 从多个图像和声音文件创建叙述幻灯片
- django - user=User.objects.get_or_create(first_name=fk_first_name,last_name=fk_last_name,email=fk_email)[0] 为什么使用 [0]
- c++ - 我应该将 printf 与 std::cin 混合使用吗?
- laravel - 如何解决请求规则验证中的未知列“employment_type_id.0”
- linux - 将mpd重新流式传输到m3u8会加载CPU,有什么解决方案吗?
- visual-studio-code - 如何找到 VSCode 默认的 NodeJS 二进制位置?
- java - 为什么我无法从 tcp 服务器获得响应?
- laravel - 如何在 Laravel 中使用相同的请求来获取替代功能
- java - 如何在 datepicker Android 中仅启用特定日期?