0

我们有一个包含 YouTube 视频的 Facebook Tab 应用程序(可能不相关)。

第一次从空缓存加载页面时一切正常。然而,在随后的页面加载中,一旦视频停止加载,onStateChange处理程序就不会在 Internet Explorer 中触发。

在 Chrome 和 Firefox 中一切正常,这个问题似乎只影响 IE,而且奇怪的是,只发生在非空缓存中。它看起来与gdata-issues #2942非常相似,除了那个问题有Status: Fixed.

我们代码的相关块如下:

<!DOCTYPE html>

...

<div class="player-surround">
   <div id="ytplayer">
       You need Flash player 9+ and JavaScript enabled to view this video.
   </div>
</div>

...

<script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script type="text/javascript">
var params = { allowScriptAccess: "always" };
var atts = { id: "ytplayer" };
// YouTube video ID redacted here
swfobject.embedSWF("http://www.youtube.com/v/XXXXXXXXXXXXXX?enablejsapi=1&playerapiid=ytplayer&version=3",
   "ytplayer", "587", "330", "8", null, null, params, atts);
</script>
<script src="//www.youtube.com/player_api"></script>

包含的 JavaScript

MFA.onPlayerStateChange = function(evt) {
    var state = this.getPlayerState();
    log('158: STATE CHANGED: ' + state);

    // Then do some stuff, but the `log` call above doesn't fire
}

MFA.getPlayerState = function() {
    var playerState;

    if (this.ytplayer) {
        playerState = this.ytplayer.getPlayerState();
        
        switch (playerState) {
            case 5:  return 'video cued';
            case 3:  return 'buffering';
            case 2:  return 'paused';
            case 1:  return 'playing';
            case 0:  return 'ended';
            case -1: return 'unstarted';
            default: return 'Status uncertain';
        }
    }
};

(显然,我从这个问题中遗漏了一堆不相关的代码。)

有没有人知道为什么一切都会正常工作,除非 IE 以前看过该页面?我可以理解它是否从未在 IE 中工作过,但当缓存为空时它工作正常,但当您重新加载页面时失败。

感谢所有想法。


编辑

Greg Schechter指出我的代码示例使用了swfobject.embedSWF代码,而不是iframe 嵌入代码

我们最初确实使用了 iframe 嵌入代码:

var s = {
   playerHeight: '330',
   playerWidth: '587',
   playerVars: { 'rel': 0 },
   videos: {
      stage1: 'XXXXXXXXXXXXXX', // ...
   }
};

window.onYouTubePlayerAPIReady = function() {
   MFA.ytplayer = new YT.Player('ytplayer', {
      height: s.playerHeight,
      width: s.playerWidth,
      videoId: s.videos.stage1,
      playerVars: s.playerVars,
      events: {
         'onReady': $.proxy(MFA.onPlayerReady, MFA),
         'onStateChange': $.proxy(MFA.onPlayerStateChange, MFA),
         'onError': $.proxy(MFA.onPlayerError, MFA)
      }
   });
} 

,但这表现出同样的问题。该swfobject.embedSWF代码随后被添加以尝试解决该问题,因为我们之前已经看到 IE 过度偏执的问题,即从 iframe 跨域访问 API 的问题。

4

2 回答 2

0

您的代码示例看起来有点不对劲。看起来你正在使用swfobject.embedSwfwith //www.youtube.com/player_api。该 //www.youtube.com/player_api脚本仅适用于 iframe 嵌入。如果您使用 iframe 嵌入,它应该可以解决您的问题。

详细信息可以在这里找到。 https://developers.google.com/youtube/iframe_api_reference

于 2012-10-30T20:38:30.510 回答
0

所以我不得不放下这个并回到另一个项目,但我的一位同事设法找到了解决方案。这个答案的其余部分直接取自他给我的电子邮件。

所以这里是我们如何解决这个(非常烦人的!)IE 问题的详细版本……事实证明,这是一个改变在 default.aspx 页面中调用 YouTube 播放器 API 的方式的案例。

我们替换了这个:

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

<script>标签中使用以下 JavaScript:

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

(这就是它在API 参考中指定的方式)。

我还注意到谷歌指定iframe_api但我们使用的是player_api. 这可能使问题更加复杂,但仅仅改变并不能解决问题。

[我们的技术总监] 向我解释的方式是,第一次加载页面时原始方式很好,因为所有内容都是新加载的,并且 YouTube API 有足够的时间在 init.js 初始化之前加载。

但是当您重新加载页面时init.js,在 API 准备好之前被缓存并且可能加载得太快,因此在尝试触发时失败onYouTubePlayerReady。以上述方式执行此操作仍然开始init.js,但同时也开始加载iframe_api(通过有效地将其作为列表中的第一个脚本标记插入)。它也可能与 IE9 的一个已知问题略有关联,在该问题中 AJAX 调用会造成内存泄漏,但不确定。

我在其他浏览器上间歇性地看到相同的错误(非常),我想这是由于这里和谷歌 API 连接到的任何数据中心之间的RTD波动造成的。如果在 API 准备好之前它不同步到足以init.js到达那里,onYouTubePlayerReady将会失败。但随后一个简单的刷新将解决它。

有趣的是,仅仅将 YouTube API 作为第一个脚本标签并没有什么不同!

所以我想教训是,当我们处理第三方 API、iframe 和 Internet Explorer 时,我们需要确保对所有第三方 API 使用异步加载,尤其是在涉及 YouTube 和 Facebook 的情况下。

于 2012-11-01T18:30:12.103 回答