这些问题似乎与 Chrome 和 FF 如何填充预加载缓冲区有关。在这两种情况下,他们似乎都忽略了循环标志并从开始时“重置”缓冲区,这意味着在最后缓冲区被清空并在视频开始导致轻微延迟/跳转时再次预加载。
IE 似乎考虑了循环标志并继续填充到最后。
这意味着很难让这看起来无缝。我在几个小时内尝试了几种技术,包括将第一帧预缓存到 15 帧屏幕外画布。我最接近无缝的方法是修改视频以在其中包含两个片段(我没有(不再)有功能强大的硬件,所以我需要减小尺寸以及测试 - 见小提琴)。
但是,这里也有缺点:
- 视频是双倍长度
- 您需要同时玩两个实例
- 同一视频的两次下载发生
- 延迟补偿因计算机而异
- 未来的浏览器更新可能会影响结果的好坏。
换句话说 - 没有解决这些浏览器问题的稳定解决方案。
我建议对上面提到的内容进行扩展,以预循环某些片段。这样可以减少故障。
但是,要分享我在这里所做的事情。
首先,我用一个额外的片段扩展了视频(并缩小了尺寸以在我的计算机上运行它):
然后我用下面的代码做了一个重叠循环。那是:
- 我同时开始播放视频,但从中间开始播放一个视频。
- 显示当前 => 中间的视频
- 我使用画布元素将视频绘制到
- 结束时切换当前视频,以便新视频仍然是从中间播放的视频
这里的理论是,这将掩盖您在开始时遇到的故障,因为视频播放总是在中间(从第二段开始)。
代码如下所示:
由于视频是异步加载的,我们需要计算负载,因为这种技术使用两个视频实例,并且浏览器似乎无法共享下载。
我们还为视频 1 设置了一个新位置,使其位于中间。当视频被移动并准备好时,会为此引发一个事件,所以我们从那一点开始:
v1.addEventListener('canplay', init, false);
v2.addEventListener('canplay', init, false);
v1.addEventListener('timeupdate', go, false);
处理程序:
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();
}
该lag
值是为了补偿两个视频之间的差异,因为它们不是在完全相同的时间开始的。
主代码只是draw
根据主视频的位置在视频之间切换(每隔一段时间画一个框架):v1
drawImage
requestAnimationFrame
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);
}
现在,使用画布还开辟了其他可能性,例如在两个视频之间进行交叉淡入淡出以进一步平滑过渡。我没有实现它,因为它超出了范围(在大小/广度上),但值得一提的是,这本身就是一个解决方案。
无论如何 - 如前所述,这是一个有很多缺点的解决方案,但它是我能减少故障的最接近的解决方案(使用 Chrome)。
唯一可以正常工作的解决方案是内部浏览器驱动的解决方案,因为您需要访问缓冲区才能完全无缝地执行此操作。
我的“解决方案”本质上是说:算了!它在这些浏览器中不起作用,请改用重复循环的视频。:-)