保持两个 YouTube 视频彼此同步
Posted
技术标签:
【中文标题】保持两个 YouTube 视频彼此同步【英文标题】:Keeping two YouTube videos in sync with each other 【发布时间】:2013-11-22 16:03:21 【问题描述】:我在同一页面上嵌入了两个相同的 YouTube 视频。我希望它们保持同步,这是我的要求/注意事项:
两个视频必须同时开始 当用户播放/暂停视频时,其他视频也会执行相同的操作 这很容易通过 API 实现 当一个视频缓冲另一个视频时停止等待,并在它们都准备好时开始 我只需要一个视频的音频 同步精度不必精确到毫秒级,只要可靠即可 一个视频将用作背景视频 此视频会略微模糊(使用 CSS3 模糊),因此质量不是很重要我尝试使用 YouTube JS API 来监听播放器状态变化并尝试使两个视频保持同步,但它并不像我希望的那样可靠。我将在下面发布部分代码。
需要注意的是,一个视频会显得比另一个大,因此 YouTube 可能会为此提供更高质量的视频。
因为我使用的是 CSS3 blur,我只能使用最近的 Webkit 浏览器,所以单独使用这些(而不是 FF/IE)的解决方案不是问题。
我的问题是这样的,对于上述要求,有没有办法让这两个视频保持同步?我确实考虑过是否可以使用 canvas API 来“重绘”视频,但经过研究发现这是不可能的。
buffering = false;
var buffer_control = function(buffering_video, sibling_video, state)
switch ( state )
case 1: // play
if ( buffering === true )
console.error('restarting after buffer');
// pause both videos, we want to make sure they are both at the same time
buffering_video.pauseVideo();
sibling_video.pauseVideo();
// get the current time of the video being buffered...
var current_time = buffering_video.getCurrentTime();
// ... and pull the sibling video back to that time
sibling_video.seekTo(current_time, true);
// finally, play both videos
buffering_video.playVideo();
sibling_video.playVideo();
// unset the buffering flag
buffering = false;
break;
case 3: // buffering
console.error('buffering');
// set the buffering flag
buffering = true;
// pause the sibling video
sibling_video.pauseVideo();
break;
【问题讨论】:
要同步这么多运动部件并保持足够同步以免分散用户的注意力,这听起来确实是一项艰巨的任务......愚蠢的问题,为什么? 也许是这样,我正在尝试突破界限:D。一个视频将是模糊的(CSS3 模糊),全尺寸背景视频,另一个是屏幕中间的普通视频......我正在做的项目有点混乱。事实上,如果它稍微不同步(但确实如此),这不会是一个大问题。 你用的是哪个api版本? @AbhishekHingnikar 我正在加载脚本<script src="http://www.youtube.com/player_api"></script>
,所以我猜它是最新版本。
也许你可以尝试一些数学函数,比如:get time of video1 |获取video2的时间|true|false video1 time>video2 time|video1 - video2
【参考方案1】:
你的项目很有趣,这就是我决定尝试帮助你的原因。我从未使用过 youtube API,但我尝试了一些编码,这对你来说可能是一个开始。
所以这是我尝试过的代码,它似乎工作得很好,它当然需要一些改进(我没有尝试计算两个播放视频之间的偏移量,但让它们取消静音显示不匹配并且听起来合法)
我们开始吧:
让我们从一些 html 基础知识开始
<!DOCTYPE html>
<html>
<head>
我们为前景播放器添加一个绝对定位,使其覆盖播放背景视频的播放器(用于测试)
<style>
#player2position:absolute;left:195px;top:100px;
</style>
</head>
<body>
这里使用 jQuery 来淡入/淡出播放器(您将在下面看到原因),但您可以使用基本的 JS
<script src="jquery-1.10.2.min.js"></script>
此代码异步加载 IFrame Player API 代码。 此函数在 API 代码下载后创建 所以现在是代码中有趣的部分。同步项目中的主要问题与启动视频之前需要缓冲的事实有关。实际上,API 并没有提供任何直观的功能来预加载视频(由于带宽问题(客户端和服务器端)。所以我们必须有点棘手。
预加载视频的步骤如下: 您必须预先加载您的两个视频。 当视频播放器准备就绪时,API 会调用这些函数。 当后台视频播放器的状态发生变化时,API会调用该函数。 当前台视频播放器的状态发生变化时,API会调用该函数。 这里有一部分代码表现得很奇怪。取消注释下面的行会使同步变得很糟糕,但如果你注释它,你将不得不点击播放按钮上的两次但是同步看起来会更好。 请注意,此代码可能不计算观看次数。 如果你想要没有解释的代码,你可以去这里:http://jsfiddle.net/QtBlueWaffle/r8gvX/1/ 2016 年更新
Live Preview 希望这会有所帮助。 <div id="player1"></div> <!-- Background video player -->
<div id="player2"></div> <!-- Foreground video player -->
<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);
var player1;
var player2;
function onYouTubeIframeAPIReady()
player1 = new YT.Player('player1',
height: '780',
width: '1280',
videoId: 'M7lc1UVf-VE',
playerVars: 'autoplay': 0, 'controls': 0 ,
events:
'onReady': onPlayer1Ready,
'onStateChange': onPlayer1StateChange
);
player2 = new YT.Player('player2',
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events:
'onReady': onPlayer2Ready,
'onStateChange': onPlayer2StateChange
);
var player1Ready = false;
var player2Ready = false;
player.mute():Void
);
模拟时间线跳转以开始缓冲 (player.seekTo(seconds:Number, allowSeekAhead:Boolean):Void
);
等待状态改变事件等于YT.PlayerState.PLAYING
;
暂停视频(player.pauseVideo():Void
);
使用player.seekTo(seconds:Number, allowSeekAhead:Boolean):Void
倒带视频;
取消静音播放器(player.unMute():Void
);
显示播放器。
var preloading1 = false;
var preloading2 = false;
function onPlayer1Ready(event)
player1Ready = true;
preloading1 = true; // Flag the player 1 preloading
player1.mute(); // Mute the player 1
$( "#player1" ).hide(); // Hide it
player1.seekTo(1); // Start the preloading and wait a state change event
function onPlayer2Ready(event)
player2Ready = true; // The foreground video player is not preloaded here
function onPlayer1StateChange(event)
if (event.data == YT.PlayerState.PLAYING )
if(preloading1)
prompt("Background ready"); // For testing
player1.pauseVideo(); // Pause the video
player1.seekTo(0); // Rewind
player1.unMute(); // Comment this after test
$( "#player1" ).show(); // Show the player
preloading1 = false;
player2Ready = true;
preloading2 = true; // Flag for foreground video preloading
player2.mute();
//$( "#player2" ).hide();
player2.seekTo(1); // Start buffering and wait the event
else
player2.playVideo(); // If not preloading link the 2 players PLAY events
else if (event.data == YT.PlayerState.PAUSED )
if(!preloading1)
player2.pauseVideo(); // If not preloading link the 2 players PAUSE events
else if (event.data == YT.PlayerState.BUFFERING )
if(!preloading1)
player2.pauseVideo(); // If not preloading link the 2 players BUFFERING events
else if (event.data == YT.PlayerState.CUED )
if(!preloading1)
player2.pauseVideo(); // If not preloading link the 2 players CUEING events
else if (event.data == YT.PlayerState.ENDED )
player2.stopVideo(); // If not preloading link the 2 players ENDING events
function onPlayer2StateChange(event)
if (event.data == YT.PlayerState.PLAYING )
if(preloading2)
//prompt("Foreground ready");
player2.pauseVideo(); // Pause the video
player2.seekTo(0); // Rewind
player2.unMute(); // Unmute
preloading2 = false;
$( "#player2" ).show(50, function()
//player2.playVideo();
);
else
player1.playVideo();
else if (event.data == YT.PlayerState.PAUSED )
if(/*!preloading1 &&*/ !preloading2)
player1.pauseVideo();
else if (event.data == YT.PlayerState.BUFFERING )
if(!preloading2)
player1.pauseVideo();
//player1.seekTo(... // Correct the offset here
else if (event.data == YT.PlayerState.CUED )
if(!preloading2)
player1.pauseVideo();
else if (event.data == YT.PlayerState.ENDED )
player1.stopVideo();
</script>
</body>
</html>
【讨论】:
在 jsFiddle 示例中,视频不是一起开始的? 啊,是一个 jQuery 问题,从 HTML 中删除了 jQuery 并将其添加到小提琴中的脚本中......现在测试。 好的,但我一直无法在 fiddle 中启动它,我习惯在本地工作,它在本地工作得很好 好吧,我尽力了 :) 但代码并不完美,它必须适应您的确切需求。祝你的项目好运 好的,我认为这个解决方案可以让我到达我需要的地方......需要一些小的改进,但是你已经打下了很好的基础。非常感谢!以上是关于保持两个 YouTube 视频彼此同步的主要内容,如果未能解决你的问题,请参考以下文章
如何使 YouTube 播放器缩放到页面宽度,同时保持纵横比?