【问题标题】:Animating HTML Video with requestAnimationFrame使用 requestAnimationFrame 为 HTML 视频制作动画
【发布时间】:2020-05-18 18:26:36
【问题描述】:

我想使用requestAnimationFrame 播放HTML <video> 元素。这很有用,因为它可以更好地控制播放(例如,可以播放某些部分、控制速度等)。但是,我遇到了以下方法的问题:

function playAnimation() {
  window.cancelAnimationFrame(animationFrame);
  var duration = video.seekable.end(0);
  var start = null;

  var step = function(timestamp) {
    if (!start) start = timestamp;
    const progress = timestamp - start;
    const time = progress / 1000;

    video.currentTime = time;
    console.log(video.currentTime);

    if (time > duration) {
      start = null;
    }
    animationFrame = window.requestAnimationFrame(step);
  }

  animationFrame = window.requestAnimationFrame(step);
}

在谷歌浏览器中,视频播放了一点点,然后就卡住了。在 Firefox 中,它冻结得更多。控制台显示视频的currentTime 正在按预期更新,但它没有呈现新时间。此外,在视频冻结的情况下,ontimeupdate 事件不会触发,即使 currentTime 正在更新。

一个简单的演示可以在这里找到:https://codepen.io/TGordon18/pen/bGVQaXM

知道发生了什么问题吗?

更新: 有趣的是,控制/限制动画帧实际上有助于 Firefox。

setTimeout(() => {
  animationFrame = window.requestAnimationFrame(step);
}, 1000 / FPS);

这似乎不是正确的方法

【问题讨论】:

  • 关于你关于 setTimeout 的注释,我猜这是因为 rAF 任务的优先级高于 mediaelement 的任务,它本身高于 setTimeout 优先级。因此,将您的 rAF 调用包装在 setTimeout 中将使 MediaElement 的任务具有最高优先级,因此将在 setTimeout 触发之前完成,从而在您的下一个 rAF 调用之前完成。如果我是对的,那么您的代码将不再以 60Hz 运行。

标签: javascript html animation html5-video requestanimationframe


【解决方案1】:

视频的查找通常比requestAnimationFrame 的一帧慢。 requestAnimationFrame 的一个理想帧约为 16.6 毫秒(60 FPS),但搜索的持续时间取决于视频的编码方式以及您要在视频中搜索的位置。当在step 函数中设置video.currentTime 然后在下一帧做同样的事情时,之前的查找操作很可能还没有完成。当您一遍又一遍地调用video.currentTime 时,浏览器仍然会尝试执行旧任务,直到它开始冻结,因为它被任务的数量所淹没。它还可能会影响它触发事件的方式,例如timeupdate

解决方案可能是显式等待搜索完成,然后才请求下一个动画帧。

video.onseeked = () => {
   window.requestAnimationFrame(step);    
}

https://codepen.io/mradionov/pen/vYNvyym?editors=0010

尽管如此,由于查找操作的工作原理,您很可能无法像在视频标签中那样实现流畅的实时播放。除非您愿意在前一帧还没有准备好时丢弃一些当前帧。

基本上为每个视频帧存储整个图像是非常昂贵的。核心视频压缩技术之一是仅以某些间隔存储完整的视频帧,例如每 1 秒(它们被称为 I 帧的关键帧)。中间的其余帧将存储与前一帧(P 帧)的差异,这与整个图像相比非常小。当视频像往常一样播放时,它已经在缓冲区中有前一帧,它唯一需要做的就是为下一帧应用差异。但是当您进行搜索操作时,没有前一帧可以计算差异。视频解码器必须找到与完整图像最近的关键帧,然后对所有后续帧应用差异,直到它最终到达您想要寻找的帧。

如果你按照我的建议,在请求下一个搜索之前等待上一个搜索操作完成,你会看到视频开始流畅,但是当它接近 2.5 秒时,它会越来越卡顿,直到达到 2.5 s+ 并再次变得平滑。但话又说回来,它会开始卡顿到 5 秒,并在 5 秒 + 后再次变得平滑。这是因为此视频的关键帧间隔为 2.5 秒,而您要寻找的时间戳距离关键帧越远,所需的时间就越长,因为需要解码的帧越多。

【讨论】:

  • 这也是非常有用的信息,谢谢!我一直在尝试提高关键帧速率,这似乎确实有帮助。我还注意到使用vp8 编解码器切换到.webm 文件可以带来改进
  • 因此,此解决方案仅在关键帧数与您要播放的 fps 一样多的情况下才有效?
猜你喜欢
  • 2020-09-14
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-08
  • 2015-03-14
  • 1970-01-01
相关资源
最近更新 更多