1

I'm using [youtube api ][1] to get to know when a video is fully buffered player.getVideoLoadedFraction()

when the fraction is 1, the video is fully buffered, but I have to poll this function to check whether it is 1 and then get the time, like:

setInterval(display_fraction,1);

since a video could be tens of minutes.

Will this polling creates a heavy load on the browser/client and thus affect the video streaming? are there any other better polling methods or ways to detect when youtube finishes buffering?

BTW, the link for youtube api is: https://developers.google.com/youtube/flash_api_reference#Playback_controls

user1769686
  • 505
  • 2
  • 10
  • 16

2 Answers2

4

Humans start perceiving time intervals somewhere between a 20th and a 10th of a second, so trying to poll with a value of 1ms is neither necessary nor desireable (any modern browser will round that up to 5ms or 10ms anyway). Values like 50 or 100 would be more appropriate.

I would also strongly recommend using a chained series of setTimeout calls rather than a setInterval call, something like this:

function onVideoReady(callback) {

    // Do first check as soon as the JavaScript engine is available to do it
    setTimeout(checkVideoReady, 0);

    // Our check function
    function checkVideoReady() {
        if (videoIsReady) {
            // The video is ready, notify calling code
            callback();
        }
        else {
            // Not ready yet, wait a 10th of a second
            setTimeout(checkVideoReady, 100);
        }
    }
}

...which you then use like this:

onVideoReady(function() {
    // The video is ready, do something
});

The reasons I advocate a chained series of setTimeout instead of setInterval are:

  1. You can change the delay easily from iteration to iteration. For instance in the above, I fire the check as soon as possible the first time, then then after 100ms each subsequent time. You can do more complex things with timing than that, the flexibility is there.

  2. It's much, much harder to inadvertently end up with more than one running, since code has to explicitly trigger the next loop.

  3. setInterval varies amongst browsers about whether it measure the interface from the start of the last call or the end of it. If you use a pattern like the above, you're always sure it's from the end of the last check.

  4. If your code is still running when the next interval is meant to occur, it just gets skipped. This can cause gaps (e.g., if you're doing something every 100ms and your previous loop takes 102ms to complete, the next one doesn't start as soon as possible, it waits the remaining 98ms), at least on some browsers.

But it's up to you, of course, the above can be done just as easily with setInterval and clearInterval calls as with a chain of setTimeout calls.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Why setTimeout not setInterval btw? – Kos Nov 05 '12 at 12:08
  • 1
    @Kos: Updated the answer to address that. – T.J. Crowder Nov 05 '12 at 12:14
  • how about the heavy load? Will this polling creates a heavy load on the browser/client and thus affect the video streaming? – user1769686 Nov 05 '12 at 12:23
  • @user1769686: Not in and of itself, no. The browser doesn't care about doing a small thing 10 times a second (or 5 times a second, or twice a second, whatever you pick). Assuming the check for whether the video is fully-loaded isn't a big time-consuming operation, should be fine. Obviously, test on your target browsers and on an appropriate class of end-user machine to determine the best interval to use; your mileage may vary. – T.J. Crowder Nov 05 '12 at 12:25
  • 1
    BTW, why you use setTimeout(checkVideoReady, 0); for the first check, why not use checkVIdeoReady direclty? besides, the second setTimeout will change the Timeout=0 to Timeout=100? – user1769686 Nov 05 '12 at 12:49
  • @user1769686: Because the contract of `onVideoReady` is that it will call the callback *asynchronously* (the code following `onVideoReady` runs before the callback is called, reliably). If we called `checkVideoReady` immediately, *sometimes* `onVideoReady` would call the callback synchronously (the video is already ready) and other times it would call it asynchronously (if the video wasn't ready yet). That's the kind of thing that leads to bugs. Using `setTimeout(checkVideoReady, 0)` means we'll check almost right away, but asynchronously. – T.J. Crowder Nov 05 '12 at 12:56
  • @user1769686: Re your second question: The second `setTimeout` doesn't *change* anything, it just uses a different timeout for that particular call. – T.J. Crowder Nov 05 '12 at 12:57
1

An alternative to chained timeouts is chained Promises. The following implements periodic polling along with a timeout.

var Promise = require('bluebird');

/**
 * Periodically poll a signal function until either it returns true or    a timeout is reached.
 *
 * @param signal function that returns true when the polled operation is complete
 * @param interval time interval between polls in milliseconds
 * @param timeout period of time before giving up on polling
 * @returns true if the signal function returned true, false if the operation timed out
 */
function poll(signal, interval, timeout) {
    function pollRecursive() {
        return signal() ? Promise.resolve(true) : Promise.delay(interval).then(pollRecursive);
    }

    return pollRecursive()
        .cancellable()
        .timeout(timeout)
        .catch(Promise.TimeoutError, Promise.CancellationError,function () {
            return false;
        });
}

You call it like so.

poll(isVideoReady, pollingInterval, timeout).then(console.log);

See Javascript polling with promises.

W.P. McNeill
  • 16,336
  • 12
  • 75
  • 111