javascript 播放完整的 HTML5 视频,然后循环播放其中的一部分

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21251979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 20:28:20  来源:igfitidea点击:

Play full HTML5 video and then loop a section of it

javascripthtmlvideo

提问by WeNeigh

I'm trying to play an 8.6 second video once completely, and then loop a small section of the video infinitely, to keep the illusion of a never-ending video. So far I've looked into the media fragments URI, and the endedevent of the video. Setting the currentTime attribute in the ended event listener works, but it makes the video "blink".

我试图完全播放一次 8.6 秒的视频,然后无限循环播放视频的一小部分,以保持视频永无止境的错觉。到目前为止,我已经研究了媒体片段 URI和视频的结束事件。在结束的事件侦听器中设置 currentTime 属性有效,但它会使视频“闪烁”。

At present, I'm using a timeupdate event listener to change the time when the video is approaching the end [shown below]

目前我正在使用timeupdate事件监听器来改变视频接近尾声的时间【如下图】

elem.addEventListener('timeupdate', function () {
if (elem.currentTime >= 8.5) {
    elem.currentTime = 5;
    elem.play();
}
}, false);

JSFiddle here

JSFiddle在这里

This works as well, but the video pauses visibly before restarting at 5 seconds. Is there a smoother way of playing the video once and then looping a segment of it?

这也有效,但视频在 5 秒重新启动之前明显暂停。有没有一种更流畅的方式来播放视频然后循环播放一段视频?

回答by Max

Try the following, to 'rewind' it as soon as it ends:

尝试以下操作,在它结束后立即“倒带”它:

vidElem.addEventListener("ended", function () {
        vidElem.currentTime = 2.5;
        vidElem.play();
}, false);

Updated fiddle: http://jsfiddle.net/Lt4n7/1/

更新小提琴:http: //jsfiddle.net/Lt4n7/1/

回答by Random

I just had to deal with the same problem and noticed the same issues with flickering. Here was my solution:

我只需要处理同样的问题,并注意到闪烁的相同问题。这是我的解决方案:

  • Get 2 videos (or sets of videos) - one for the non-looped section, the other for the looped section
  • Create 2 video elements
  • set the looping element to 'display:none'
  • 获取 2 个视频(或视频集)——一个用于非循环部分,另一个用于循环部分
  • 创建 2 个视频元素
  • 将循环元素设置为 'display:none'

Then just capture the ended event and swap display status (example uses jquery but you could use 'style.display="none/block"' just as easily:

然后只需捕获结束的事件并交换显示状态(示例使用 jquery,但您可以轻松地使用 'style.display="none/block"' :

VideoPlayer1 = document.getElementById('video1');
VideoPlayer2 = document.getElementById('video2');
VideoPlayer1.addEventListener('ended', videoLooper, false);

function videoLooper()
{
    VideoPlayer2.play();
    $(VideoPlayer2).show();
    $(VideoPlayer1).hide();
}

回答by Tremours

Your code is fine, the problem is with your MP4 file! Try using a much smaller video like this one ( http://www.w3schools.com/tags/movie.mp4) to confirm the issue is not with your code.

您的代码很好,问题出在您的 MP4 文件上!尝试使用像这样的小得多的视频 ( http://www.w3schools.com/tags/movie.mp4) 来确认问题不在于您的代码。

So how can you achieve the same result but with large videos files? You will need two video files:

那么如何在大视频文件中实现相同的结果呢?您将需要两个视频文件:

  • video1 is the main video
  • video2 is the looping video
  • video1 是主视频
  • video2 是循环视频

Remember: HTML5 video has no problem playing and looping large video files so we will use this method to play the videos.

请记住:HTML5 视频播放和循环播放大型视频文件没有问题,因此我们将使用此方法播放视频。

In the example below we will play the first video and when it finishes we will execute a function to hide video1 and then show/play video2. (Video 2 is already set to loop)

在下面的示例中,我们将播放第一个视频,当它完成时,我们将执行一个函数来隐藏 video1,然后显示/播放 video2。(视频 2 已设置为循环播放)

Don't forget to load JQuery in your head otherwise this will not work.

不要忘记在您的脑海中加载 JQuery,否则这将不起作用。

<video id="video1" width="1080" height="568" poster="movie.png" autoplay onended="run()">
  <source src="movie.webm" type="video/webm">
  <source src="movie.ogg" type="video/ogg">
  <source src="movie.mp4" type="video/mp4">
  <object data="movie.mp4" width="1080" height="568">
    <embed width="1080" height="568" src="movie.swf">
  </object>
Optional test to be displayed if the browser doesn't support the video tag (HTML 5)
</video>


<video id="video2" width="1080" height="568" poster="loop.png" loop>
  <source src="loop.webm" type="video/webm">
  <source src="loop.ogg" type="video/ogg">
  <source src="loop.mp4" type="video/mp4">
  <object data="loop.mp4" width="1080" height="568">
    <embed width="1080" height="568" src="loop.swf">
  </object>
Optional test to be displayed if the browser doesn't support the video tag (HTML 5)
</video>


<script> 
$( "#video2" ).hide();
function run(){
   $( "#video1" ).hide();
    $( "#video2" ).show();
    document.getElementById("video2").play();
   };
</script> 

回答by fregante

You can't solve this issue in javascript. That delay you see depends on the video compression and the hardware.

您无法在 javascript 中解决此问题。您看到的延迟取决于视频压缩和硬件。

To start playing at a time that is not 0, the video decoder has to go back and find a key frameand then build the current frame by reading everything between the last key frame and your chosen time.

要在非 0 的时间开始播放,视频解码器必须返回并找到一个关键帧,然后通过读取最后一个关键帧和您选择的时间之间的所有内容来构建当前帧。

I'm not an expert in video compression, but maybe there is a way to pick these key frames and place them exactly where you need them. I don't think it will be easy and smooth, though.

我不是视频压缩方面的专家,但也许有一种方法可以选择这些关键帧并将它们准确放置在您需要的位置。不过,我认为这不会容易和顺利。



If you're looking for an easier solution, use @Random's, but it uses two <video>tags to work around this limit.

如果您正在寻找更简单的解决方案,请使用@Random's,但它使用两个<video>标签来解决此限制。

回答by dxpkumar

var iterations = 1;
var flag = false;
document.getElementById('iteration').innerText = iterations;
var myVideo = document.getElementById('video-background');
myVideo.addEventListener('ended', function() {
  alert('end');
  if (iterations < 2) {
    this.currentTime = 0;
    this.play();
    iterations++;
    document.getElementById('iteration').innerText = iterations;
  } else {
    flag = true;
    this.play();
  }
}, false);
myVideo.addEventListener('timeupdate', function() {
  if (flag == true) {
    console.log(this.currentTime);
    if (this.currentTime > 5.5) {
      console.log(this.currentTime);
      this.pause();
    }
  }
}, false);
<div>Iteration: <span id="iteration"></span></div>

<video id="video-background" autoplay="" muted="" controls>
            <source src="https://res.cloudinary.com/video/upload/ac_none,q_60/bgvid.mp4" type="video/mp4">
    </video>
<div>Iteration: <span id="iteration"></span></div>

// Please note that loop attribute should not be there in video element in order for the 'ended' event to work in ie and firefox

// 请注意,循环属性不应出现在视频元素中,以便“结束”事件在 ie 和 firefox 中工作