javascript - HTML5 视频到 Canvas 播放速度很慢

标签 javascript html video canvas

我已经构建了这个 HTML5 视频播放器,我正在将其加载到 Canvas 中进行操作并返回到 Canvas 上以显示它。视频开始时很慢,每次播放时帧率只会变差。我目前在视频中操作的只是视频暂停时的颜色值,但最终会在未来发布的整个视频中使用实时操作。

我使用下面的教程来学习这个技巧 https://www.youtube.com/watch?v=zjQzP3mOXdc

这里是相关代码,但可能有其他地方的干扰,请随时查看底部链接中的源代码

var v = document.getElementById('video');
var color = "#DA7AC1";
var processes={
  timerCallback:function() {
    if (this.v2.paused || this.v2.ended) {
      return;
    }
        this.ctxIn.drawImage(this.v2,0,0,this.width,this.height);
        this.pixelScan();
        var self=this;
        setTimeout(function() {
          self.timerCallback();
        }, 0);
  },
  doLoad:function(){
    this.v2=document.getElementById("video");
    this.cIn=document.getElementById("cIn");
    this.ctxIn=this.cIn.getContext("2d");
    this.cOut=document.getElementById("cOut");
    this.ctxOut=this.cOut.getContext("2d");
    var self=this;
    this.v2.addEventListener("playing", function() {
      self.width=self.v2.videoWidth;
      self.height=self.v2.videoHeight;
      cIn.width=self.v2.videoWidth;
      cIn.height=self.v2.videoHeight;
      cOut.width=self.v2.videoWidth;
      cOut.height=self.v2.videoHeight;
      self.timerCallback();
    }, false);
  },
  pixelScan: function() {
    var frame = this.ctxIn.getImageData(0,0,this.width,this.height);
    for(var i=0; i<frame.data.length;i+=4) {
      var grayscale=frame.data[i]*.3+frame.data[i+1]*.59+frame.data[i+2]*.11;
      frame.data[i]=grayscale;
      frame.data[i+1]=grayscale;
      frame.data[i+2]=grayscale;
    }
    this.ctxOut.putImageData(frame,0,0);
    return;
  }
}

http://coreytegeler.com/ethan/

任何和所有帮助将不胜感激!谢谢!

最佳答案

原因 1

尝试调整您的计时器,避免将 0 作为超时值:

setTimeout(function() {
      self.timerCallback();
}, 34);

34 毫秒就足够了,因为视频帧速率通常不会超过 30 FPS (NTSC) 或 25 FPS (PAL),即 1000/30。如果您使用 0,您可能会堆积调用,这意味着浏览器将忙于清空事件队列。

如果您使用低于 33-34 毫秒的任何东西,您最终会将同一帧处理两次或更多次,这当然是不必要的(您的视频实际上是 29.97 FPS/NTSC,因此您可能需要考虑保持 34 毫秒)。

原因2

视频分辨率也是全高清 (1920x1080),这对于 canvas 和 JS 实时处理来说有点过分(对于典型的消费类计算机)。尝试减小视频大小,以便普通规范的计算机能够处理数据。

原因3(部分)

您不需要两张屏幕 Canvas ,甚至不需要一个屏幕视频。尝试动态创建这些标签,而不是将它们插入到 DOM 中。在屏幕上使用单个 Canvas 并将结果绘制到该 Canvas (您可以将 ImageData 从一个 Canvas 放到另一个 Canvas )。

原因4(部分)

理想情况下,将 setTimeout 替换为 requestAnimationFrame 方法,因为这会显着提高同步性和效率。您可以实现切换以将 FPS 降低到例如 30,因为您不需要对每一帧处理两次(引用 30 FPS 视频帧速率)。

更新

要动态创建这些元素(引用原因 3),您可以这样做:

var canvas = document.createElement('canvas'),
    video = document.createElement('video'),
    ctx = canvas.getContext('2d');

video.preload = 'auto';
video.addEventListener('canplay', start, false);

if (video.canPlayType('video/mp4')) {
    video.src = 'videoUrl.mp4';

} else if ...etc.

然后当视频加载了足够的数据(在元数据或 canplay 上)时,您将屏幕外(和屏幕上) Canvas 元素设置为视频的大小:

canvas.width = video.videoWidth;
canvas.height = video.videoHeight;

然后在播放时处理它的缓冲区并复制到您之前定义的屏幕 Canvas 上。

没有有屏幕外 Canvas - 我只是在您使用的原始代码中以及在 Canvas IIRC 中进出 Canvas 时提到这一点。您可以简单地使用单个屏幕 Canvas 和屏幕外视频并将视频帧绘制到 Canvas ,对其进行处理并将处理后的数据放回。在这种情况下应该也能正常工作。

关于javascript - HTML5 视频到 Canvas 播放速度很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21197707/

相关文章:

javascript - 检索 JSON 不适用于 AngularJS 和 GSON

javascript - jqGrid - 执行操作之前的模式窗口

javascript - 页面加载时布局中断

javascript - 将水平 html 表转换为垂直

带有引导覆盖内容的 HTML5 背景视频

javascript - YouTube 模态静态

javascript - 在 jQuery 中获取滚轮数量

javascript - 模块构建失败 : ReferenceError: window is not defined

jquery - 动画结束时如何创建事件?

actionscript-3 - 如何无缝循环FLV