17

I have a dynamic video gallery and it works great on a computer. When moving to an iPad, the video starts loading and it shows the cannot play icon. Instead of this I'd rather the video not show until it's ready to play. I have tried to add events listeners for "canplaythrough" and "canplay" and when they occur for the video to fade in then play. Does the iPad not support these events?

new_video = document.createElement('video');
new_video.setAttribute('class', 'none');
new_video.setAttribute('width', '568');
new_video.setAttribute('height', '269');
new_video.setAttribute('id', 'video'+video_num);
current_video.insertBefore(new_video, video_controls);
new_video.load();
new_video.addEventListener('canplaythrough', function() {
     $('#video'+video_num').fadeIn(100);
     new_video.play();
});
mrollinsiv
  • 371
  • 2
  • 4
  • 6
  • 2
    What codec does your video use? Safari and Firefox differ on the video codec that they both support. (though hopefully Google is about to change that) – Earlz May 25 '10 at 21:39
  • reliable video on the iPad is the most unimaginable mess - the sheer number of workarounds I've had to come up with amazes me – Simon_Weaver Oct 02 '14 at 03:11

8 Answers8

7

The way to solve this visual problem is to hide the video element until it is ready to be played. Note that you cannot set display:none (video won't load if you do that) and visibility:hidden won't solve the issue either.

To fix it, wrap the video element on a DIV with overflow:hidden and set -webkit-transform:translateX(1024px) (a number high enough to push the video outside the screen).

Than you have to listen for the canplay or canplaythrough or load events (based on your need) and set the translateX to zero after that.

Miller Medeiros
  • 1,256
  • 14
  • 12
  • 1
    Two things that aren't directly related with the answer: - Instead of changing the opacity of the video it is usually a better approach to change the opacity of an overlay on top of the video element. (opacity doesn't work on video elements on Google Chrome if GPU acceleration isn't enabled) - Avoid using `setAttribute`, use DOM properties instead: `video.id`, `video.className`, `video.width`, etc.. – Miller Medeiros Mar 29 '11 at 04:16
4

On the iPad it will not load the video until a user starts an event this is by design of apple to prevent iPhone or iPad users from burning up their data plans. So you will not be able to do what you want sorry.

Check out this link and look for the Device-Specific Considerations section for some info. But it will not start loading data so it couldn't fire the canplaythrough event until a user touches it.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Jeff Beck
  • 3,944
  • 3
  • 28
  • 45
  • right I get that, so what happens is I call new_video.load(); after the user clicks on a video. After that I attach the event listeners. This in theory should work since once the user clicks the video, it calls loading then it adds all of the event listeners. – mrollinsiv Jun 04 '10 at 15:58
  • After you call load then the user clicks the video it will start playing as soon as it can. I don't think the events will fire in such a way that will allow you to fade in the video. – Jeff Beck Jun 04 '10 at 18:53
  • This answer appears to be correct - I get the canplay and canplaythrough events only once the user has clicked on the video. – James Westgate Jan 29 '13 at 12:29
  • You can use loadstart on the ipad so that you know that the video is at least loading and capable of playing. – James Westgate Jan 29 '13 at 12:43
1

Realize this is an old issue, but if anyone else stumbles across this, I encountered a similar problem.

Looking at the events dispatched by the video element, it looks like the iPad will start loading the video, then almost immediately suspend it (appears to be simultaneous with the first 'progress' event).

It will not fire the "canplay" or "canplaythrough" events until after playback has actually begun, so you must listen to one of the 3 events that do fire before playback begins:

  • loadstart
  • progress
  • suspend

I would change your handler to 'loadstart' and give that a shot.

yenemy
  • 41
  • 2
1

Check to see if the browser can play the video before you attempt to load it:

function canPlayVorbis() {
    var v = document.createElement('video');
    return !!(v.canPlayType && v.canPlayType('video/ogg; codecs="theora, vorbis"').replace(/no/, ''));
}

function canPlayMP4() {
    var v = document.createElement('video');
    return !!(v.canPlayType && v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''));
}

function canPlayWebM() {
    var v = document.createElement('video');
    return !!(v.canPlayType && v.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, ''));
}

Taken from Dive Into HTML5 Appendix A.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
robertc
  • 74,533
  • 18
  • 193
  • 177
  • unfortunately thats not the problem. The iPad supports h.264 video and thats the video I'm loading. The problem is that when video is loading it shows the cannot play sign until enough has loaded. I want to hide this video element all together until it's ready to be played all the way through – mrollinsiv Jun 01 '10 at 22:00
  • In that case maybe you need to hide the element somehow and query the ready state (no idea how well supported it is): http://dev.w3.org/html5/spec/video.html#the-ready-states – robertc Jun 01 '10 at 23:22
1

automatically starts player on the ipad/iphone:

function fakeClick(fn) {
    var $a = $('<a href="#" id="fakeClick"></a>');

    $a.bind("click", function(e) {
        e.preventDefault();
        fn();
    });

    $("body").append($a);

    var evt,
        el = $("#fakeClick").get(0);

        if (document.createEvent) {
            evt = document.createEvent("MouseEvents");
            if (evt.initMouseEvent) {
                evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                el.dispatchEvent(evt);
            }
        }

        $(el).remove();
} 

$(function() {
    var video = $("#mobileVideo").get(0);

    fakeClick(function() {
        video.play();
    });
});
superjos
  • 12,189
  • 6
  • 89
  • 134
Ryan Weiss
  • 1,308
  • 1
  • 14
  • 36
  • 3
    Just tested it. Doesn't work anymore, [allegedly since iOS 4.X](http://stackoverflow.com/questions/3009888/autoplay-audio-files-on-an-ipad-with-html5/3056220#3056220). – feklee Aug 20 '11 at 10:12
1

the problem seems to be dynamically creating the video object - that somehow breaks the code on the iPad. I wrote a video player that moves the alreay present video element into an container and immediately the video stops working. no problem on other systems though... guess you gotta find a way to have the video element already in place and then add all your other code above and below it....

Jörn Berkefeld
  • 2,540
  • 20
  • 31
0

Here's a GREAT place to get familiar with HTML5 events.

http://www.w3.org/2010/05/video/mediaevents.html

Tyguy7
  • 17
  • 1
0

This is possibly why your MP4 video won't play until it's fully loaded: how to get your HTML5 MP4 video to play before being fully loaded. Worth a shot anyway.

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