20

I created a new page especially to test the API. When copy pasting their example with

<div id="player"></div>

and

 var player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
      height: '390',
      width: '640',
      videoId: 'M7lc1UVf-VE',
      events: {
        'onReady': onPlayerReady,
        'onStateChange': onPlayerStateChange
      }
    });
  }

Everything works.

Now when I remove the <div id="player"></div> and instead replace it with

 <iframe id="player" type="text/html" width="640" height="390" src="http://www.youtube.com/embed/GuVq-TZ7AJM?enablejsapi=1" frameborder="0"></iframe>

It no longer works. It never goes in the onPlayerReady or onPlayerStateChange. The weird thing is it was working last night and today it isn't. I have attached my full code in case it may help.

<!DOCTYPE html>
<html>
  <body>
    <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
    <iframe id="player" type="text/html" width="640" height="390" src="http://www.youtube.com/embed/GuVq-TZ7AJM?enablejsapi=1" frameborder="0"></iframe>


    <script>
      // 2. This code loads the IFrame Player API code asynchronously.
      var tag = document.createElement('script');

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

      // 3. This function creates an <iframe> (and YouTube player)
      //    after the API code downloads.
      var player;
      function onYouTubeIframeAPIReady() {

        player = new YT.Player('player', {
          events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
          }
        });
      }

      // 4. The API will call this function when the video player is ready.
      function onPlayerReady(event) {
        alert('test');
        event.target.playVideo();
      }

      // 5. The API calls this function when the player's state changes.
      //    The function indicates that when playing a video (state=1),
      //    the player should play for six seconds and then stop.
      var done = false;
      function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.PLAYING && !done) {
          setTimeout(stopVideo, 6000);
          done = true;
        }
      }
      function stopVideo() {
        player.stopVideo();
      }
    </script>
  </body>
</html>
Zane Shelby
  • 338
  • 2
  • 4
Melonheadjr44
  • 223
  • 1
  • 2
  • 6
  • I recently had this issue and none of the answers worked for me. My problem was that I had created multiple `YT.Player`:s for the same iframe, and apparently only the first `YT.Player` will actually work while the others just fail silently. They don't fire any events and they lack all the `playVideo()`, `pauseVideo()` etc methods. – powerbuoy Mar 24 '20 at 17:17
  • Hi @powerbuoy, did you solve the issue? It's happening something similar to me. I have 3 videos, each one on its own `iframe`, and I've created a `YT.Player` instance for each video. If the page loads normally, all of them constructs the instances properly and fire the events (`onReady`, `onStateChange`), but if during the loading something stops the JS execution for some reason (a breakpoint for example), only the first instance is constructed properly and fires the events, the others just became a kind of `YT.Player` instances, but without the methods (`playVideo()`...) and not firing events – Bernat Oct 24 '22 at 17:27

3 Answers3

19

Per issue 5670:

A quick fix is to add in the origin=http://www.example.com (replace with your servers full domain; make sure you use http:// or https:// as appropriate for your site) to the src= attribute of the player's iframe element. Please make sure that the origin= attribute's value exactly matches the host domain and URL scheme. E.g.

<iframe
  type="text/html"
  width="640"
  height="480"
  src="https://www.youtube.com/embed/VIDEO_ID?enablejsapi=1&origin=https://www.example.com"
  frameborder="0">
</iframe>
Zane Shelby
  • 338
  • 2
  • 4
  • 3
    This still does not work for me in FF. It works fine in Chrome and Safari, but in FF the readyState and the stateChanges do not fire. I've tried everything I could. I finally ended up by creating an empty DIV and initialising the `YT.Player` directly there – Raul Rene Oct 28 '14 at 13:44
5

A fix was finally posted: https://code.google.com/p/gdata-issues/issues/detail?id=5670#c6

Here is a direct quote of the answer at the link above:

A quick fix is to add in the origin=http://www.example.com (replace with your servers full domain; make sure you use http:// or https:// as appropriate for your site) to the src= attribute of the player's iframe element. Please make sure that the origin= attribute's value exactly matches the host domain and URL scheme. E.g.

<iframe
  type="text/html"
  width="640"
  height="480"
  src="https://www.youtube.com/embed/VIDEO_ID?enablejsapi=1&origin=https://www.example.com"
  frameborder="0">
</iframe>

I'm currently working with the engineering team to figure out whether origin= is going to be required moving forward or whether this new requirement can be reverted, but this is the immediate fix. Apologies for the breakage and lack of advanced communication in the meantime.

If you use the YT.Player() constructor to create the iframe element for you then this isn't be an issue—it's a bit of an edge case for developers who are explicitly including the iframe element as part of their page's HTML.

I implemented the fix above, and it worked for me.

Dave Romsey
  • 509
  • 6
  • 20
3

Also experienced this issue in one of our apps earlier today, I believe it's as a result of some internal changes / code push in youtube. Something similar happened in June c.f YouTube iframe player API - OnStateChange not firing

I resolved my issue by replacing

<iframe id="ytplayer" ... src="http://www.youtube.com/embed/wQ78D6zoVKo"></iframe>

with

<div id="ytplayer"></div>

thus letting the js script replace the div.

The clue was in your questions, so thanks.

Community
  • 1
  • 1
io2
  • 131
  • 3
  • 1
    Glad it worked for you. I unfortunately cannot have the js script replace the div since it will be done in WordPress – Melonheadjr44 Dec 10 '13 at 18:30
  • This isn't working for me. I already had:
    – chow Dec 10 '13 at 18:54
  • 3
    I'm thinking that @io2 is correct that this is an internal YouTube API issue and that we didn't all collectively just lose our minds today :) Here is a link to the issue on the bug tracker: https://code.google.com/p/gdata-issues/issues/detail?id=5672&q=onReady&colspec=API%20ID%20Type%20Status%20Priority%20Stars%20Summary – Dave Romsey Dec 10 '13 at 19:28