Has YouTube started locking down cross origin requests?
I am using a fullscreen autoplay hero video on my website and it has been functioning correctly for a long time. Within the last couple weeks it stopped working and I have the following error in the logs.
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://www.youtube.com') does not match the recipient window's origin ('https://tbrogames.github.io').
Per the answer on this question
I tried changing the host between http and https to see if that would fix it and it didn't.
My website that throws the error: https://tbrogames.github.io/
I was able to find a bigger games website that also has this exact issue.
https://playbattlegrounds.com/main.pu
They are also using a youtube video as the hero/splash video; and it no longer functions, throwing the same error.
The relevant javascript can be found here
https://github.com/tbrogames/tbrogames.github.io/blob/master/js/defer.js
However, this was working for a long time and I didn't change any of the code. Which is why I'm thinking that it is a change that YouTube has made.
I think that error is actually misleading. I had the same issue, but I believe that it is actually chrome that is no longer autoplaying the hero. I get this error: Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first. https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
The fix for me was calling mute on the video in Javascript Before playing the video. The iframe version of the embed with the same properties would not autoplay
<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('ythero', {
videoId: '3FjTef9gn3Q',
height: '100%',
width: '100%',
playerVars: {
rel: 0,
controls: 0,
showinfo: 0,
autoplay: 1,
loop: 1,
playlist: '3FjTef9gn3Q',
modestbranding: 1
},
events: {
'onReady': onPlayerReady,
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.mute();
event.target.playVideo();
}
</script>
YouTube does allow it. Make sure you are loading from a URL such as:
https://www.youtube.com/embed/HIbAz29L-FA?modestbranding=1&playsinline=0&showinfo=0&enablejsapi=1&origin=https%3A%2F%2Fintercoin.org&widgetid=1
Note the "origin" component, as well as "enablejsapi=1". The origin must match what your domain is, and then it will be whitelisted and work.
Related
I'm getting this error: Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('<URL>') does not match the recipient window's origin ('<URL>').
My page operates as I'd hoped (I don't notice any unwanted behavior), but I never like ignoring errors in my console, especially if I don't even understand the root cause.
My question is NOT A DUPLICATE because I've already studied all of these questions but none of the answers worked:
Failed to execute 'postMessage' on 'DOMWindow': https://www.youtube.com !== http://localhost:9000
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided does not match the recipient window's origin ('null')
Youtube API - Failed to execute 'postMessage' on 'DOMWindow'
YouTube API and cross origin requests
YouTube iFrame Player API failed to execute postMessage on DOMWindow
Failed to execute 'postMessage' on 'DOMWindow': target/origin mismatch http vs https
I'm already using https.
I've already tried setting playerVars to {origin: window.location.origin}.
I've already tried setting host.
I've already tried changing the visibility of the iframe.
And so on.
var playerVars = {origin: window.location.origin};//https://stackoverflow.com/a/50518247/470749
window.onYouTubeIframeAPIReady = function () {
for (var i = 0; i < youtube.length; i++) {
var youtubeLazyEl = youtube[i];
var videoId = youtubeLazyEl.dataset.v;
players[videoId] = new YT.Player(videoId, {
videoId: videoId,
//host: 'https://www.youtube.com', //https://stackoverflow.com/a/47914456/470749
//playerVars: playerVars,
});
}
};
Ideas?
As you seem to be using lazy loading, try removing the iframes HTML attribut loading="lazy" - that solved the issue for me.
TLDR; not really an answer, but may possibly assist the google engineers in tracking down this issue.
I have noticed the issue only surfaces for me when creating more than one player.
I've a page that creates multiple players to populate a scroll view.
I noticed I was getting one less error message than there were players created, so added a switch that forces the page to only create one player then ignore all other requests.
custom switch code: permalink
createOnePlayerOnly = location.search.indexOf('oneplayer')>=0 ? true : false,
this causes a single player to load fine, with no errors (there are other errorsrelated to a chromecast extension no longer shipped with chrome, which are unrelated AFAIK)
each player is always created via the same code which always sets the origin and widget
playerVars: info.playerVars || {
fs: 1,
controls: 0,
playsinline: 0,
enablejsapi: 0,
modestbranding: 1,
disablekb: 1,
autohide: 1,
autoplay: 0,
loop: 0,
volume: 0,
iv_load_policy: 3,
origin: location.href,
widget_referrer : location.href
}
So it's possible that the iframe code doesn't pick up the origin value from the options correctly when additional players are made. not sure why that might be, but it might be to do with caching, or scoping issues.
I think we could customize the sendMessage of the YT.Player
playerOptions.playerVars.origin = window.location.origin or your domain.
this.youtubePlayer = new YT.Player(element,playerOptions);
this.youtubePlayer.sendMessage = function (a) {
a.id = this.id, a.channel = "widget", a = JSON.stringify(a);
var url = new URL(this.h.src), origin = url.searchParams.get("origin");
if (origin && this.h.contentWindow) {
this.h.contentWindow.postMessage(a, origin)
}
}
I used this function to resolve in my project.
My Origin answer
I'm using Youtube iframe API to add a video to my page, but it's showing related videos when the video is about to end even though i have set the 'rel' parameter to 0.
Here is the concerned part of my code:
function onYouTubeIframeAPIReady() {
player = new YT.Player('homeplayer', {
height: '1070',
width: '1920',
videoId: videoID,
playerVars: {
'controls': 0,
'loop': 1,
'modestbranding': 1,
'rel': 0,
'showinfo': 0,
'playlist': videoID
},
events: {
'onReady': onPlayerReady
}
});
}
Maybe this question has already been asked but i can't find a solution as youtube api has been updated multiple times.
The functionality of the rel parameter has changed; in August of 2018, YouTube deprecated it and in September of 2018 they modified the player API so you can no longer hide related videos. Rather, if you set rel to 0, the embedded player will only show related videos from the channel that the just-played video is from. If you omit rel, then the embedded player will show related videos from anywhere on YouTube. There is no longer any way to remove related videos altogether.
See https://developers.google.com/youtube/player_parameters#release_notes_08_23_2018 for more details.
I am trying to play embed videos in my webpage, in desktop browser there is no problem, but in mobile version I have these issues:
Video wont start automaticaly
There is Dailymotion logo in right bottom corner
I am using DM object provided by file https://api.dmcdn.net/all.js.
Code:
<script src="https://api.dmcdn.net/all.js"></script>
<script>
DM.init({
apiKey: 'correct api key',
status: true, // check login status
cookie: true // enable cookies to allow the server to access the session
});
</script>
<div id="player{$img->getId()}" class="dailymotion tile"></div>
<script>
$(function () {
var player{$img->getId()} = DM.player(document.getElementById("player{$img->getId()}"), {
{var DMurl = explode("/", $img->getImgUrl())}
video: {$DMurl[count($DMurl) - 1]},
width: "100%",
height: "100%",
params: {
autoplay: true,
mute: true,
endscreen-enable: false,
ui-logo: true,
controls: false
}
});
player{$img->getId()}.play();
});
</script>
My problem might be caused by syntax error in params (endscreen-enable and ui-logo, phpstorm is showing syntax error because of '-' char)
Video wont start automatically
=> this is normal on mobile devices, it will be the same for any video you add, from any provider. The reason is that most mobile devices prevent videos from being played automatically, hence the play must be triggered by a user interaction. This is detailed on Dailymotion developer website at : https://developer.dailymotion.com/player/faq#player-faq-autoplay-does-not-work-on-mobile
There is Dailymotion logo in right bottom corner
=> you pass ui-logo: true so this is normal !
I'm currently loading the YouTube API like so:
$(function () {
// This code will trigger onYouTubePlayerAPIReady
$('<script>', {
src: 'https://s.ytimg.com/yts/jsbin/www-widgetapi-vflwt8QCF.js',
async: true
}).insertBefore($('script:first'));
});
I was looking at the YouTube demo page, https://developers.google.com/youtube/youtube_player_demo, and I noticed in their source that they were using a different URL to load their widget API:
<script src="https://s.ytimg.com/yts/jsbin/www-widgetapi-vfl4qCmf3.js" async></script>
I thought that this might be a more up-to-date version of their API. So, I swapped it out, but I receive an error message:
Uncaught ReferenceError: YTConfig is not defined
I'm left wondering which of these is the correct location, if either, to be loading the most up to date widgetapi data from. Is there a location for this info?
to get the latest API version I suggest to use example from YT reference:
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
this'll make sure the latest version is being loaded
if you really need to grab latest version for some reason just check this url:
https://www.youtube.com/iframe_api
and get it from the source code
Hello all and thanks for any help in advance.
I have a ruby on rails application in which I am attempting to stream audio through jPlayer, which is hosted on S3. So far I have no problem uploading files or using the browsers built in player to play audio files, or even getting jPlayer to initialize with a song that is on S3. The issue comes when I get into changing songs.
I initialize jPlayer like this:
$('a.html5').click(function() {
var url = $(this).attr('href');
$("#jquery_jplayer_1").jPlayer({
ready: function (event) {
$(this).jPlayer("setMedia", {
mp3: url
});
},
swfPath: "javascripts",
supplied: "mp3",
wmode: "window"
});
return false;
});
where the mp3: url points to the S3 URL (this all works just fine).
This allows me to select a song from a list of links, and it loads up and starts playing no problem.
The issue is that when I try to change songs, I get an access-control-allow-origin error. So I tried the following:
$('a.html5').click(function() {
var url = $(this).attr('href');
$("#jquery_jplayer_1").jPlayer("setMedia", mp3: url).jPlayer("play");
return false;
});
This still gives me an access-control-allow-origin error. I have been pounding my head against the wall for hours trying to figure this out and nothing.
So basically a summary is that I can initialize jPlayer and play a song just fine, but when I want to go change a song, access-control-allow-origin errors ruin my day.
Any ideas?
Well it appears that the only issue was a lack of brackets around the mp3: url part of jPlayer("setMedia"....
so it should have been (...).jPlayer("setMedia", {mp3: url}).(...)
After Searching a lot it could be one of the solutions too.
function songs(json1) {
$("#jquery_jplayer_1").jPlayer("destroy"); //this will destroy previous jplayer content and then if you again call this function it will add the new url of you audio song to the jplayer
var audio_url_inside = json1.audio_url;
$('#jquery_jplayer_1').jPlayer({
ready:function (event) {
$(this).jPlayer("setMedia", {
mp3:audio_url_inside,
oga:audio_url_inside
}).jPlayer("play"); //attemp to play media
},
swfPath:"http://www.jplayer.org/2.1.0/js",
supplied:"mp3, oga"
});
}
:Hope it will help.