10

I've got some YouTube embedding code (I will paste only code which is causing the trouble for me and cut things which are not public):

console.log(ytplayer);
ytplayer.playVideo();

Console.log on Chrome and on FF shows me good objects with correct methods, and method playVideo() exists there. And it works for all other browsers I checked, but it doesn't work on FF!? What is even more interesting, that when I play video using normal YouTube play button then I can use pauseVideo() method (and all the others: seeking, controlling volume), but I can't use playVideo() method...

I use new way of embedding video:

ytplayer = new YT.Player(player, {
        height: height,
        width: width,
        videoId: videoid,
        allowfullscreen: 'true',
        playerVars: {
            controls: 0,
            showinfo: 0,
            wmode: 'opaque',
            autoplay: (autoplay ? 1 : 0)
        },
        events: {
            'onReady': function () {
                console.log('I am ready');
            }
        }
    });

Of course 'I am ready' is in console output. I have no idea what I do wrong and why only FF is not working... There is no JS error, and no clue... Hope someone had this problem before and got it resolved!:)

Karol
  • 7,803
  • 9
  • 49
  • 67
  • `There is no JS error, and no clue` only the link to the problem page could help others to identify the problem, not just your words. – Cheery Feb 15 '12 at 04:11
  • 1
    Maybe you are right @Cheery, but I can't post you link because project I'm working on is commerial, and must be private until release... sorry! By "There is no JS error, and no clue" I mean, that everything in console output is the same for both: Chrome and FF, and for FF it doesn't work. Also there is no error and warning. – Karol Feb 15 '12 at 04:45
  • `Also there is no error and warning.` And moreover it requires 'experiments' and not 'theoretical thoughts'. – Cheery Feb 15 '12 at 04:48

4 Answers4

11

I was having a very similar issue and was struggling with an answer. My calls to playVideo() didn't seem to work.

ORIGINAL:

$('#play_movie').click(function(){
    $('#video').show();
    if(player)
    {
        if(typeof player.playVideo == 'function')
        {
            player.playVideo();
        }
    }

The issue was that the player was not yet available - if I just gave it a bit of time to show up, then the call worked

$('#play_movie').click(function(){
    $('#video').show();
    if(player)
    {
        var fn = function(){ player.playVideo(); }
        setTimeout(fn, 1000);
    }

Don't know if this is your exact issue, but I hope it helps someone

orangeale
  • 169
  • 1
  • 4
  • It can be a solution for some cases. – Karol Jun 27 '12 at 07:57
  • 3
    There is an 'onReady' event that is triggered by the player, not the 'onYouTubeIframeAPIReady', you could use that, it seems more correct. – Aldo Reyes Jul 26 '12 at 21:42
  • The `playVideo()` method was working for me in Chrome, but failed in FF and IE. IE reported an error that the object didn't support the method. Once I added the timeout, it worked like a charm. Thanks! – gtr1971 Feb 13 '13 at 18:58
  • 1
    This was not my issue. It was simply that autoplay doesn't work since in newer browsers it is now disabled for stuff that looks like ads. Which an embedded video might. So the user will have to click play on the video before you can use it. – odinho - Velmont May 19 '20 at 06:19
9

A more robust way to do that is to check if the player is ready. If the player is not ready, queue player.playVideo() and execute it when it is ready using the onReady event. Gist

var playerConfig = {},                 // Define the player config here
    queue = {                          // To queue a function and invoke when player is ready
      content: null,
      push: function(fn) {
        this.content = fn;
      },
      pop: function() {
        this.content.call();
        this.content = null;
      }
    },
    player;

window.onYouTubeIframeAPIReady = function() {
  player = new YT.Player('player', {
    videoId: 'player',
    playerVars: playerConfig,
    events: {
      onReady: onPlayerReady
    }
  });
};

// API event: when the player is ready, call the function in the queue
function onPlayerReady() {
  if (queue.content) queue.pop();
}

// Helper function to check if the player is ready
function isPlayerReady(player) {
  return player && typeof player.playVideo === 'function';
}

// Instead of calling player.playVideo() directly, 
// using this function to play the video. 
// If the player is not ready, queue player.playVideo() and invoke it when the player is ready
function playVideo(player) {
  isPlayerReady(player) ? player.playVideo() : queue.push(function() {
                                               player.playVideo();
                                             });
} 
Yujun Wu
  • 2,992
  • 11
  • 40
  • 56
  • I like this approach too. Never thought this way - neat and robust as you said. – Karol Aug 28 '14 at 00:44
  • Should be accepted answer! If I had to complain about your semantics, I'd say your queue is not really a queue (confusing with push/pop), but what you're doing is really quite good. – Ryan Taylor Sep 24 '15 at 23:19
  • Just came across this. Out of curiosity, where or how does the user defined `playVideo()` get called? – Tony M Oct 09 '18 at 22:43
1

I came across this post looking for something similar. I found my answer here, by relic180:

YouTube API - Firefox/IE return error "X is not a function" for any 'player.' request

Basically, Chrome can initialize youtube embeds even when the divs are hidden (i.e. display:none), but FF and IE can't. My solution was a variant of relic180's:

I move my player to left:200% or whatever when I want it invisible but getting initialized (and available for other calls to player), then move it back on screen when I need it.

Community
  • 1
  • 1
Symbolic
  • 693
  • 5
  • 10
0

I personally found on preset IFrames, that the API won't work properly if you wouldn't use https://www.youtube.com as the domain. So be careful not to miss on the "www". Otherwise the API will create the player object but will fail to execute methods.

a_f
  • 36
  • 2