javascript - 同步多个YouTube视频

标签 javascript jquery html youtube youtube-api

一次播放多个YouTube的最佳方法是什么?我希望它们在毫秒级同步,因此不会受到缓冲问题或长度不同的广告的影响。

更新1:

我认为如果我能回答以下问题,我的问题将得到充分回答:

当视频能够播放(视频已被充分缓冲以能够播放/广告未播放/视频因其他任何原因而停止播放)时,如何检测使用YouTube的JavaScript API?

更新2:

YouTube同步的基本思想已经由SwigView完成。唯一缺少的是视频的同步更加精确,而SwigView在实现方面做得并不出色。

我开始怀疑当前的API是否有可能,并且我正在寻找替代方法。

最佳答案

通过定期测量和调整两个播放器之间的时间差,可以使两个YouTube iFrame API播放器的同步误差在0.2秒或更佳。例如,通过将一个播放器的播放速度加倍或减半并将其在X / 2毫秒后设置回正常速度,可以非常精确地完成X毫秒时差的调整。可以从常规API list 中添加用于用户交互(停止,播放,暂停)的助手。由于它们会暂停播放器,因此它们还包含广告。

代码说明:

script.js

// the players
var player1;
var player2;

// the rules
var syncThreshold=0.2; // seconds, threshold for an acceptable time difference to prevent non-stop syncing
var jumpThreshold=2; // seconds, threshold for a time difference that should be corrected by a rough jump
var jumpDeadTime=500; // milliseconds, a dead time in which we don't sync after a jump

// timeouts and intervals
var timeSyncInterval;
var syncActionTimeout=undefined;

// The YouTube API calls this once it's ready
function onYouTubeIframeAPIReady() {
  player1 = new YT.Player('somediv1', {
    videoId: 'zkv-_LqTeQA',
    events: {
      onReady: syncTime,
      onStateChange: syncStateChange
    }
  });
  player2 = new YT.Player('somediv2', {
    videoId: 'zkv-_LqTeQA'
  });
}

// the syncing magic
function syncTime(){
  // making sure the syncing interval has not been set already for some reason
  clearInterval(timeSyncInterval);
  // setting a 1s interval in which we check it the players are in sync and correct in necessary
  timeSyncInterval = setInterval(function () {
    // if the timeout is already set, we are already trying to sync the players, so we don't have to do it again
    if(syncActionTimeout==undefined){
      // measure the time difference and calculate the duration of the sync-action
      var time1=player1.getCurrentTime();
      var time2=player2.getCurrentTime();
      var timeDifference=time2-time1;
      var timeDifferenceAmount=Math.abs(timeDifference);
      var syncActionDuration=1000*timeDifferenceAmount/2;

      if(timeDifferenceAmount>jumpThreshold){
        // the players are too far apart, we have to jump
        console.log("Players are "+timeDifferenceAmount+" apart, Jumping.");
        player2.seekTo(player1.getCurrentTime());
        // we give the player a short moment to start the playback after the jump
        syncActionTimeout=setTimeout(function () {
          syncActionTimeout=undefined;
        },jumpDeadTime);
      }else if(timeDifference>syncThreshold){
        // player 2 is a bit ahead of player 1, slowing player 2 down
        console.log("Player 2 is "+timeDifference+"s ahead of player 1. Syncing.");
        player2.setPlaybackRate(0.5);
        // setting a timeout that fires precisely when both players are sync
        syncActionTimeout=setTimeout(function () {
          // the players should be sync now, so we can go back to normal speed
          player2.setPlaybackRate(1);
          syncActionTimeout=undefined;
        },syncActionDuration);
      }else if(timeDifference<-syncThreshold){
        console.log("Player 1 is "+(-timeDifference)+"s ahead of player 2. Syncing.");
        // player 1 is bit ahead of player 2, slowing player 2 down
        player2.setPlaybackRate(2);
        // setting a timeout that fires precisely when both players are sync
        syncActionTimeout=setTimeout(function () {
          // the players should be sync now, so we can go back to normal speed
          player2.setPlaybackRate(1);
          // undefining the timeout to indicate that we're done syncing
          syncActionTimeout=undefined;
        },syncActionDuration);
      }
    }
  },1000);
}

// a little helper to deal with the user
function syncStateChange(e){
  if(e.data==YT.PlayerState.PLAYING){
    player2.seekTo(player1.getCurrentTime());
    player2.playVideo();
  }else if(e.data==YT.PlayerState.PAUSED){
    player2.seekTo(player1.getCurrentTime());
    player2.pauseVideo();
  }
}

index.html
<!DOCTYPE html>
<html>
<head>
        <title>Sync Two Youtube Videos</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <!-- CDN -->
        <script type="text/javascript" src="//www.google.com/jsapi"></script>
        <script type="text/javascript" src="https://apis.google.com/js/client.js?onload=onJSClientLoad"></script>

    <script src="https://www.youtube.com/iframe_api"></script>
    <!-- HOSTED -->
        <script src="script.js"></script>
</head>
<body>
  <div id="somediv1"></div>
  <div id="somediv2"></div>
</body>
</html>

关于javascript - 同步多个YouTube视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17578594/

相关文章:

jquery - onClick 元素将 Classname 添加到具有相同 Classname 的相关 div

javascript - 如何在单击某个单选按钮后禁用复选框。

javascript - 为具有相同类名的所有按钮而不是当前选定的按钮触发 Jquery 事件

javascript - 我怎样才能使背景图像适应主分区?

C# Web 浏览器控件未正确更新

javascript - 使用indexOf查找数组中的项目

javascript - 为什么 if 语句不起作用并使用显示 : none? 使我的元素消失

javascript - javascript中的正则表达式仅匹配字母或空格

javascript - 更改单选后如何聚焦于输入字段?

javascript - JQuery:单击 div 编辑表格