是否可以反向播放HTML5视频?

Ish*_*Ish 23 javascript html5 html5-video

HTML5 <video>标签是反向播放视频,还是我必须下载2个视频(前进和后退播放).任何避免用户下载2个视频的解决方案?

Fré*_*idi 14

甚至没有进入HTML5或Javascript,许多视频格式都是旨在向前播放的流格式.向后播放将需要解码整个流,将每个原始帧存储在磁盘上以避免破坏内存,然后向后渲染帧.

然而,至少有一个人真正尝试过使用mplayer它,所以至少在原则上它可以完成.

  • 谢谢@Frédéric,现在我知道拥有 2 个单独的视频可以更好地解决我的问题。 (2认同)

Bap*_*teB 11

我设法在更新方法中做到了.每一帧我将video.currentTime减少到过去的时间,到目前为止,这是我设法获得的最佳结果.

  • 很高兴看到一个jsfiddle. (4认同)
  • 这是我要工作的一个非常粗略的,它有点不稳定,但你可以通过更改“0.1”和“100”来设置速率(即 0.1 秒等于 100 毫秒):``js var v = document.getElementById ('视频'); var反向 = setInterval(function() { v.currentTime = v.currentTime - 0.1; }, 100); ```` (2认同)

Chr*_*her 11

此片段仅显示了如何完成,但复制每个帧需要一些时间。这很大程度上取决于硬件。

它生成它必须播放的每一帧的画布。当它设置为 100% 时,播放会直接开始并向后、向前播放......等等。生成后也会附加原始视频,但由于 iframe 规则不会自动播放。

它非常适合短视频和概念证明。

更新: 我更改了捕获部分的顺序,以便跳过最大持续时间的帧,但捕获 0 处的帧(之前忘记了)。

最大持续时间的帧导致我尝试的每个视频上出现白色画布。

我还更改了播放方式,一旦到达最后一帧就以相反的顺序播放,以实现无限播放。因此您很容易看出,与硬件加速视频相比,这种播放有点占用 CPU 资源。

fetch('https://i.imgur.com/BPQF5yy.mp4')
  .then(res => res.blob())
  .then(blob => {
    return new Promise((res) => {
      const fr = new FileReader();
      fr.onload = e => res(fr.result);
      fr.readAsDataURL(blob);
    })
  }).then(async(base64str) => {
    const video = document.createElement("video");
    video.src = base64str;
    video.controls = true;
    video.className = "w-50";

    while (isNaN(video.duration))
      await new Promise((r) => setTimeout(r, 50));

    const FPS = 25;


    const status = document.createElement("div"),
      length = document.createElement("div");
    length.innerText = `Generating ${Math.ceil(video.duration / (1 / FPS))} frames for a ${FPS} FPS playback (Video Duration = ${video.duration})`;
    document.body.appendChild(length);
    document.body.appendChild(status);

    const frames = [],
      copy = () => {
        const c = document.createElement("canvas");
        Object.assign(c, {
          width: video.videoWidth,
          height: video.videoHeight,
          className: "w-50"
        });
        c.getContext("2d").drawImage(video, 0, 0);
        return c;
      };

    // first seek outside of the loop this image won't be copied
    video.currentTime = video.duration; 
    // this frame seems to be always white/transparent
    
    while (video.currentTime) {
      if (video.currentTime - 1 / FPS < 0)
        video.currentTime = 0;
      else
        video.currentTime = video.currentTime - 1 / FPS;
      await new Promise((next) => {
        video.addEventListener('seeked', () => {
          frames.push(copy());
          status.innerText = (frames.length / (Math.ceil(video.duration / (1 / FPS))) * 100).toFixed(2) + '%';
          next();
        }, {
          once: true
        });
      });      
    }


    /*
     * frames now contains all canvas elements created,
     * I just append the first image and replace it on
     * every tick with the next frame.
     * using last.replaceWith(frames[currentPos]) guarantees a smooth playback.
     */

    let i = 0, last = frames[0];

    document.body.insertAdjacentHTML('beforeend', `<div class="w-50">Captured</div><div class="w-50">Video</div>`);

    document.body.appendChild(frames[0]);

    const interval = setInterval(() => {
      if (frames[++i]) {
        last.replaceWith(frames[i]);
        last = frames[i];
      } else {
        frames.reverse();
        i=0;
      }
    }, 1000 / FPS);

    document.body.appendChild(video);
    // won't :(
    video.play();
  });
Run Code Online (Sandbox Code Playgroud)
/* Just for this example */
.w-50 {
  width: 50%;
  display: inline-block;
}

* {
  margin: 0;
  padding: 0;
  font-family: Sans-Serif;
  font-size: 12px;
}
Run Code Online (Sandbox Code Playgroud)


Eli*_*rey 10

aMediaElement.playbackRate = -1;
Run Code Online (Sandbox Code Playgroud)

UA可能不支持此功能,但设置playbackRate为负值是有效的.

  • 请注意,Chrome目前没有计划实施负回放率.https://code.google.com/p/chromium/issues/detail?id=33099 (5认同)
  • 目前也不支持Firefox (4认同)
  • 在Safari中使用MP4,但非常笨重(视频根本不流畅). (3认同)