Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent HTML5 videos from downloading the files on mobile - videojs

So I'm currently building a website that has a carousel containing four videos, each video is triggered to play by hooking in to the Bootstrap 3 carousel's slide.bs.carousel event.

Each of the videos are embedded in the page like so:

<video id="somevideo" class="video-js vjs-default-skin m-hide" controls preload="auto" data-setup='{ "controls": false, "autoplay": false, "preload": "auto" }'>
  <source src="somevideo.mp4">
  <source src="somevideo.webmhd.webm">
</video>

Now, given the restrictions imposed particularly by Apple on the autoplaying and preloading of HTML5 videos (both are disabled and user interaction is required to trigger playback) I've decided to omit the videos for mobile & opt for static images instead. This is relatively simple, since all that's required to stop the video from overlaying the content is a media query that hides them.

That said, I'm finding it very difficult to prevent the videos from being downloaded and the overhead is massive.

For example, I have a script to check whether the user is currently visiting from a mobile device, as such, I've tried:

var check = false;
window.mobilecheck = function() {
    // Check for mobile here
    if (check === true) {
        // Device is mobile
        var videos = document.querySelectorAll('.video-js');
        for (var i = 0; i < videos.length; i++) {
            // videojs(videos[i]).destroy();
            videos[i].parentNode.removeChild(videos[i]);
        }
    }
}

This successfully removes the elements, but this has to be called on DOMReady which also means the resources already begin download.

How do I stop the videos from loading on mobile? I'd like to find a solution that uses VideoJS inherently preferably.

like image 420
gdgr Avatar asked Feb 19 '15 11:02

gdgr


3 Answers

Based on the suggestions Ian kindly made, here is my working solution.

Firstly, I changed each video's child source elements to have an attribute data-src like so:

<video id="my-id">    
   <source data-src="somevideo.mp4">
</video>

Then, after performing a mobile check using the script available at http://detectmobilebrowsers.com/ which I modified to include iPads etc (related SO answer here) I simply used the following script to automatically update the src attribute of each video (if we're on desktop in my case):

var sources = document.querySelectorAll('video#my-id source');
// Define the video object this source is contained inside
var video = document.querySelector('video#my-id');
for(var i = 0; i<sources.length;i++) {
  sources[i].setAttribute('src', sources[i].getAttribute('data-src'));
}
// If for some reason we do want to load the video after, for desktop as opposed to mobile (I'd imagine), use videojs API to load
video.load(); 

And that's it! Nothing loads on mobile devices anymore and I can have fairly granular control over the devices it will or won't load on.

Hope this helps somebody.

like image 139
gdgr Avatar answered Oct 16 '22 14:10

gdgr


One way you could do this is by setting the src attributes of your video element via JavaScript, and only doing so based on a media query (using matchMedia).

This would mean that the bulk of your code would have to move to JavaScript though.

For example, your HTML could be something like:

<video data-mp4="video.mp4" data-webm="video.webm" class="video-js" controls></video>

And then in your JavaScript (pseudo code here, not actual JS):

if (window.matchMedia("(min-width: 640px)").matches) {
   // do nothing
} else {
   var videos = document.querySelectorAll('.video-js'),
       videoFile;
   for (var i = 0; i < videos.length; i++) {
      // Choose video type
      if (video[i].canPlayType("video/mp4") === "probably") {
         videoFile = video[i].getAttribute("data-mp4");
      }
      // do the same check for WebM here...
      video[i].src = videoFile;
      // Call whatever reload or refresh method video.js has
      // for example...
      video[i].refresh();
   }
}

Something like that might work for you, although you might have to play around a bit with it.

like image 28
Ian Devlin Avatar answered Oct 16 '22 14:10

Ian Devlin


Based on Ian and GDGR's answers, I modified this to work for multiple videos.

<video class="mobile-no-load">    
    <source data-src="somevideo.mp4">
 </video>

if (window.innerWidth > 730) {   
    // get multiple videos
    var sources = document.querySelectorAll('video.mobile-no-load'); 
    // loop through the videos
    sources.forEach(function(source){ 
        // target the src attribute of the <source> element and set it to the data-src attribute
        source.childNodes[1].setAttribute('src', source.childNodes[1].getAttribute('data-src'))
    }); 
}
like image 43
Shapeshifter Avatar answered Oct 16 '22 15:10

Shapeshifter