如何使用JavaScript缓冲/预加载HTML5视频

3
我正在运行以下代码,它在每个视频结束时更改html5视频的源,以便它不断播放一个视频接着另一个视频。第一个视频播放完后,它会播放第二个视频,然后是第三个视频,最终从头开始,形成无限循环。它还选择了一个随机起点,但这对我的问题不重要。
在下面的代码中,您只会找到两个视频源,但最终代码将使用大约十个左右。
我的问题是,在一个视频结束和下一个视频开始之间有一个小暂停。我已经将视频标签的背景颜色设置为红色,以便您可以看到每个视频播放之间的红色闪烁。
我猜这可以通过预加载javascript代码中指定的所有视频来解决。因此,当播放当前视频时,我想实现仅预加载javascript代码中指定的列表中的下一个视频。因此,当播放第5个视频时,它应该预加载第6个视频等。
或者这不是可以通过有效的缓冲/预加载来解决的问题吗?我也乐意听取任何其他建议。

var vidElement = document.getElementById('video');
    var vidSources = [
      "http://www.w3schools.com/html/mov_bbb.mp4",
      "http://www.w3schools.com/html/movie.mp4"
      ];
    var activeVideo = Math.floor((Math.random() * vidSources.length));
    vidElement.src = vidSources[activeVideo];
    vidElement.addEventListener('ended', function(e) {
      // update the active video index
      activeVideo = (++activeVideo) % vidSources.length;
      if(activeVideo === vidSources.length){
        activeVideo = 0;
      }

      // update the video source and play
      vidElement.src = vidSources[activeVideo];
      vidElement.play();
    });
video { background-color: red }
<video src="http://www.w3schools.com/html/mov_bbb.mp4" id="video" autoplay muted playsinline></video>
<p>(each video is just ~ 10 seconds)</p>


您是想预加载整个HTML5视频源还是只加载其中的一小部分? - Bharata
@Bharata 无论采用何种方法消除视频之间的红色闪光(小间隙)都可以。我猜测在播放之前预加载每个视频可以解决这个问题,但我不确定百分之百。 - Jascha Goltermann
1个回答

1
你可以使用 preload 属性创建 video 元素,并将其添加到包含 div 中,如下所示:

function initVideoElement(videoEl)
{
    videoEl.playsinline = true;
    videoEl.muted = false;
    videoEl.preload = 'auto'; //but do not set autoplay, because it deletes preload

    //loadedmetadata is wrong because if we use it then we get endless loop
    videoEl.onplaying = function(e)
    {
        if(++nextActiveVideo == 2)
            nextActiveVideo = 0;

        //replace the video elements against each other:
        if(this.inx == 0)
            nextVideoElement = videoElements[1];
        else
            nextVideoElement = videoElements[0];

        nextVideoElement.src = vidSources[nextActiveVideo];
        nextVideoElement.pause();
    };

    videoEl.onended = function(e)
    {
        this.style.display = 'none';
        nextVideoElement.style.display = 'block';
        nextVideoElement.play();
    };
}

var videoContainer = document.getElementById('videoContainer'),
    nextActiveVideo = 0,
    nextVideoElement,
    videoElements =
    [
        document.createElement('video'),
        document.createElement('video')
    ],
    vidSources =
    [
        "http://www.w3schools.com/html/mov_bbb.mp4",
        "http://www.w3schools.com/html/movie.mp4"
    ];

videoElements[0].inx = 0; //set index
videoElements[1].inx = 1;

initVideoElement(videoElements[0]);
initVideoElement(videoElements[1]);

videoElements[0].autoplay = true;
videoElements[0].src = vidSources[0];
videoContainer.appendChild(videoElements[0]);

videoElements[1].style.display = 'none';
videoContainer.appendChild(videoElements[1]);
video{background-color: red}
<div id="videoContainer"></div>


@JaschaGoltermann,你没有看到这个片段吗?我使用play()代替autoplay,它可以正常工作。或者有什么问题吗? - Bharata
是的,我看到了,但我需要一个可以与自动播放一起使用的解决方案。你能否创建一个使用自动播放的jsFiddle呢?我还在寻找其他解决方案,比如创建一个画布而不是类似于这个视频标签的东西:https://dev59.com/5VsX5IYBdhLWcg3wNtLA#34137680 - Jascha Goltermann
目前的解决方案中,当使用自动播放时,预加载并没有被有效地利用,因为它只能在下一个视频开始播放时才开始预加载...相反,它应该在当前视频仍在播放时就已经开始预加载。 - Jascha Goltermann
@JaschaGoltermann,你的jsfiddle示例是错误的,因为我写过,你必须在从 vidElement 创建后直接设置 autoplay。但是你已经在 createVideoElement() 中用 autoplay 替换了 preload。无论如何,我已经改变了我的代码,现在它应该像你需要的那样工作(希望如此)。 - Bharata
感谢您的努力!不幸的是,这个程序在短时间内会导致我的浏览器崩溃。我已经尝试了Chrome和Firefox。我需要检查另一台电脑以确定是否只有我遇到了这个问题... - Jascha Goltermann
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接