YouTube JS API Breaking Change? Will no longer ini

2019-08-28 17:49发布

To demonstrate the breaking change I discovered today I took the basic JS API sample page which can be found with link below and simply commented out the videoId parameter:

YT Sample Code demonstrating initialization error: http://www.multitask123.com/fmgem/YT_Sample2.htm

With said removal of videoId parameter the player will now display/initialize with the following error message in the embedded player, "An error occurred. Please try later." This was not the case until this afternoon.

For the past three months I could call onYouTubePlayerAPIReady as follows and there would be no error message:

function onYouTubePlayerAPIReady() {
        player = new YT.Player('player', {
            height: '390',
            width: '640',
            //videoId: 'JW5meKfy3fY', - COMMENTED OUT INTENTIONALLY! HARD REQUIREMENT!
            events: {
                'onReady': onPlayerReady,
                'onError': onPlayerError,
                'onStateChange': onPlayerStateChange
            }
        });
    }

The error is caught by the onPlayerError event handler during initialization and the error comes in with the "evt" parameter's data attribute. So onPlayerError(evt) is called on initialization and evt.data = 2. This value is documented as, "The request contains an invalid parameter value" which is clearly the API expecting a videoId.

I do not want to go into too much detail but I spent countless hours getting the initialization of the player to work just right as there are numerous cross browser initialization issues. I need to hide the player until I actually need it to play something.

I forget which browser is the culprit but one of them actually forces me to show the player even though no video is playing.

I discovered I cannot lazy load/JIT the embedded player because it loads asynchronously so if I try to only load it when my users wish to actually view a video or there are other parameters of the URL involved that will load a playlist for example the player will balk because I cannot BOTH initialize the player and ask it to play a video.

So the bottom line is the player NEEDS to be initialized when the page is loading but NOT with a videoId parameter because quite simply I have no idea what is going to be played in 90% of the circumstances and even if I did that would be the result of a different asynchronous call to a different API. I say this because the solution to initialize it with a videoid is unacceptable.

The YouTube API is amazing and I love it so much so that I have spent 18 months developing http://www.fmgem.com and now this breaking change is ruining the first impression beta users will have of my app. So if the YT API team does indeed monitor this please change it back. Pretty please with sugar on top. :))

Something similar happened a few weeks ago with the same function's wmode attribute on load.

//wmode: 'opaque' //--- causes wicked bug in Chrome - And I was able to change opaque to transparent so no biggie there but this would require me to review my entire architecture and methodically handle apx 9 different asynchronous use-cases for load that again, have all had cross-browser quirks.

So I cannot afford to be reactive and I have been forced to put in a "sneezing baby panda" videoId into the live code at http://www.fmgem.com but that looks quite unprofessional and it is merely a band-aid until I can review the entire architecture unless YT Team actually acknowledges this as a breaking change and then puts it back to its prior behavior.

This was detected by some users sometime during the afternoon of 2/27/2013 and I have read on google groups that YouTube's developers monitor SO.

Any answers, solutions, guidance or confirmation would be greatly appreciated.

Thanks!!

3条回答
Root(大扎)
2楼-- · 2019-08-28 18:33

You can initially load a blank 0 second movie. Or you can re-arrange your code a tad bit.

Do not call onYouTubePlayerAPIReady function yourself. Use flag variables instead:

var playerAPIReady;
var player;

Set the first variable when the API file calls onYouTubePlayerAPIReady function:

function onYouTubePlayerAPIReady() {
    playerAPIReady = true;
}

Set the second variable when the user chooses to play first video:

function createPlayerAndPlayVideo(id) {
    if(! playerAPIReady) {
        // player API file not loaded
        return;
    }
    if (! player) {
        player = new YT.Player('player', {
            height: '390',
            width: '640',
            videoId: id
            events: {
                'onReady': onPlayerReady,
                'onError': onPlayerError,
                'onStateChange': onPlayerStateChange
            }
        });
    } else {
        player.loadVideoById(id);
    }
}

Re-use the same player for subsequent videos as shown in the else block.

查看更多
forever°为你锁心
3楼-- · 2019-08-28 18:39

I'm not ruling out that something may have changed on Feb. 27, but the intention has always been that videoId (or a list id) is required when initializing an iframe Player. It isn't spelled out explicitly in the documentation, but at the same time, it never suggests that the parameter is optional, and all examples given do include a value for videoId.

So I wouldn't count on this behavior changing back in the future.

The most common thing to do when you have a YouTube iframe Player that you want to be initialized and not visible is to use CSS to set its position outside of the viewable area in the browser (such as by using negative x and y coordinates). You can initialize the player with whatever placeholder video you want, then call loadVideoById() when you're ready to play back a real video, and when you detect onStateChange with YT.PlayerState.BUFFERING or YT.PlayerState.PLAYING, you can move the player to the appropriate visible position.

Alternatively, you can just delay loading the player until you need it.

查看更多
相关推荐>>
4楼-- · 2019-08-28 18:40

While this is a breaking change beyond a doubt now that I got a good night's sleep I found a solution to my own issue to lazy load / JIT the player.

The solution I have a proof of concept of and am currently implementing is as simple as setting a global var to test if I have a videoid.

var cleared = false;
    function onYouTubePlayerAPIReady(videoid) {
        if (!cleared) return;
        .....

Then when I actually want to play a video I just see if the variable is false and if so I call the onYouTubePlayerAPIReady function and pass it the videoid and initialize it. My mistake was to try to initialize and then call the play() function in the same call. The solution for me is to either call the initializer with an id or call the playbyid function if already initialized.

While I do love the YT public API and others that I use it does open the door to lots of breaking changes and that is always a test of one's architectural and mental fortitude.

查看更多
登录 后发表回答