25

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.

gdgr
  • 1,435
  • 2
  • 15
  • 31
  • 1
    It's worth noting that on Chrome v43.02357.93 for android I've noticed that with a video hidden via media queries does not download at all. I've tested this via chromes debug tools in the network tab. Whether this is just a Chrome thing or not I cannot say, and the solutions provided are still good techniques to use. – Novocaine Jun 15 '15 at 14:50
  • 1
    If video has src, it will be downloaded, CSS can not change it. – ViliusL Oct 28 '21 at 08:53

3 Answers3

33

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.

Community
  • 1
  • 1
gdgr
  • 1,435
  • 2
  • 15
  • 31
  • 3
    Glad what I wrote helped. The question now is, which one should be marked as the answer, mine - which put you on the right path, or your own answer? ;-) – Ian Devlin Feb 20 '15 at 07:52
  • 3
    I was pondering over that! Technically speaking my answer is the correct answer to the question, and it's code that will work as opposed to pseudo. In the interest of being nice, I'll let you decide :) – gdgr Feb 20 '15 at 16:59
  • 2
    Argh, that's harsh as now I can't be mean when you are being nice, so assign yours as the answer :-p – Ian Devlin Feb 21 '15 at 12:51
  • 2
    Nice, a diplomatic exchange online! – gdgr Feb 21 '15 at 13:05
  • I'm having a problem with this solution. It copies the src URL well enough, but the video doesn't start downloading. I'm wondering if it's because my video has no controls - it's supposed to autoplay. – user1269310 Jul 10 '15 at 16:16
  • Hey I just updated my answer to hopefully help you out there. I gather you're wanting to do this on desktop right? Otherwise it would seem to defeat the original objective of doing this! – gdgr Jul 11 '15 at 16:44
  • I like this solution better for checking for mobile: https://coderwall.com/p/i817wa/one-line-function-to-detect-mobile-devices-with-javascript – Mattijs Jun 09 '19 at 14:23
  • @Mattijs That uses window.orientation which is deprecated - https://developer.mozilla.org/en-US/docs/Web/API/Window/orientation#Browser_compatibility – rmcsharry Nov 10 '19 at 16:27
23

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.

Ian Devlin
  • 18,534
  • 6
  • 55
  • 73
1

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 && 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'))
    }); 
}