【问题标题】:YouTube onPlayerStateChange event not firing in Internet Explorer on reloaded pageYouTube onPlayerStateChange 事件未在重新加载页面上的 Internet Explorer 中触发
【发布时间】:2012-10-20 05:33:16
【问题描述】:

我们有一个包含 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 embed code

我们最初确实使用了 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 的问题。

【问题讨论】:

    标签: javascript youtube-api dom-events


    【解决方案1】:

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

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

    【讨论】:

    • 我们使用了 iframe 嵌入,但它不起作用,这就是我们查看 swfobject.embedSWF 代码的原因。我会适当地更新问题。
    • 如问题所述——在 IE 中,如果我们使用 iframe 嵌入,onYouTubePlayerAPIReady 事件不会触发。如果我们使用 SWF 对象嵌入,onYouTubePlayerAPIReady 事件会触发,但onStateChange 事件不会触发(在视频结尾处)。
    【解决方案2】:

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

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

    我们替换了这个:

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

    &lt;script&gt; 标记中使用以下 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 reference 中指定的方式)。

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

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

    但是当您重新加载页面时,init.js 已被缓存,并且可能在 API 准备好之前加载得太快,因此在尝试触发 onYouTubePlayerReady 时失败。以上述方式执行此操作仍然从init.js 开始,但同时也开始加载iframe_api(通过有效地将其作为列表中的第一个脚本标签插入)。它也可能与known issue with IE9 where AJAX calls can create a memory leak 略有关联,但不确定。

    我在其他浏览器上(非常)间歇性地看到相同的错误,我想这是由于RTDs 在此处和 Google API 连接到的任何数据中心之间波动。如果在 API 准备好之前,init.js 无法同步到那里,onYouTubePlayerReady 将失败。但是,一个简单的刷新就可以解决它。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      • 2012-06-17
      • 1970-01-01
      • 1970-01-01
      • 2010-12-23
      • 1970-01-01
      相关资源
      最近更新 更多