视频搜索滚动(60fps)

发布于 2025-01-18 13:44:06 字数 1403 浏览 0 评论 0原文

试图在页面滚动时通过视频寻求效果。通过将视频的所有帧导出到JPEG图像,预先加载图像并将其渲染到canvas来实现这一目标。但是,这种方法使用了很多带宽,并且需要很长时间才能加载慢速网络。

尝试通过将视频呈现到Canvas来实现相同的效果并不像基于图像的方法那样顺利。

这是一个具有基于视频的方法的工作演示:

https:/ /codesandbox.io/s/infallible-chaum-grvi0r?file=/index.html

htmlmediaelement.fastseek()没有广泛的浏览器覆盖范围,如何实现30-60 fps的实时播放率?

这是效果的相关代码(有关完整代码,请参见上面的CSB链接):

const video = document.querySelector("video");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

(function tick() {
  requestAnimationFrame(tick);

  const { scrollHeight, clientHeight, scrollTop } = document.body;
  const maxScroll = scrollHeight - clientHeight;
  const scrollProgress = scrollTop / maxScroll;

  canvas.width = document.body.clientWidth;
  canvas.height = document.body.clientHeight;

  // This is the line that causes the issue
  video.currentTime = video.duration * scrollProgress;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
})();

Trying to achieve an effect of seeking through a video when the page is scrolled. This has been achieved by exporting all frames of the video to JPEG images, pre-loading the images, and rendering them to a canvas. However, this approach uses a lot of bandwidth and takes a long time to load on slow networks.

Trying to achieve the same effect by rendering a video to a canvas does not play as smoothly as the image-based approach.

Here is a working demo with the video-based approach:

https://codesandbox.io/s/infallible-chaum-grvi0r?file=/index.html

Since HTMLMediaElement.fastSeek() doesn't have widespread browser coverage, how can one achieve a realtime playback rate of 30-60 FPS?

Here is the relevant code for the effect (see CSB link above for the full code):

const video = document.querySelector("video");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

(function tick() {
  requestAnimationFrame(tick);

  const { scrollHeight, clientHeight, scrollTop } = document.body;
  const maxScroll = scrollHeight - clientHeight;
  const scrollProgress = scrollTop / maxScroll;

  canvas.width = document.body.clientWidth;
  canvas.height = document.body.clientHeight;

  // This is the line that causes the issue
  video.currentTime = video.duration * scrollProgress;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
})();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

堇年纸鸢 2025-01-25 13:44:06

该问题是由于 drawImage() 的具体情况造成的,如此处,仅应在触发 seeked 事件后调用它。下面的代码通过使用标记值 (seeked = false) 解决了该问题,该值将阻止 drawImage() 的执行,直到下一个 seeked事件:

const video = document.querySelector("video");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
let seeked;
(function tick() {
    requestAnimationFrame(tick);
    if (seeked) {
        seeked = false;
        const { scrollHeight, clientHeight, scrollTop } = document.body;
        const maxScroll = scrollHeight - clientHeight;
        const scrollProgress = scrollTop / Math.max(maxScroll, 1);

        canvas.width = document.body.clientWidth;
        canvas.height = document.body.clientHeight;

        // This is the line that causes the issue
        video.currentTime = video.duration * scrollProgress;

        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    }
})();
video.addEventListener('seeked', () => {
    seeked = true;
});
video.currentTime = .001;

The problem is due to specifics of drawImage() as noted here, it should be called only after firing of seeked event. The code below solves the problem by using a sentinel value (seeked = false) which will block the execution of drawImage() until the next seeked event:

const video = document.querySelector("video");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
let seeked;
(function tick() {
    requestAnimationFrame(tick);
    if (seeked) {
        seeked = false;
        const { scrollHeight, clientHeight, scrollTop } = document.body;
        const maxScroll = scrollHeight - clientHeight;
        const scrollProgress = scrollTop / Math.max(maxScroll, 1);

        canvas.width = document.body.clientWidth;
        canvas.height = document.body.clientHeight;

        // This is the line that causes the issue
        video.currentTime = video.duration * scrollProgress;

        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    }
})();
video.addEventListener('seeked', () => {
    seeked = true;
});
video.currentTime = .001;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文