anuragsimgeker
anuragsimgeker

Reputation: 23

HTML5 Video Loop Never Hits 100 Percent Duration

I'm trying to fire an event when video playback has reached 100%.

When the video is not looped, I get (currentTime/duration * 100 === 100) as true. When the video is on loop, I never get 100.

Any suggestions?

JSFiddle Link Here

Here's the HTML.

<h3>Without Loop</h3>

<div>Current: <span id="console2"></span></div>
<div>Has hit 100%: <span id="hundredIsTrue2" class="red">No</span></div>
<video id="video2" autoplay>
    <source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
    <source src="http://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg" />
</video>

<h3>With Loop</h3>

<div>Current: <span id="console"></span></div>
<div>Has hit 100%: <span id="hundredIsTrue" class="red">No</span></div>
<video id="video" autoplay loop>
    <source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
    <source src="http://www.w3schools.com/html/mov_bbb.ogg" type="video/ogg" />
</video>

Here's the JavaScript.

var video = document.getElementById('video'),
    console = document.getElementById('console'),
    hundred = document.getElementById('hundredIsTrue'),
    video2 = document.getElementById('video2'),
    console2 = document.getElementById('console2'),
    hundred2 = document.getElementById('hundredIsTrue2');

    video.addEventListener('timeupdate', function (e) {
        console.innerHTML = e.target.currentTime / e.target.duration * 100;

        if (e.target.currentTime / e.target.duration * 100 === 100) {
            hundred.className = 'green';
            hundred.innerHTML = 'Yes';
        }
    });

    video2.addEventListener('timeupdate', function (e) {
        console2.innerHTML = e.target.currentTime / e.target.duration * 100;

        if (e.target.currentTime / e.target.duration * 100 === 100) {
            hundred2.className = 'green';
            hundred2.innerHTML = 'Yes';
        }
    });

Here's the CSS.

.red {
    background-color: red;
}
.green {
    background-color: green;
}

Upvotes: 0

Views: 230

Answers (2)

brianchirls
brianchirls

Reputation: 7853

The timeupdate event does not actually run on every frame. It runs approximately every 250ms or 1/4 second. So it looks like what's happening here is that the last timeupdate event fires at less than 250ms before the end of the video and then the video ends and starts over back at the beginning before there's a chance for another timeupdate event to fire. So the next timeupdate event that fires will report currentTime at or close to zero.

So if you want to have your video automatically loop, there's a few things you can do to detect the end. One option is to look for a time that's sufficiently close, like maybe 0.5 second before the end. Another option is to wait for the seeked event, which should fire as the video ends and seeks back to zero, but that won't be helpful if you also allow the user to manually seek around the video.

A third option is to disable automatic looping and listen for the ended event. ended fires when the video gets to the end, but only if the loop property/attribute is not enabled. When you receive the event, you can fire your event, set currentTime back to 0 and call .play() again.

Upvotes: 0

Gaurav S
Gaurav S

Reputation: 1009

The calculated value moves from the 90s back to 0 without hitting the exact value 100. Would something like the below help? There is a possiblity of the value not hitting 99 either. Setting a smaller value like '95' might work for what you want to achieve.

if (e.target.currentTime / e.target.duration * 100 > 99) {
        hundred.className = 'green';
        hundred.innerHTML = 'Yes';
    }

Upvotes: 0

Related Questions