I need to detect when a video file has completed loading. I\'m thinking I should use progress->buffer, but in the back of my mind, I remember reading that this was unreliabl
Here's a fleshed out implementation with Google's MDC-Web's mdc-linear-progress UI component.
var doc = document;
var bufferLengthDetector;
var linearProgress;
var mdc = window.mdc;
mdc.autoInit();
var video = doc.querySelector('video');
if(doc.getElementById("footer-progress")){
linearProgress = mdc.linearProgress.MDCLinearProgress.attachTo(doc.getElementById("footer-progress"));
}
if(video){
video.addEventListener('timeupdate', function() {
var percent = Math.floor((100 / video.duration) * video.currentTime);
linearProgress.progress = percent/100;
}, false);
video.addEventListener('progress', function() {
var duration = video.duration;
if (duration > 0) {
bufferLengthDetector = setInterval(readBuffer, 500);
}
});
}
function readBuffer(){
var percent = video.buffered.end(video.buffered.length - 1) / video.duration;
if (percent >= .9) {
linearProgress.buffer = 1;
clearInterval(bufferLengthDetector);
}
else {
linearProgress.buffer = percent;
}
}
html {
height:100%;
}
body{
margin: 0;
}
#footer-progress{
position: fixed;
bottom: 0;
width: 100%;
visibility: visible;
opacity: 1;
}
video {
position: fixed;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
z-index: -100;
transform: translateX(-50%) translateY(-50%);
background: #212121;
background-size: cover;
transition: visibility 1s, opacity 1s linear;
visibility: visible;
opacity: 1;
}
<head>
<link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
</head>
<body>
<video class="bg-video" playsinline autoplay>
<source src="//rack.pub/media/do-not.webm" type="video/webm">
<source src="//rack.pub/media/do-not.mp4" type="video/mp4">
I'm sorry your browser doesn't support HTML5 video in WebM with VP8/VP9 or MP4 with H.264.
</video>
<div role="progressbar" class="mdc-linear-progress" data-buffer="true" id="footer-progress">
<div class="mdc-linear-progress__buffering-dots"></div>
<div class="mdc-linear-progress__buffer"></div>
<div class="mdc-linear-progress__bar mdc-linear-progress__primary-bar">
<span class="mdc-linear-progress__bar-inner"></span>
</div>
<div class="mdc-linear-progress__bar mdc-linear-progress__secondary-bar">
<span class="mdc-linear-progress__bar-inner"></span>
</div>
</div>
</body>
I've had the same problem and use a timer attached to the progress event. It's a hack but I haven't seen any other ways of doing this. (I've tested this on Chome 10 - Windows).
var video = document.getElementById('#example-video-element');
var timer = 0;
video.addEventListener('progress', function (e) {
if (this.buffered.length > 0) {
if (timer != 0) {
clearTimeout(timer);
}
timer = setTimeout(function () {
if(parseInt(video.buffered.end() / video.duration * 100) == 100) {
// video has loaded....
};
}, 1500);
}
}, false);
This looks like the type of approach you were thinking of taking, but figured I would post an example for those anonymous users who might be looking for a quick code sample =p
GJ
You can bind the "buffered" event, but (in Chrome at least) this works fine except that it doesn't call the last "buffered" event (i.e. it will detect 90%...94%...98%... but won't call on 100%).
Note: recent versions of jQuery should use .prop() instead of .attr()
To get around this I've used setInterval() to check the buffer every 500ms (where $html5Video is your <video>
element:
var videoDuration = $html5Video.attr('duration');
var updateProgressBar = function(){
if ($html5Video.attr('readyState')) {
var buffered = $html5Video.attr("buffered").end(0);
var percent = 100 * buffered / videoDuration;
//Your code here
//If finished buffering buffering quit calling it
if (buffered >= videoDuration) {
clearInterval(this.watchBuffer);
}
}
};
var watchBuffer = setInterval(updateProgressBar, 500);