当我创建
YT.Player(HTMLIFrameElement, { options })
的实例时,我得到一个具有以下内容的对象:
但不是
文档中描述的
playVideo
、pauseVideo
等。
我在这里有一个演示:http://siesta-annotations.surge.sh/Siesta_webviewer_test/?page=3
我正在通过
trait.playable.youtube.js
中的 DOM 创建 iframe,并将 iframe 添加到 documentFragment
,最终将添加到 div 中:
const element = document.createElement('iframe')
element.src = `https://www.youtube.com/embed/${id}?rel=0;&autoplay=${this.options.autostart ? 1 : 0};&enablejsapi=1;&origin=${location.hostname};`
element.style = this.inlineStyle
然后我创建一个 YT.Player 实例:
// nasty initialization because we're outside webpack and this is a demo
if (global.YT.loaded) {
this.player = new global.YT.Player(element, {
events: {
'onStateChange': this.stateHandler,
'onReady': onPlayerReady
}
})
} else {
const oldHandler = global.onYouTubeIframeAPIReady
global.onYouTubeIframeAPIReady = () => {
if (oldHandler) oldHandler()
this.player = new global.YT.Player(element, {
events: {
'onStateChange': this.stateHandler,
'onReady': onPlayerReady
}
})
}
}
YT.Player 的实例看起来像这样:
看起来缩小过程出错了。我做错了什么 - 我应该如何为我的用例初始化 YT.Player?
这是我的第二篇文章,希望能解决您的问题。
我不是 100% 确定你的代码是如何工作的,但我怀疑......
看起来像是
对象的双重实例化,这会导致YT.Player
对象不稳定。YT.Player
我自己也挣扎了很久(ps:我是业余程序员😅)
作为示例,以下代码片段是从 Youtube Iframe API 网站修改的,以及第二个实例化如何破坏播放器对象的示例 尝试一下! JS 斌:
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
</br>
<button onclick="instantiateOneMore()">
Call
<pre>new YT.Player('player')</pre>
</button>
<button onclick="pauseVideo()">
pauseVideo();
</button>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://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',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
let callTime = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
callTime ++;
console.log(callTime);
//document.querySelector('#dd').innerHTML = player.pauseVideo;
}
function pauseVideo(){
player.pauseVideo();
}
instantiateOneMore = () => {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
//document.querySelector('#dd').innerHTML = player.pauseVideo;
}
// 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.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
/* setTimeout(stopVideo, 6000) */
;
done = true;
}
}
/*
function stopVideo() {
player.stopVideo();
} */
</script>
</body>
</html>
此外,第二个
onPlayerReady()
甚至不会被调用。因此,如果您打算放置一些计数器来查看 new YT.Player(...)
被调用了多少次,您会怀疑它只被调用了一次。这使得效果幽灵远离调试。
奇怪的是,直到在构造函数播放器选项对象中调用
'onReady'
之前,您无法访问 YTPlayer API。 https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
function onYouTubeIframeAPIReady() {
new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': function (event) {
onPlayerReady(event.target)
},
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(player) {
player.playVideo();
}
这当然仅适用于一名玩家,因此如果您想处理多名玩家,则需要推出自己的 YouTube 播放器管理器。 (我知道 API 很疯狂)
如果您有带有 YouTube 视频的 iframe,则可以采用以下快速解决方案(未经测试):
const YTManager = {
videos: [],
youtubeApiReady = false,
initialize () {
const matchId = /[^/]+$/
this.youtubeApiReady = true
document.querySelectorAll('iframe[src*="youtube"]')
.forEach(iframe => this.videos.push({
dom: iframe,
player: null,
videoId: iframe.src.exec(matchId) || iframe.src.exec(matchId)[0]
}))
},
createPlayers () {
if (this.youtubeApiReady === false) return
this.videos.forEach(v => {
new YT.Player(v.dom.id, {
videoId: v.videoId,
events: {
'onReady': function (event) {
v.player = event.target
}
}
})
})
},
find (id) {
return this.videos.find(v => v.id === id)
},
play (id) {
const video = this.find(id)
if (this.youtubeApiReady && video && video.player) {
video.playVideo()
}
},
pause (id) {
const video = this.find(id)
if (this.youtubeApiReady && video && video.player) {
video.pauseVideo()
}
},
}
window.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
// YouTube client side script has been loaded
YTManager.youtubeApiReady = true
YTManager.createPlayers()
}
document.addEventListener("DOMContentLoaded", function() {
// all iframes has been parsed by the browser
YTManager.initialize()
});
当然,如果没有 ID,您就无法调用
YTManager.play
或 YTManager.pause
,并等待 YouTube 脚本加载,然后视频初始化完成。总而言之,真是一团糟。我相信你能想出一个更好的经理。我在工作中编写了一个更好的程序,但也适用于完全不同的对象和要求,因此它不太适合通用的 YouTube 视频管理器。但上面的是我现在的玩家的要点。
我建议从一开始就使用 iframe - 如果您的脚本出现任何问题,视频仍然可以播放,只是您无法控制它们。
Iframed youtube 视频看起来像这样:
<iframe
id="uniqueDOMElementID1"
width="560"
height="315"
src="https://www.youtube.com/embed/bHQqvYy5KYo"
frameborder="0"
allow="autoplay; encrypted-media"
allowfullscreen></iframe>
这是一个很老的问题,但我今天偶然发现了这个问题并自己解决了,尽管花了我几个小时。
就我而言,罪魁祸首是错误的视频 ID。
假设正确的 ID 是
videoId:"M7lc1UVf-VE"
,但我最初输入的是 videoId:"M7lc1UVf-VE?si=5rdPpwWtXnTEFHd_
。不知何故,它部分起作用,电影实际上正在播放,但其他功能从未起作用。
所以,我建议检查一下视频id上是否有不必要的参数。