HTML5 video full preload in javascript
Solution 1
canplaythrough
is the event that should fire when enough data has downloaded to play without buffering.
From the Opera teams excellent (although maybe very slightly dated now) resource Everything you need to know about HTML5 video and audio
If the load is successful, whether using the src attribute or using source elements, then as data is being downloaded, progress events are fired. When enough data has been loaded to determine the video's dimensions and duration, a
loadedmetadata
event is fired. When enough data has been loaded to render a frame, theloadeddata
event is fired. When enugh data has been loaded to be able to play a little bit of the video, acanplay
event is fired. When the browser determines that it can play through the whole video without stopping for downloading more data, acanplaythrough
event is fired; this is also when the video starts playing if it has a autoplay attribute.
'canplaythrough' support matrix available here: https://caniuse.com/mdn-api_htmlmediaelement_canplaythrough_event
You can get around the support limitations by binding the load
element to the same function, as it will trigger on those.
Solution 2
This will load the entire video in JavaScript
var r = new XMLHttpRequest();
r.onload = function() {
myVid.src = URL.createObjectURL(r.response);
myVid.play();
};
if (myVid.canPlayType('video/mp4;codecs="avc1.42E01E, mp4a.40.2"')) {
r.open("GET", "slide.mp4");
}
else {
r.open("GET", "slide.webm");
}
r.responseType = "blob";
r.send();
Solution 3
- Download the video using fetch
- Convert the response to a blob
- Create an object URL from the blob (e.g. blob:http://localhost:8080/df3c4336-2d9f-4ba9-9714-2e9e6b2b8888)
async function preloadVideo(src) {
const res = await fetch(src);
const blob = await res.blob();
return URL.createObjectURL(blob);
}
Usage:
const video = document.createElement("video");
video.src = await preloadVideo("https://example.com/video.mp4");
Solution 4
Hope this could help you
var xhrReq = new XMLHttpRequest();
xhrReq.open('GET', 'yourVideoSrc', true);
xhrReq.responseType = 'blob';
xhrReq.onload = function() {
if (this.status === 200) {
var vid = URL.createObjectURL(this.response);
video.src = vid;
}
}
xhrReq.onerror = function() {
console.log('err' ,arguments);
}
xhrReq.onprogress = function(e){
if(e.lengthComputable) {
var percentComplete = ((e.loaded/e.total)*100|0) + '%';
console.log('progress: ', percentComplete);
}
}
xhrReq.send();
and then , if your video src has another domain ,you have to handle CORS .
Solution 5
So far the most trustable solution we found was to play it and wait for the buffer to be fully loaded.
Which means if the video is long, you will have to wait for almost all the video length.
That isn't cool, i know.
Wondering if someone has figured out some other magically reliable way of doing it ( ideally using something like PreloadJS which automatically falls back to flash when HTML5 video isn't supported ).
Alex
Updated on July 22, 2021Comments
-
Alex almost 3 years
I have a high quality video which I cannot compress too much as it's going to be the base of a lot of image analysis whereby each frame will be redrawn into the canvas and then manipulated.
I'm trying to preload the whole thing before playing it as I can't have the video stop, buffer and continue. Is there an event which I can listen for which signifies that the whole video has preloaded before I commence playback?
Here's how I'm doing it in JS/jQuery:
this.canvas = this.el.find("canvas")[0]; this.video = this.el.find("video")[0]; this.ctx = this.canvas.getContext("2d"); this.video.autoplay = false; this.video.addEventListener("play",this.draw) this.video.addEventListener("timeupdate",this.draw) this.video.addeventlistener("ended",this.trigger("complete",this))
-
Alex about 12 yearsis this fully supported though?
-
Simon West about 12 yearsKnowing the half arsed way most of the HTML5 video spec has been implemented by the major vendors, probably not.
-
Placeable over 10 yearsThanks for this. One note though, Safari browsers doesn't execute the "canplaythrough" event. So you should use "canplay" instead which it does fire. But it seems a bit random the only event that ALWAYS fire is "loadeddata" on Safari.
-
kroe almost 10 yearsthat should do it! i still didn't test, but that is exactly what i was looking for. thanks a lot.
-
kroe almost 10 years"canplaythrough" doesn't really solve my issue. and i'm not sure how to put your question as the accepeted
-
Marco Kerwitz over 9 years@kroe Just click on the tick next to this answer.
-
Volker E. over 9 yearsThe link to areweplayingyet isn't working any more, have you already implemented a working version via
load
event on iOS devices? -
Dr.Knowitall almost 9 yearsCanplaythrough is a myth. It doesn't work at all, especially in firefox.
-
chadkouse over 8 yearsSeems like my video player still only takes a certain percentage of the download before pausing it. In my case it preloads about 38-40% and then waits for the video to start playing, then it trickles the rest of the file in. Is there a workaround to download the whole file?
-
jacobsgriffith over 8 yearsThis method for sure downloads the entire video in JavaScript. Check your network traffic using fiddler or the network tab in chrome to make sure. All else fails use some library like jplayer or popcorn.org or videojs
-
Marius over 8 yearsThis works really well, thanks! I was afraid there would be data url upper limits -- looking around, people say that data urls should be used only with small files. But using your approach, I've been preloading ~100MB videos and it works reliably in chrome.
-
supersan almost 5 yearsthis should be the accepted answer.. the top answer is wrong because it doesn't really answer the original question
-
plafer over 2 yearsThis is not preloading. This only fetches it from a remote server to the disk. "Preloading" refers to when a video (or image) is loaded in memory.
-
Enijar over 2 yearsThis satisfies the constraints of the author's question. Whilst this is not technically "preloading", it will load the video into a blob (stored on the user's machine for the lifetime of the page), and prevent the issue of video buffering or stopping.
-
alsotang about 2 yearsThis method is awesome!! It download the whole video, and nothing would be downloaded while playing or seeking.