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

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

IE9 做得不错。有什么方法可以克服这个问题吗?在像这样的视频中很明显应该无缝循环,但有一个烦人的跳过/暂停。

编辑:如您所见,如果我使用 javascript 来模拟循环,则会有一个可测量的滞后:http: //jsfiddle.net/bWqVf/13/

4

9 回答 9

15

这些问题似乎与 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根据主视频的位置在视频之间切换(每隔一段时间画一个框架):v1drawImagerequestAnimationFrame

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)。

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

我的“解决方案”本质上是说:算了!它在这些浏览器中不起作用,请改用重复循环的视频。:-)

于 2013-08-09T09:39:10.960 回答
3

我认为问题与浏览器特定的视频处理有关。

作为一个怪癖,您可以减少将视频转换为的延迟webm,但您应该将它放在mp4源之前,即:

<video width="640" height="360" autoplay loop muted>
    <source src="http://jakelauer.com/fireplace.webm" type="video/webm" />
    <source src="http://jakelauer.com/fireplace.mp4" type="video/mp4" /> 
</video>
于 2013-08-02T20:54:28.753 回答
1

赫里卡!

在我工作的地方,我们已经找到了解决这个问题的实际、真实、无变通的解决方案。它还通过多个开发人员解释了不一致的行为。

tl;dr 版本是:比特率。谁会猜到?我想,如果您使用 Adob​​e Media Encoder,许多人会为此使用标准值,通常是 10 Mbit/s 左右的高清视频。这还不够。正确的值是18 Mbit/s甚至更高。16还是有点卡。我无法表达这有多好。到目前为止,我已经尝试了大约五个小时的最混乱的解决方法,直到我和我们的视频编辑器一起找到了这个。

我希望这对每个人都有帮助,并为您节省大量时间!

我也希望我也可以在另一个线程中发布这个问题,但是关于这个问题有很多相同类型的问题,我想接触到很多人。

于 2018-04-18T09:10:52.713 回答
0

我认为您的问题与“代码相关”无关。它更多地与实际视频本身有关。如果您编辑视频以实现无缝循环,那就更好了。

看看这里,因为它会给你一些关于如何做的指导。

希望这对您有所帮助。

编辑:您可以尝试将视频分成两部分:介绍和循环部分。为每个元素制作一个 <video> 元素并将它们放置在同一个位置,隐藏第二个视频。在介绍中设置“结束”事件以换出显示并开始第二个视频。然后,您可以在第二个视频元素上设置循环属性。

只要您preload至少具有循环视频的属性,就可以让两个视频无缝地一起播放,这应该没有问题。

如果这不起作用,请尝试使用相同的循环视频制作两个视频元素。当一个正在播放时,您可以隐藏另一个并将其 currentTime 设置回零,因此当没有人在看时,任何搜索延迟都会发生。

如果上述方法都不适合您,那么您可以尝试使用 javascript 的其他方式。请注意,我尚未测试以下代码。它的作用是从第 2 秒开始播放视频,当视频到达第 4 秒时,它将再次开始播放(从第 2 秒开始)。

function playVideo() {
    var starttime = 2;  // start at 2 seconds
    var endtime = 4;    // stop at 4 seconds

    var video = document.getElementById('player1');

    //handler should be bound first
    video.addEventListener("timeupdate", function() {
       if (this.currentTime >= endtime) {
            this.play();
        }
    }, false);

    //suppose that video src has been already set properly
    video.load();
    video.play();    //must call this otherwise can't seek on some browsers, e.g. Firefox 4
    try {
        video.currentTime = starttime;
    } catch (ex) {
        //handle exceptions here
    }
}
于 2013-08-05T01:03:57.020 回答
0

对我有用的解决方案(并且不需要大量的 JavaScript)类似于:

var video = document.getElementById('background-video');
var loopPoint = 15; // s

function resetVideo() {
  if (video.currentTime >= loopPoint) {
    video.currentTime = 0;
  }
}
video.addEventListener('timeupdate', resetVideo);

不幸的是,我猜这非常昂贵,因为每次视频/音频更新时它都会使用回调。

于 2015-09-18T22:53:34.633 回答
0

这个问题发生在我使用带有 Electron 的 Chromium 包装器上。无论如何,我离解决问题更近了(还不够接近)。以下是改进循环到从提示点 A 到 B 的近乎无缝跳回的事项列表:

  1. 仅包含关键帧的 mp4 视频是关键(稍微增加了视频大小)
  2. 获得一个对帧率敏感的循环。这个小工具在使用关键帧和时间码时很有帮助:http: //x3technologygroup.github.io/VideoFrameDocs/#!/documentation/ FrameRates

(3。只有在 1 和 2 中的事情没有帮助时才需要最后一件事。我已经用 XmlHTTPrequest 加载了整个视频以完全填充缓冲区。)

var xhr = new XMLHttpRequest();
xhr.open('GET', '../assets/video/Comp1.mp4', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {

  if (this.status == 0) { // I used chromium and electron, usually status == 200 !
    var myBlob = this.response;
    var vid = URL.createObjectURL(myBlob);
    // myBlob is now the blob that the object URL pointed to.
    var v = document.getElementById("video");
    v.src = vid;
    // not needed if autoplay is set for the video element
    v.play();
    // This requires the VideoFrame-tool (see Nr. 2.)
    var videoFrame = new VideoFrame({
      id: 'v',
      frameRate: 25, // ! must match your video frame rate
      callback: function(response) {
        // I jump from fram 146 to 72 
        if (videoFrame.get() === 146) {
          // now, jump! Dealbreaker is that the seek is stopping the video
          // and the few ms to play it again bugger up the experience. 
          // Any improvements welcome!
          videoFrame.seekBackward(71, function() {
            v.play();
          });

        }
      }
    });

    videoFrame.listen('frame', 25);

    v1.play();

  }
}

xhr.send(null);

我遇到此代码的唯一问题是搜索停止了视频并且需要再次触发 play()。这会导致一个故障,我通过在我想要跳转到的实际提示点之前返回 3 帧来解决这个故障。

如果在具有不同视频的不同硬件上使用这仍然不准确,但也许它会让您更接近解决方案——我也是!:)

于 2015-09-22T21:42:25.020 回答
-2

问题是什么。

起始幻灯片和结束幻灯片不同。如果两张幻灯片相同,则循环看起来很好。由于仅这些幻灯片中的不匹配,它看起来像是在几秒钟内暂停。避免这些事情并尝试一下。

于 2013-08-05T09:52:12.680 回答
-2

仔细检查下面jsFiddle的 URL 我添加了 console.log 并跟踪视频标签事件,如播放、暂停、结束等,我签入了窗口 chrome 版本 28(我的工作循环没有火暂停事件)

http://jsfiddle.net/bWqVf/6/

于 2013-08-06T12:52:44.780 回答
-2

好的......经过多次试验和错误,这最终对我有用。在我看来,视频在结束后没有更新,所以我只是在播放结束后再次提醒它所有属性。

myVid.setAttribute('src', "videos/clip1.mp4");
myVid.autoplay = true;  
myVid.addEventListener('ended', vidEnded);  

function vidEnded()
{
    myVid.setAttribute('src', "videos/clip1.mp4");
    myVid.autoplay = true;          
}
于 2013-12-26T20:28:55.283 回答