Youtube Iframe API loadVideoById() 跳过视频
Youtube Iframe API loadVideoById() skips the video
问题
我正在使用 Youtube Iframe API,我需要使用每个视频的 API 的 startSeconds 和 endSeconds 选项。
但问题是:loadVideoById 函数会跳过视频。
在我的示例代码中,只播放了第一个、第三个、第五个视频。
这是代码。这只是我的应用程序的简化版本。
源代码
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
var videos = [
{
vid: 'nbCqWMIT-Pk',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'sAoJGNF_laA',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'kF_23_XxaHQ',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'zxYp3I0Gyrg',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'U_gA99OQwO4',
startSeconds: 10,
endSeconds: 15
}
];
var index = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
event.target.playVideo();
}
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
console.log(index);
if (index < videos.length - 1) {
index++;
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
}
}
}
</script>
</body>
</html>
源码简单说明
视频数组是为我自己的测试分配的。 (这都是Faker的亮点,因为我是他的忠实粉丝:))
我让播放器播放列表中的视频。如果播放器发出“ENDED”事件,则更改索引并播放下一个视频。
但是在播放第二个和第四个视频的时候,这个视频没有播放。只有 ENDED 事件来了。
似乎加载的视频的 endSeconds 值不等于视频的总时长,它会跳过下一个视频。
我该如何解决这种情况?是 Youtube API 的错误吗?
我添加了一个日志函数来查看调用了哪些状态,这似乎是 API 中的一个问题。当新视频加载状态 -1(未开始)时,紧接着是状态 0(结束)。
为了防止这种情况发生,我刚刚添加了一个额外的检查以确保至少加载了一部分视频。
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
var videos = [
{
vid: 'nbCqWMIT-Pk',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'sAoJGNF_laA',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'kF_23_XxaHQ',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'zxYp3I0Gyrg',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'U_gA99OQwO4',
startSeconds: 10,
endSeconds: 15
}
];
var index = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
event.target.playVideo();
}
function onPlayerStateChange(event) {
console.log("State change: " + event.data + " for index: " + index);
if (event.data === YT.PlayerState.ENDED && player.getVideoLoadedFraction() > 0) {
console.log(index);
if (index < videos.length - 1) {
index++;
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
}
}
}
</script>
</body>
</html>
我发现你的问题出在函数 onPlayerStateChange()
增量应该在最后(加载你的视频之后):
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
console.log(index);
if (index < videos.length - 1) {
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
index++;
}
}
}
此代码有效,但第一个视频播放了两次,最后一个没有显示。您只需要为 onPlayerReady
中的第一个视频增加索引,并将 <=
放入 onPlayerStatechange
.
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index],
});
event.target.playVideo();
if (index == 0){
index++;
}
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
;
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
console.log(index);
if (index <= videos.length - 1) {
event.target.loadVideoById({
videoId: videos[index],
});
index++;
}
}
}
var index = 0;
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
event.target.playVideo();
}
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
index++;
if (index > videos.length -1 ) {index=0;}else{index=index;}
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
}
}
问题
我正在使用 Youtube Iframe API,我需要使用每个视频的 API 的 startSeconds 和 endSeconds 选项。
但问题是:loadVideoById 函数会跳过视频。 在我的示例代码中,只播放了第一个、第三个、第五个视频。
这是代码。这只是我的应用程序的简化版本。
源代码
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
var videos = [
{
vid: 'nbCqWMIT-Pk',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'sAoJGNF_laA',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'kF_23_XxaHQ',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'zxYp3I0Gyrg',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'U_gA99OQwO4',
startSeconds: 10,
endSeconds: 15
}
];
var index = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
event.target.playVideo();
}
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
console.log(index);
if (index < videos.length - 1) {
index++;
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
}
}
}
</script>
</body>
</html>
源码简单说明
视频数组是为我自己的测试分配的。 (这都是Faker的亮点,因为我是他的忠实粉丝:))
我让播放器播放列表中的视频。如果播放器发出“ENDED”事件,则更改索引并播放下一个视频。
但是在播放第二个和第四个视频的时候,这个视频没有播放。只有 ENDED 事件来了。
似乎加载的视频的 endSeconds 值不等于视频的总时长,它会跳过下一个视频。
我该如何解决这种情况?是 Youtube API 的错误吗?
我添加了一个日志函数来查看调用了哪些状态,这似乎是 API 中的一个问题。当新视频加载状态 -1(未开始)时,紧接着是状态 0(结束)。
为了防止这种情况发生,我刚刚添加了一个额外的检查以确保至少加载了一部分视频。
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
var videos = [
{
vid: 'nbCqWMIT-Pk',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'sAoJGNF_laA',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'kF_23_XxaHQ',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'zxYp3I0Gyrg',
startSeconds: 10,
endSeconds: 15
},
{
vid: 'U_gA99OQwO4',
startSeconds: 10,
endSeconds: 15
}
];
var index = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
event.target.playVideo();
}
function onPlayerStateChange(event) {
console.log("State change: " + event.data + " for index: " + index);
if (event.data === YT.PlayerState.ENDED && player.getVideoLoadedFraction() > 0) {
console.log(index);
if (index < videos.length - 1) {
index++;
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
}
}
}
</script>
</body>
</html>
我发现你的问题出在函数 onPlayerStateChange()
增量应该在最后(加载你的视频之后):
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
console.log(index);
if (index < videos.length - 1) {
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
index++;
}
}
}
此代码有效,但第一个视频播放了两次,最后一个没有显示。您只需要为 onPlayerReady
中的第一个视频增加索引,并将 <=
放入 onPlayerStatechange
.
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index],
});
event.target.playVideo();
if (index == 0){
index++;
}
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
;
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
console.log(index);
if (index <= videos.length - 1) {
event.target.loadVideoById({
videoId: videos[index],
});
index++;
}
}
}
var index = 0;
function onPlayerReady(event) {
event.target.cueVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
event.target.playVideo();
}
function onPlayerStateChange(event) {
if (event.data === YT.PlayerState.ENDED) {
index++;
if (index > videos.length -1 ) {index=0;}else{index=index;}
event.target.loadVideoById({
videoId: videos[index].vid,
startSeconds: videos[index].startSeconds,
endSeconds: videos[index].endSeconds
});
}
}