Youtube iframe api not triggering onYouTubeIframeAPIReady

65,268

Solution 1

It is not a timeout issue, and you should not need to fire this function manually.

Make sure your onYouTubeIframeAPIReady function is available at the global level, not nested (hidden away) within another function.

Solution 2

You can always append it to the window object to make sure it is evoked globally. This is helpful if your code is using amd.

window.onYouTubeIframeAPIReady = function() {}

Solution 3

If you have to put in inside to a function, one possible solution is instead of:

function onYouTubeIframeAPIReady() {
  // func body...
}

you can declare it like this:

window.onYouTubeIframeAPIReady = function() {
  // func body...
}

In this case make sure, that you insert the certain script to the dom after the declaration (the insertBefore() call what is in the global scope now in your case):

Solution 4

If you load the IFrame Player API code asynchronously as follows:

<script>
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
</script>

and you are also loading the script code like this:

<script src="http://www.youtube.com/player_api"></script>

then the function onYouTubeIframeAPIReady won't be called due to the same code is being loaded twice (the function is called just one time when the api is completely loaded).

So use just one of the ways according to your needs.

Solution 5

After revisiting this, I found a working solution for me when using webpack (or I assume any other commongJS module system), or if you find the youtube api is ready before your own JS file, was to use an interval - until youtube provides some form of promise callback:

var checkYT = setInterval(function () {
    if(YT.loaded){
        //...setup video here using YT.Player()

        clearInterval(checkYT);
    }
}, 100);

This seemed to be the most error-proof in my case.

Share:
65,268
jribeiro
Author by

jribeiro

Full Stack Web Developer driven by passion, innovation and creativity! I specialise in creating great web and mobile experiences for companies and creatives

Updated on July 09, 2022

Comments

  • jribeiro
    jribeiro almost 2 years

    I've been battling with the youtube iframe api for quite some time now. Somehow the method onYouTubeIframeAPIReady is not always triggered.

    From the symptoms it seems a loading problem. No errors are shown in the inspector.

    Here is my code:

    HTML

    <div id="player"></div>
              <script>
                videoId = 'someVideoId';
                var tag = document.createElement('script');
                tag.src = "//www.youtube.com/iframe_api";
                var firstScriptTag = document.getElementsByTagName('script')[0];
                firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
              </script>
    

    JS

    (called at the end of the page. I tried to place the code right after the above script and the result was the same.)

    var isReady = false
      , player
      , poster
      , video;
    
    $(function () {
    $('.js-play').click(function (e) {
        e.preventDefault();
        interval = setInterval(videoLoaded, 100);
      });
    });
    function onYouTubeIframeAPIReady() {
      console.log(videoId)
      player = new YT.Player('player', {
        height: '445',
        width: '810',
        videoId: videoId,
        events: {
          'onReady': onPlayerReady//,
          //'onStateChange': onPlayerStateChange
        }
      });
    }
    
    function onPlayerReady(event) {
      isReady = true;
      console.log("youtube says play")
    }
    
    function videoLoaded (){
      if (isReady) {
          console.log("ready and play")
          poster.hide();
          video.show();
    
          $('body').trigger('fluidvideos');
    
          player.playVideo();
          clearInterval(interval);
      } 
    }
    

    The problem is that sometimes nothing gets printed by the console.log and nothing happens.

    On mobile phones this happens all the time. Any ideas?

  • Don Boots
    Don Boots about 11 years
    This is wrong on every level. Even if we were waiting for the player to be ready, you would use setInterval.
  • Don Boots
    Don Boots about 11 years
    This is the correct solution, BY FAR. I had the same problem, but my function was in $(document).ready(). I moved it out and it worked.
  • r8n5n
    r8n5n about 11 years
    Voted down as this is not the correct solution. bcm's solution is the correct way to do this. ... 'Make sure your onYouTubeIframeAPIReady function is available at the global level, not nested (hidden away) within another function.'
  • DavidT
    DavidT over 9 years
    I know this is an old thread. For anyone else using requireJS this solution fixes the issue.
  • Augustin Riedinger
    Augustin Riedinger about 9 years
    Ain't there a custom event we could listen to instead of making the function available in the global scope? This feels really dirty! Something like $('document').on('youTubeIframeAPIReady', function(e){});...
  • Joel Balmer
    Joel Balmer over 8 years
    Oh my god... Thank you SO much for pointing this out. Couldn't figure out why it wasn't working.
  • Ben Swinburne
    Ben Swinburne almost 8 years
    @AugustinRiedinger did you find a suitable event to listen for?
  • Kodie Grantham
    Kodie Grantham over 7 years
    Helped me with Meteor and the YouTube Iframe API package as well.
  • Augustin Riedinger
    Augustin Riedinger over 7 years
    Not for now. Maybe a custom script: window.onYouTubeIframeAPIReady = function() { document.dispatchEvent(new CustomEvent('onYouTubeIframeAPIReady', {})) })
  • Yabsley
    Yabsley almost 6 years
    This answer fixed an issue for me with the onYouTubeIframeAPIReady function not being called on in Safari only. The function was already in the global scope and was working fine in Firefox and Chrome. Appending it to window fixed the issue in Safari.
  • GAV
    GAV almost 2 years
    Nice, Solved my issue when compiling in Yarn encore