Jquery HTML5画布在更改正在设置动画的精灵表时挂起(逐帧视频播放)

Jquery HTML5画布在更改正在设置动画的精灵表时挂起(逐帧视频播放),jquery,html,mobile,video,Jquery,Html,Mobile,Video,我需要在使用HTML5的移动设备上播放具有透明背景的视频。在Windows Phone上,我可以捕获视频标签的当前帧并在画布中显示。但这在Android和iOS设备上不起作用(我认为是出于安全原因?) 我的解决方案是使用FFMPEG分割.flv,然后将这些帧缝合成大图像,如sprite表单 问题是,当我切换到新的帧表时,动画“挂起”。我只是通过控制台(通过在更改当前sprite工作表行时记录)直观地检查了这一点。我通过查看它在更改sprite工作表时是如何挂起的,以及在反复循环同一工作表时它是如

我需要在使用HTML5的移动设备上播放具有透明背景的视频。在Windows Phone上,我可以捕获视频标签的当前帧并在画布中显示。但这在Android和iOS设备上不起作用(我认为是出于安全原因?)

我的解决方案是使用FFMPEG分割.flv,然后将这些帧缝合成大图像,如sprite表单

问题是,当我切换到新的帧表时,动画“挂起”。我只是通过控制台(通过在更改当前sprite工作表行时记录)直观地检查了这一点。我通过查看它在更改sprite工作表时是如何挂起的,以及在反复循环同一工作表时它是如何不挂起的来测试这一点

我在手之前预加载所有图像:

var frameImages = [];

for(var i = 0; i < 35; i++)
{
  frameImages.push(new Image());
  frameImages[i].src = 'frame' + i + '.png';

  console.log(frameImages[i].src);

  frameImages[i].onload = function()
  {
    // Notify us that it's been loaded.
    console.log("Image loaded");
  }
}
我在ChromeV23.0.1271.97M的Win7机器和Nexus7上用Chrome试过

请在此处查看它的实际操作:
-这是在使用mozAnimationStartTime
和-这是使用常规JS计时器,每个步骤都会进行调整(从)

有什么想法吗?这个问题清楚吗

谢谢,
凯文很酷的代码。为什么不能使用视频标签(见选项6)?无论如何,我将列出我能想到的问题,并希望它能帮助您:

  • ++
    更改为
    +=1
    :与以前的代码保持一致,并且可能有助于消除javascript代码中的故障

  • 你把一堆图像拼接成一张“精灵纸”。然后,当您要转到下一张工作表时,代码将挂起。因此,由于您的代码尚未运行,作为测试,请删除在每个帧的子图像中循环的所有循环,然后在每次渲染时直接将frameImages数组中的每个帧输出到画布,以查看它是否仍然挂起。这样做的结果将让您知道您的代码是否可以到达frameImages中的下一帧,或者是否不能。这可能会使您更接近bug的来源

  • currentFrame是否在processFrame的范围内用var声明?如果没有,就放
    var currentFrame=0您定义
    函数processFrame(…

  • 当您说“然后我像这样播放”时,在所有onload启动后,您是否使用或等效地调用动画开始函数? 一种方法是:您可以在每次触发的onload中增加一个计数器,每次检查计数器是否等于所需的加载总数,然后才调用动画开始。 我的直觉是,这是一个缓存问题,因为由于内部结构不同,不同浏览器之间的差异似乎最大。

  • 尝试在drawImage调用之间和更新currentFrame时清除画布,因为这可能有助于在更改图像时重置画布的内部状态

  • 你可以用HTML5视频标签做alpha和transparency。只需使用一些svg转换。这些都很容易做到,就像它在中所说的那样


  • 这里还有另一个不太传统的解决方案——使用视频作为画布输入,并使用getImageData将每个帧显示为绿色

    基本上你有你的视频标签和画布

    <video id='source' style='display: none;'>
       <source>whatever.mp4</source>
       <source>whatever.ogg</source>
    </video>
    <canvas id='screen' width='videoWidth' height='videoHeight></canvas>
    
    你的画框函数是

    function drawFrame(){
       var ctx = document.getElementById('screen').getContext('2d'),
           vid = document.getElementById('source');
    
       ctx.drawImage(vid, 0, 0);
       var tolerance = 0.2,
           bgColor = [0, 255, 0], //or whatever 
           imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height),
           len = imageData.data.length;
    
       for (var i=0; i<len; i+=4){
          var r = imageData.data[i],
              g = imageData.data[i+1],
              b = imageData.data[i+2];
    
          //There's lots of different color comparing methods, just check google
          var dif = colorCompare([r, g, b], bgColor);
          if (dif < tolerance){
             imageData.data[i+3] = 255;
          }
       }
    
       ctx.putImageData(imageData, 0, 0);
    }
    
    函数drawFrame(){
    var ctx=document.getElementById('screen').getContext('2d'),
    vid=document.getElementById('source');
    ctx.drawImage(vid,0,0);
    var公差=0.2,
    bgColor=[0,255,0],//或其他任何东西
    imageData=ctx.getImageData(0,0,ctx.canvas.width,ctx.canvas.height),
    len=imageData.data.length;
    
    对于(var i=0;i不确定您是否已经看过了……但是您是否考虑过使用jquery队列?当我将它加载到浏览器中时,我看到一些帧没有显示,或者空白,然后返回,等等。我以前使用队列对我想要“链接”的ajax调用进行同步处理以特定的顺序组合在一起……因此,这可能是一个区域,您可以尝试以同步方式加载每个“图片帧”,确保每个帧以正确的顺序加载


    对客户来说,这似乎已经足够好了。我的意思是,如果这对业务造成了伤害,那么为此向他付费的人不会一直向他付费。他的业务在增长,而不是萎缩。最重要的是,你必须记住观众。我们对技术非常满意,我们这一代人也一样。业务我的客户通常都是年龄较大的观众,他们对技术不太熟悉。有时甚至会让他们感到难以承受。有人在网站上与他们交谈,可能会让他们更舒服,更容易消化信息。再说一遍,这不关我的事。我在Chrome中也可以使用,但只有在加载完所有内容后才能使用帧,因此您可能希望延迟动画,直到所有精灵完全加载。不确定您是否在其他浏览器中进行过任何调试,但我在Firefox中看到动画延迟(声音不同步)我看不到动画,也听不到Opera中的声音。它在IE8中不起作用,但这是意料之中的LOL。也许可以为非HTML5兼容的IE浏览器使用背景声音,并确保不在那里调用不受支持的函数?不过,我可以预见视频+音频同步问题。到目前为止做得不错!!!;)只是一个离题的观察,但演讲者的底部几乎没有移动(没有双关语)我认为这可能会节省带宽。动画的下半部分在演示者“进入”时只是一帧一帧地不同,然后她只是在手移动时轻微摇晃。我意识到这意味着许多额外的工作可能没有被要求,也可能没有付费,但可能节省了大约40%的带宽这实际上只需要在安卓和iOS设备上运行,客户端已经可以运行了
    var t = null;
    document.getElementById('source').addEventListener('playing', function(){
       var vid = this;   
       t = setInterval(function(){
           if (vid.paused || vid.ended){
              clearInterval(t);
              return
           } else {
              drawFrame();
           }
       }, 20)
    }, false)
    
    function drawFrame(){
       var ctx = document.getElementById('screen').getContext('2d'),
           vid = document.getElementById('source');
    
       ctx.drawImage(vid, 0, 0);
       var tolerance = 0.2,
           bgColor = [0, 255, 0], //or whatever 
           imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height),
           len = imageData.data.length;
    
       for (var i=0; i<len; i+=4){
          var r = imageData.data[i],
              g = imageData.data[i+1],
              b = imageData.data[i+2];
    
          //There's lots of different color comparing methods, just check google
          var dif = colorCompare([r, g, b], bgColor);
          if (dif < tolerance){
             imageData.data[i+3] = 255;
          }
       }
    
       ctx.putImageData(imageData, 0, 0);
    }