播放Soundcloud嵌入时暂停Youtube嵌入

Jaq*_*aqx 7 javascript youtube-api soundcloud ruby-on-rails-3

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

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

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

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;
                        }
                    }
                }
            });
        }
   });
});
Run Code Online (Sandbox Code Playgroud)

我使用过这些来源的函数: 用JavaScript或jQuery监听Youtube事件

YouTube iframe API:如何控制已经在HTML中的iframe播放器?

YouTube API目标(多个)现有iframe

使用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>
Run Code Online (Sandbox Code Playgroud)

jlm*_*ald 6

首先,如果您能够在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>
Run Code Online (Sandbox Code Playgroud)

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

为了使两个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;
  }
};
Run Code Online (Sandbox Code Playgroud)

接下来,您将要定义两个单独的函数; 每当捕获YouTube播放事件时,第一个将被调用,而每当捕获Soundcloud播放事件时,第二个将被调用.目前Soundcloud HTML5 Widget有一些错误,迫使必须包含一些相当丑陋的黑客 - 即,当您第一次播放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;
  }
};
Run Code Online (Sandbox Code Playgroud)

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

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);
       });
     });
    });
   }());
Run Code Online (Sandbox Code Playgroud)

这种方法设置为处理两个API的多个参与者,并且如果您想支持其他可嵌入媒体小部件(如果他们在开始播放时公开事件并且他们能够以编程方式暂停玩家),则应该可以进行适当的扩展.

  • 如果它有用,这里有一个完整的工作小提琴:http://jsfiddle.net/jlmcdonald/NqRqm/1/ (2认同)