我道歉,因为我对我的问题非常困惑。我真的处于绑定状态,因为这会导致我的生产网站出现问题。
我的网站上有一个javascript播放器可以播放歌曲列表,可以在youtube,soundcloud或vimeo上托管。昨天我注意到这个错误,这个错误通常会在你试图通过"跳过"加载新歌时出现。用播放器按钮。这个错误刚刚开始在最后一两天。我在youtube api发行说明中没有看到任何新内容,并且使用Chrome,Firefox和Safari会出现此错误,因此很可能与浏览器中的更改无关。我使用的东西已经改变了,因为我没有在18天内推出新代码。
示例播放列表位于:http://www.muusical.com/playlists/programming-music
我认为我已经隔离了重现错误的方法,以下是步骤:
*请注意,如果播放列表中的第一首歌是youtube歌曲,即使不播放最初加载的youtube歌曲,只是跳到另一首歌曲也会产生错误。
基本上,一旦你加载和/或播放了一首youtube歌曲并尝试跳到另一首歌曲,就会出现错误。
如果您发现此行为的例外,请告诉我。
我在控制台中看到此错误:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://www.muusical.com') does not match the recipient window's origin ('http://www.muusical.com').
我使用youtube javascript api加载播放器:
new YT.Player('playlist-player', {
playerVars: { 'autoplay': 1, 'fs': 0 },
videoId: "gJ6APKIjFQY",
events: {
'onReady': @initPlayerControls,
'onStateChange': @onPlayerStateChange
}
})
哪个产生这个iframe:
<iframe id="playlist-player" frameborder="0" allowfullscreen="1" title="YouTube video player" width="640" height="360" src="https://www.youtube.com/embed/gJ6APKIjFQY?autoplay=1&enablejsapi=1&origin=http%3A%2F%2Fwww.muusical.com"></iframe>
从上面的youtube歌曲中点击跳过后,这就是我在iframe中看到的内容:
<iframe id="playlist-player" frameborder="0" allowfullscreen="1" title="YouTube video player" width="640" height="360" src=""></iframe>
我支持youtube,soundcloud和vimeo歌曲。似乎有一首youtube歌曲加载了&#34;起源&#34;从http更改为https。我不认为有必要为其他主机包含嵌入方法,因为即使整个播放列表只是youtube也会发生此错误,并且它不会出现在仅包含来自soundcloud和vimeo的歌曲的播放列表中。
此外,这是我加载youtube javascript的方式:
// Load the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
如果您需要我澄清任何事情,请告诉我,并提前感谢您的光临。
答案 0 :(得分:3)
我已经阅读了一些关于此的内容,此处有一些SO帖子以及此链接:https://code.google.com/p/gdata-issues/issues/detail?id=5788
我准备在你的问题上添加评论,说我对此感到疯狂......但是当我开始描述我的设置时,我找到了一种方法来避免这个问题^^。
我从空的div
元素开始,并使用Youtube Iframe API将其转换为iframe
,并提供所有必要的选项。
我有像这样的多个div,并且通常使用相同的JS变量来存储所有这些玩家,但是一次一个(一个替换另一个,依此类推...... - 它可能会更好,我知道)
为了解决这个问题,我想在用另一个元素构建新玩家之前用youtubePlayer.destroy();
销毁玩家。我的Chrome控制台中没有更多的JS错误出现了:)。
希望它有所帮助,所有关于http和https的文章都不适用于我的情况,因为我没有自己设置iframe网址,而我的网站恰好是而不是 https。 ..
我确实在HTML中恢复了异步调用而不是静态script
标记,但我认为这不是必需的。
编辑:这个错误信息实际上是误导性的,它只是模糊地表示:你没有以正确的方式使用youtube API:)
答案 1 :(得分:2)
@sodawillow的答案部分正确,但我想提供解决方案的详细信息以及导致我的代码停止调用.destroy()
方法删除youtube播放器的原因。
我的网站有一个播放器可以从各个网站中切换出来的歌曲,其中一个是Youtube。取决于播放器的类型,可以有不同的方法来移除播放器。我的代码检查是否存在youtube播放器,如果通过检查,则它使用只有youtube播放器具有的.destroy()
方法。问题是YouTube更改了其播放器对象上某些静态变量的名称。例如,如果我通过以下方式创建了一个播放器:
var player = new YT.Player('playlist-player', {
playerVars: { 'autoplay': 1, 'fs': 0 },
videoId: "gJ6APKIjFQY",
events: {
}
})
然后会有一个变量player.L
,其中包含字符串"player"
。因此,要检查当前播放器是否是YouTube播放器并将其删除,我执行了此操作:
if (player.L == "player") {
player.destroy();
} else {
//handle the removal of the Soundcloud or Vimeo player.
}
最近有时Youtube将字符串"player"
的位置更改为现在位于player.M
。我可以更改上面的代码来检查player.M
而不是player.L
,这样可行,但是为了避免将来出现这个问题而我已经实现了:
if (player.destroy) {
player.destroy();
} else {
//handle the removal of the Soundcloud or Vimeo player.
}
只要Youtube未明确删除.destroy()
方法,就不会出现任何问题。
总而言之,问题是@sodawillow猜测,我没有使用.destroy()
方法删除Youtube播放器。原因是因为Youtube对他们的api进行了一些未经宣布的修改,改变了一些静态变量的位置。
答案 2 :(得分:1)
此错误属于Google Youtube API。
在“https://www.youtube.com/iframe_api”内:
if (!window['YT']) {
var YT = {loading: 0, loaded: 0};
}
if (!window['YTConfig']) {
var YTConfig = {'host': 'http://www.youtube.com'};
}
他们使用http而不是https。
我们需要覆盖'host'选项和'widget_referrer',与'origin'相同。
player = new YT.Player('player', {
host: 'https://www.youtube.com',
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE'
...
origin: "https://www.enziin.com",
widget_referrer: "https://www.enziin.com"
}
古德勒克。
答案 3 :(得分:0)
我的解决方案是将所有Youtube播放器逻辑写在一个单独的页面中(尽可能为空白),并在IFRAME
标记中引用该页面。
<iframe src="/youtube_frame/?data=SOME_DATA -%>" height="400px" width="100%" frameborder="0" border="0" scrolling="no"></iframe>
然后,您的youtube_frame.html
将是这样的:
<!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 = "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
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
// event.target.playVideo();
}
// 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) {
console.log("OnplayerStateChange");
if (event.data == YT.PlayerState.PLAYING && !done) {
console.log("OnplayerStateChange - If statement");
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
</body>
</html>
(作为一个边缘注释:我的上下文是Prototype.js干扰事件&#39; OnStateChange&#39;,我们无法删除此依赖项。 使用jsfiddle对于重现问题没有用,因为它几乎没有依赖性。 我的应用程序是在Rails中构建的,并使用此插件显示视频播放列表:https://github.com/Giorgio003/Youtube-TV/)