【问题标题】:Video Flicker inside HTML canvas when looping循环播放时 HTML 画布内的视频闪烁
【发布时间】:2019-07-13 21:38:44
【问题描述】:

我正在尝试在 canvasloop 视频中显示视频。循环播放视频时有时会出现此问题。在再次播放视频之前,视频会闪烁一帧。它不会一直发生,我不明白发生了什么。

这里是代码

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

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

let src = "https://i.imgur.com/5ZiAeSX.mp4";
let video = document.createElement("video");
video.src = src;
video.muted = true;
video.play();

video.onended = () => {
  video.play();
};

function render() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(video, 0, 0);

  requestAnimationFrame(render);
}

render();

你也可以试试fiddlehere

【问题讨论】:

    标签: javascript html canvas video


    【解决方案1】:

    这是因为循环 MediaElement 从来都不是无缝操作。 这在looping audio media 时尤其明显。

    通常,当在

    但是,在您的情况下,它变得非常明显,因为您确实清除了画布,但没有要在其上绘制的视频帧。所以它会导致一个大的白色闪光。

    一个简单的解决方法是检查currentTime 是否为0 并且在此期间不重绘:

    let canvas = document.querySelector("canvas");
    let ctx = canvas.getContext("2d");
    
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    
    let src = "https://i.imgur.com/5ZiAeSX.mp4";
    let video = document.createElement("video");
    video.src = src;
    video.muted = true;
    video.play();
    
    let missed_frames = 0; // only for demo
    video.onended = () => {
      video.play();
      // only for demo
      setTimeout(() => {
      _log.textContent = 'missed ' + missed_frames +' frames while looping';
      missed_frames = 0;
      }, 200);
    };
    
    
    function render() {
      if(video.currentTime) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    	  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      }
      // only for demo
      else {
        missed_frames++;
      }
      requestAnimationFrame(render);
    }
    
    render();
    #_log { color: white; position: absolute; }
    <pre id="_log"></pre>
    <canvas></canvas>

    如果你真的需要无缝循环,一个更难的解决方法是使用MediaSource 对象,但如果不是真的需要,设置起来有点麻烦。

    【讨论】:

      【解决方案2】:

      您可以将 viedo.loop 设置为 true,并在您要求视频继续播放时避开该部分。

      我就是这样做的:

      let canvas = document.querySelector("canvas");
      let ctx = canvas.getContext("2d");
      
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      
      let src = "https://i.imgur.com/5ZiAeSX.mp4";
      let video = document.createElement("video");
      video.src = src;
      video.muted = true;
      video.videoHeight = '500px'; // returns the intrinsic height of the video
      video.videoWidth =  '100px'; // returns the intrinsic width of the video
      video.play();
      video.loop = true
      
      /* video.onended = () => {
        video.play();
      }; */
      
      function render() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(video, 0, 0);
      
        requestAnimationFrame(render);
      }
      
      render();
      

      这就是您的视频闪烁的原因,它不会循环播放,只会一遍又一遍地重播。 试一试;)

      【讨论】:

      • 不会改变任何东西
      • 是我们在右边看到的暂停时间你称之为闪烁吗?因为我根本看不到视频闪烁,我只看到它在播放中间暂停。为了使其更加对称,您可以从视频中删除此暂停时间,或者在每次重播前使其休眠 1 秒,但这个解决方案很老套
      • 问题似乎已经解决,实际上它取决于视频,如果视频不是精确的持续时间,如 4:0s 而是 3:97,而是在最后一帧闪烁。小提琴上似乎没有发生,因为我放错了视频
      • 好的!你仍然可以使用 video.loop = true,它似乎做同样的事情,但代码更少;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-06
      • 1970-01-01
      • 2021-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多