通过一点点创意,我们实际上可以使用loadPlaylist() 而不会造成任何干扰。 API 提供了events,其中之一将显示对我们的目的有用:onStateChange。
onStateChange
只要玩家的状态发生变化,就会触发此事件。 API 传递给您的事件侦听器函数的事件对象的数据属性将指定一个与新播放器状态相对应的整数。可能的值是:
- -1(未启动)
- 0(已结束)
- 1(播放中)
- 2(暂停)
- 3(缓冲)
- 5(视频提示)
一些观察表明,当播放列表从一个视频转换到另一个视频时,-1 事件会触发。这是我们的机会。通过仅在发生转换时更新播放列表,不会(嗯,几乎没有)明显的中断。
我们的想法是维护一个单独的播放列表,我们可以对其进行操作。这是一个简单的 Youtube 视频标识符数组,我们可以随时在其中推送新数据。
每次发生视频转换时,我们都会根据播放器播放列表的长度检查播放列表的长度。如果它们不匹配,我们会更新玩家的播放列表。
我们还会在播放器的播放列表中跟踪过渡前播放的最后一个视频的索引。在加载新的播放列表时,我们提供previous index + 1,用于播放播放列表中的下一个视频,而不是从头开始播放。
我们使用previous index + 1 的原因是因为如果我们在播放最后一个视频时更新,使用当前索引会返回0,因为播放器会循环回到第一个视频。
我必须指出,这纯粹是为将新视频附加到播放列表的情况而设计的。以其他方式编辑播放列表需要更多逻辑。
JSFiddle 上的工作演示。
HTML
<div id="player"></div>
<button id="button">queue 2 more videos</button>
CSS
div {
width:300px;
height:240px;
background-color: yellow;
}
JavaScript
var player;
var playlist = ['b_XKnkQZkOM','dnNt78eGjSM'];
var previousIndex = 0;
$(window).load(function(){
player = new YT.Player('player', {
height: '240',
width: '300',
playerVars : {
playlist: playlist.join(','),
},
events: {
onStateChange: function(event) {
/*
the video has changed
seize the opportunity to update the playlist without interruption
*/
if(event.data == -1 || event.data == 0) {
// get current video index
var index = player.getPlaylistIndex();
// update when playlists do not match
if(player.getPlaylist().length != playlist.length) {
// update playlist and start playing at the proper index
player.loadPlaylist(playlist, previousIndex+1);
}
/*
keep track of the last index we got
if videos are added while the last playlist item is playing,
the next index will be zero and skip the new videos
to make sure we play the proper video, we use "last index + 1"
*/
previousIndex = index;
}
}
}
});
});
$(document).ready(function() {
$('#button').click(function(){
playlist.push('ZVeaEl7nMWM');
playlist.push('YRBwXHowb6I');
});
});
请注意,如果您屏蔽 youtube.com/api/stats(广告屏蔽等),则不会在视频结束时触发事件 0。