<视频>元素循环不会在Chrome或Firefox中无缝循环播放视频 [英] <video> element with looping does not loop videos seamlessly in Chrome or Firefox

查看:391
本文介绍了<视频>元素循环不会在Chrome或Firefox中无缝循环播放视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 < video width =640height =360src =http://jakelauer.com/fireplace.mp4autoplay loop muted /> 

小提琴: http ://jsfiddle.net/bWqVf/



IE9做了一个体面的工作。有什么建议可以克服这个问题吗?这是非常明显的这样的视频,应该无缝循环,但有一个恼人的跳过/暂停。

编辑:
正如你所看到的,如果我使用JavaScript模拟循环,有一个可衡量的滞后: http://jsfiddle.net/bWqVf/13/

解决方案

这些问题似乎与Chrome和FF如何填充预加载缓冲区有关。在这两种情况下,他们似乎都忽略了循环标志,并且从开始意义上重置了缓冲区,在这种情况下,当视频开始时缓冲区被清空并重新预载,导致轻微的延迟/跳跃。 b
$ b

IE似乎考虑了循环标记,并继续填充到最后。

这意味着这将是非常困难的这看起来无缝。我花了几个小时尝试了几种技术,包括将第一帧预先缓存到15帧的屏幕画布。最接近我可以得到无缝修改视频有两个部分(我不(不再)具有能力的硬件,所以我需要减少维度以及测试 - 见小提琴)。
$ b

然而,这里也有缺点:$ b​​
$ b


  • 视频是双倍长度的

  • 您需要同时播放两个实例

  • 同一个视频的两次下载发生
  • 计算机到电脑
  • 未来的浏览器更新会影响结果的好坏。



换句话说 - 没有稳定的解决方案来解决这些浏览器的问题。



我会推荐一个我上面提到的扩展,预先循环一些段。这样你就可以减少毛病了。

然而,分享一下我在这里所做的一切。


首先我使用额外的段来扩展视频(并减少维度以便在我的电脑上运行):



然后我用下面的代码做一个重叠循环。那就是:


  • 我同时启动视频,而从中间开始播放一个视频。

  • 显示当前=>中间的视频

  • 我使用画布元素将视频拖到
  • 结束当前视频被切换,以便新视频仍然是从中间播放的视频



这里的理论是,这将掩盖你的故障开始时视频播放总是在中间(从第二段开始)。



代码如下所示:



由于视频加载异步,我们需要计算加载,因为这种技术使用两个视频实例,浏览器似乎无法共享下载。



我们也为视频1设置了一个新的位置。当视频被移动并准备就绪时,会发生一个事件,所以我们从这一点开始:

  v1.addEventListener(' canplay',init,false); 
v2.addEventListener('canplay',init,false);
v1.addEventListener('timeupdate',go,false);

处理程序:

 函数init(){
count--; /// = 2
///这两个视频都被加载,准备:
if(count === 0){
length = v1.duration;
mid =长度* 0.5;
current = mid;

///设置第一个视频的开始到中间
v1.currentTime = mid + lag;



函数go(){
///删除侦听器,或者每个frame都会调用
v1.removeEventListener 'timeupdate',go,false);
v1.play();
v2.play();
draw();

lag 值是试图补偿两个视频之间的差异,因为他们不是在同一时间开始。



主代码绘制根据主视频的位置( v1 )简单地在视频之间切换 - 帧速率也降低到30 fps,以减少开销 drawImage 作为 requestAnimationFrame 以60 fps运行最佳(这里的视频是30 fps,所以我们只需要画一个帧其他时间):

pre $ function draw(){

/// frame-rate from 60到30
if(reduce === true){
reduce = false;
requestAnimationFrame(draw);
return;
} else {
reduce = true;
}

///使用视频>> =中等时间
var v = v1.currentTime> = mid? v1:v2;

///在画布上绘制视频帧
ctx.drawImage(v,0,0);

requestAnimationFrame(draw);





$ b现在,使用canvas也可以打开其他的可能性,两个视频之间的淡入淡出以进一步平滑过渡。我没有实现这个,因为它在范围之外(大小/宽度),但值得一提的是,这可能是一个解决方案本身。



在任何情况下 - 如上所述,这是一个有很多缺点的解决方案,但它是我可以减少毛刺(使用Chrome)最接近的解决方案。



唯一可以正常工作的解决方案是一个内部浏览器驱动的,因为你需要访问缓冲区才能完全无缝地完成这个任务。



我的解决方案实际上是这样说的:忘掉它!它不会在这些浏览器中工作,而是使用重复的循环视频。 : - )

<video width="640" height="360" src="http://jakelauer.com/fireplace.mp4" autoplay loop muted/>

Fiddle here: http://jsfiddle.net/bWqVf/

IE9 does a decent job of it. Is there any recommendation for ways to overcome this? It is very obvious in videos like this one that SHOULD seamlessly loop, but have an annoying skip/pause.

EDIT: As you can see, if I use javascript to simulate the loop, there's a measurable lag: http://jsfiddle.net/bWqVf/13/

解决方案

The problems seem to be related to how both Chrome and FF fills the pre-load buffers. In both cases they seem to ignore the loop flag and "reset" the buffers from start meaning in that case that at the end the buffers are emptied and pre-loaded again when video starts causing a slight delay/jump.

IE seem to consider the loop flag and continue to fill also towards the end.

This means it's gonna be very hard to make this look seamless. I tried several techniques over a few hours including pre-caching the first frames to 15 frames off-screen canvases. The closest I could get to seamless was modifying the video to have two segments in it (I do not (no longer) have capable hardware so I needed to reduce the dimension as well to test - see fiddle).

However, there are drawbacks here as well:

  • The video is double length
  • You need to play two instances at the same time
  • Two downloads of the same video happens
  • Lag compensation will vary from computer to computer
  • Browser updates in the future can influence good/bad how the result will end up to be.

In other words - there is no stable solution to get around the problem with these browsers.

I would recommend an extension to what I mention above, to pre-loop some segments. This way you can reduce the glitch.

However, to share what I did here goes.

First I extended the video with an extra segment (and reduced the dimension to run it on my computer):

Then I used the following code to do an overlapping loop. That is:

  • I start the videos at the same time, but one video from the middle.
  • The video that is currently => middle is shown
  • I use a canvas element to draw the video onto
  • When at end the current video is switched so that the new video is still the one being played from the middle

The theory here is that this will mask the glitch you get at the start as the video playing is always in the middle (starting on the second segment).

The code looks like this:

As the videos are loaded async we need to count the loads as this technique uses two video instances and the browser seem to be unable to share the download.

We also set a new position for video 1 to be at the middle. An event is raised for this when video is moved and ready, so we start everything from that point:

v1.addEventListener('canplay', init, false);
v2.addEventListener('canplay', init, false);
v1.addEventListener('timeupdate', go, false);

Handlers:

function init() {
    count--; /// = 2
    /// both videos are loaded, prep:
    if (count === 0) {
        length = v1.duration;
        mid = length * 0.5;
        current = mid;

        /// set first video's start to middle
        v1.currentTime = mid + lag;
    }
}

function go() {
    /// remove listener or this will be called for each "frame"
    v1.removeEventListener('timeupdate', go, false);
    v1.play();
    v2.play();
    draw();
}

The lag value is an attempt to compensate for the difference between the two videos starting as they don't start at the exact same time.

The main code draw simply switches between the videos depending on the position of the main video (v1) - the frame rate is also reduce to 30 fps to reduce overhead of drawImage as requestAnimationFrame runs optimally at 60 fps (the video here is 30 fps so we only need to draw a frame every other time):

function draw() {

    /// reduce frame-rate from 60 to 30        
    if (reduce === true) {
        reduce = false;
        requestAnimationFrame(draw);
        return;
    } else {
        reduce = true;
    }

    /// use video that is >= middle time
    var v = v1.currentTime >= mid ? v1 : v2;

    /// draw video frame onto canvas
    ctx.drawImage(v, 0, 0);

    requestAnimationFrame(draw);
}

Now, using canvas opens up other possibilities as well such as making for example a cross-fade between the two videos to smooth the transition further. I didn't implement this as it is outside the scope (in size/broadness), but worth to mention as that could be a solution in itself.

In any case - as mentioned, this is a solution with many drawbacks but it is the closest I could get to reduce the glitch (using Chrome).

The only solution that can work properly is an internal browser driven one as you would need access to the buffers to be able to do this fully seamlessly.

My "solution" is in essence saying: forget it! It won't work in these browsers, use an repeated looped video instead. :-)

这篇关于&lt;视频&GT;元素循环不会在Chrome或Firefox中无缝循环播放视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆