【问题标题】:Pause Youtube embed when playing Soundcloud embed播放 Soundcloud embed 时暂停 Youtube embed
【发布时间】:2013-08-09 16:03:13
【问题描述】:

我有一个音乐博客,其中包含各种嵌入式 soundcloud 和 youtube 播放器。

我想要做的是防止任何音频同时播放。换句话说,当我播放 youtube 视频时,如果我点击播放 soundcloud 嵌入,我希望 youtube 播放器暂停,反之亦然。

如果我点击播放另一个 youtube 播放器,我已经开发了暂停流式 youtube 播放器的代码(soundcloud 已经固有地这样做了)。我只需要使它交叉兼容。真的很感激一些帮助,谢谢。

var playerCurrentlyPlaying = null;
var players = {}
YT_ready(function() {
   $(".youtube_embed").each(function() {
       var identifier = this.id;
       var frameID = getFrameID(identifier);
       if (frameID) {
            players[frameID] = new YT.Player(frameID, {
                events: {
                    "onStateChange": function(event){
                        if (event.data == YT.PlayerState.PLAYING)
                        {
                            if(playerCurrentlyPlaying != null &&
                               playerCurrentlyPlaying != frameID)
                            callPlayer( playerCurrentlyPlaying , 'pauseVideo' );
                            playerCurrentlyPlaying = frameID;
                        }
                    }
                }
            });
        }
   });
});

我使用了以下来源的函数: Listening for Youtube Event in JavaScript or jQuery

YouTube iframe API: how do I control a iframe player that's already in the HTML?

YouTube API Target (multiple) existing iframe(s)

使用 UniqueID() 渲染 HTML:

<span class="soundcloud_embed" id="soundcloud_post_312">
  <iframe id="ui-id-1" width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F103518792&show_artwork=true&secret_token=s-LnOTK"></iframe>
</span>

<span class="youtube_embed" id="youtube_post_309">
  <iframe id="ui-id-2" width="528" height="190" src="//www.youtube.com/embed/Y3CYKXBEtf0" frameborder="0" allowfullscreen></iframe>
</span>

【问题讨论】:

    标签: javascript ruby-on-rails-3 youtube-api soundcloud


    【解决方案1】:

    首先,如果您能够在 iframe 上自己获取 ID,事情将大大简化,如下所示:

    <span class="soundcloud_embed">
      <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F4997623" id="sound1"></iframe>
    </span>
    <span class="soundcloud_embed">
      <iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F105153133" id="sound2"></iframe>
    </span>
    <span class="youtube_embed">
      <iframe width="400" height="225" src="//www.youtube.com/embed/tv8WgLEIPBg" id="vid1" frameborder="0" allowfullscreen></iframe>
    </span>
    <span class="youtube_embed">
      <iframe width="400" height="225" src="//www.youtube.com/embed/FmICU1gMAAw" id="vid2" frameborder="0" allowfullscreen></iframe>
    </span>
    

    如果您不想破解您提到的 auto_html gem 来获取 ID,您可以使用 jquery 的 .uniqueId() 函数在所有 iframe 上生成它们,或者使用帖子中的 getFrameID() 辅助方法提到(并且似乎已经在使用)。

    为了尽可能轻松地让两个 API(Youtube 和 Soundcloud)能够响应彼此的事件,您可以使用几个控制对象来跟踪哪些玩家在您的页面上以及哪些其中当前正在播放(此策略类似于您提到的链接所采用的策略,但已扩展为能够跟踪哪个播放器属于哪个 API)。使用它,定义一个通用的暂停函数,作为两个 API 的简单包装器:

    var playerCurrentlyPlaying = {"api":null,"frameID":null};
    var players = {"yt":{},"sc":{}};
    
    pauseCurrentPlayer=function() {
      var api=playerCurrentlyPlaying["api"],
          frameid=playerCurrentlyPlaying["frameID"];
    
      switch(api) {
        case "yt":
          players[api][frameid].pauseVideo();
          break;
        case "sc":
          players[api][frameid]["widget"].pause();
          break;
      }
    };
    

    接下来,您需要定义两个单独的函数;第一个将在捕获 YouTube 播放事件时调用,第二个将在捕获 Soundcloud 播放事件时调用。目前,Soundcloud HTML5 Widget 有一些错误,迫使必须包含一些非常丑陋的 hack——即,当您第一次播放 Soundcloud 声音时,有时不会触发 Play 事件。幸运的是,Play_Progress 事件是,所以我们可以利用它,但还必须包含一个解决方法,这样它就不会在暂停声音和开始视频时产生竞争条件:

    onYTPlay =function(frameid) {
      if (playerCurrentlyPlaying["frameID"]!=frameid && playerCurrentlyPlaying["frameID"]!=null) {
         pauseCurrentPlayer();
      }
      playerCurrentlyPlaying["api"]="yt";
      playerCurrentlyPlaying["frameID"]=frameid;
    };
    
    onSCPlay=function(frameid,event) {
      if (event==SC.Widget.Events.PLAY||players["sc"][frameid]["firstplay"]==true) {
         if (playerCurrentlyPlaying["api"]=="yt") { // because any soundcloud player will be automatically paused by another soundcloud event, we only have to worry if the currently active player is Youtube
            pauseCurrentPlayer();
         }
         playerCurrentlyPlaying["api"]="sc";
         playerCurrentlyPlaying["frameID"]=frameid;
         players["sc"][frameid]["firstplay"]=false;
      }
    };
    

    最后,您可以将钩子添加到 Youtube 嵌入和 Soundcloud 嵌入中,记住我们必须为 Soundcloud Play 事件添加的技巧。不要忘记嵌入 Soundcloud Widget API (&lt;script src="w.soundcloud.com/player/api.js"; type="text/javascript"&gt;&lt;/script&gt;),然后使用此代码进行绑定:

    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    
    function onYouTubeIframeAPIReady() {
      $(".youtube_embed iframe").each(function() {
        players["yt"][$(this).attr('id')] = new YT.Player($(this).attr('id'), {
          events: { 'onStateChange': onYTPlayerStateChange }
        });
      });
    }
    
    onYTPlayerStateChange = function(event) {
      if (event.data==YT.PlayerState.PLAYING) {
         onYTPlay(event.target.a.id);
      }
    };
    
    (function(){
        $(".soundcloud_embed iframe").each(function() {
          var frameid=$(this).attr('id');
          players["sc"][frameid]={};
          players["sc"][frameid]={"widget":SC.Widget(document.getElementById(frameid)),"firstplay":true};
          players["sc"][frameid]["widget"].bind(SC.Widget.Events.READY, function() {
           players["sc"][frameid]["widget"].bind(SC.Widget.Events.PLAY, function() {
            onSCPlay(frameid,SC.Widget.Events.PLAY);
           });
           players["sc"][frameid]["widget"].bind(SC.Widget.Events.PLAY_PROGRESS, function() {
            onSCPlay(frameid,SC.Widget.Events.PLAY_PROGRESS);
           });
         });
        });
       }());
    

    这种方法是为处理这两种 API 的多个播放器而设置的,如果您想支持其他可嵌入的媒体小部件(假设它们在开始播放时公开事件并且能够以编程方式暂停播放器),则应该可以很好地扩展)。

    【讨论】:

    • 首先,感谢您的宝贵时间和这篇精彩的文章。请看我更新的部分。我不确定暂停函数中的这一行是否有效:players[api][frameID].pauseVideo();。当我用以前的调用播放器替换该函数时,YT 会暂停为原始
    • 我想知道您的代码中是否存在拼写错误或其他问题...当我使用您的就绪函数而不是我提供的函数时(我将回调推断到它们自己的函数而不是嵌入它们),但我保持其他一切不变,YT 播放器仍然使用我的 pauseCurrentPlayer() 函数正确暂停。您是否收到任何控制台错误?
    • 请注意,如果您使用 getFrameId 和 callplayer 辅助函数,您必须修改它们才能与 soundcloud 一起使用,因为它们使用正则表达式使它们成为 YT具体的(因此我一开始说完全忽略辅助函数并自己在 iframe 上放置 ID 或在运行任何其他代码之前使用 jQuery 的 .uniqueID() 函数添加它们更简单)。
    • 当我点击一些 YT 播放器时,我在 JS 控制台中收到此错误:未捕获的 TypeError: Object # has no method 'pauseVideo' application.js?body=1:179 pauseCurrentPlayer application .js?body=1:179 player.yt.(匿名函数).YT.Player.events.onStateChange.
    • 如果有帮助,这里有一个完整的工作小提琴:jsfiddle.net/jlmcdonald/NqRqm/1
    【解决方案2】:

    这是可能的。检查小部件 api 游乐场。您可以从 soundcloud iframe 小部件观看所有状态事件。这也可以在 Flash embed 上完成。 https://w.soundcloud.com/player/api_playground.html

    在开始播放时注意 SC.Widget.Events.PLAY {"loadedProgress":0,"currentPosition":0,"relativePosition":0} 事件

    【讨论】:

      猜你喜欢
      • 2018-05-28
      • 2014-07-25
      • 2021-08-02
      • 2019-05-01
      • 2014-04-05
      • 1970-01-01
      • 2015-03-20
      • 2013-08-16
      • 1970-01-01
      相关资源
      最近更新 更多