带有循环功能的<video>元素无法在Chrome或Firefox中无缝循环播放视频

Jak*_*ake 9 html javascript video firefox google-chrome

<video width="640" height="360" src="http://jakelauer.com/fireplace.mp4" autoplay loop muted/>
Run Code Online (Sandbox Code Playgroud)

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

IE9做得不错.是否有任何建议可以克服这个问题?在像这样的视频中非常明显,应该无缝循环,但有一个恼人的跳过/暂停.

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

小智 15

问题似乎与Chrome和FF如何填充预加载缓冲区有关.在这两种情况下,它们似乎忽略了循环标志并从开始"重置"缓冲区意味着在这种情况下缓冲区被清空并在视频开始时再次预加载导致轻微的延迟/跳转.

IE似乎考虑了循环标志并继续填充到最后.

这意味着要让这种外观变得无缝是很难的.我在几个小时内尝试了几种技术,包括将第一帧预先缓存到15帧的屏幕外画布.我最接近无缝的是修改视频中有两个段(我不(不再)有能力的硬件所以我需要减少尺寸以及测试 - 见小提琴).

但是,这里也有缺点:

  • 该视频是双倍长度
  • 您需要同时播放两个实例
  • 发生同一视频的两次下载
  • 滞后补偿因计算机而异
  • 未来的浏览器更新可能会影响结果的好坏.

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

我建议扩展我上面提到的,预先循环一些段.这样可以减少故障.

但是,分享我在这里所做的事情.

首先,我使用额外的段扩展了视频(并缩小了尺寸以在我的计算机上运行它):

首映

然后我使用以下代码进行重叠循环.那是:

  • 我同时开始播放视频,但是中间有一个视频.
  • 显示当前=>中的视频
  • 我使用canvas元素将视频绘制到
  • 当结束时,切换当前视频,以便新视频仍然是从中间播放的视频

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

代码如下所示:

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

我们还为视频1设置了一个新位置.当视频移动并准备好时,会引发一个事件,因此我们从那一点开始所有事情:

v1.addEventListener('canplay', init, false);
v2.addEventListener('canplay', init, false);
v1.addEventListener('timeupdate', go, false);
Run Code Online (Sandbox Code Playgroud)

处理程序:

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();
}
Run Code Online (Sandbox Code Playgroud)

lag值是为了补偿两个视频之间的差异,因为它们不是在完全相同的时间开始.

主要的代码draw只是取决于主视频(位置在视频之间切换v1) -帧速率也降低为30 fps,以减少开销drawImagerequestAnimationFrame运行优化以60fps(这里的视频是每秒30帧,所以我们只需要每隔一段时间画一帧):

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);
}
Run Code Online (Sandbox Code Playgroud)

现在,使用画布还可以打开其他可能性,例如在两个视频之间进行交叉淡入淡出以进一步平滑过渡.我没有实现这个,因为它超出了范围(大小/宽度),但值得一提的是,因为这本身就是一个解决方案.

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

唯一可以正常工作的解决方案是内部浏览器驱动,因为您需要访问缓冲区才能完全无缝地执行此操作.

我的"解决方案"实质上是在说:忘了!它不适用于这些浏览器,而是使用重复的循环视频.:-)