YouTube embed player not working in Javascript - javascript

Since a couple of days, code which worked fine to embed a YouTube video via Javascript stopped working. Now the video loads but it is not playable (the play button is not clickable), with this error in the console:
Uncaught TypeError: a.g.mX is not a function
at O_ (https://www.youtube.com/yts/jsbin/player-en_US-vfl8LqiZp/base.js:3796:24)
at new P_ (https://www.youtube.com/yts/jsbin/player-en_US-vfl8LqiZp/base.js:3791:111)
at new c2 (https://www.youtube.com/yts/jsbin/player-en_US-vfl8LqiZp/base.js:3985:268)
at new i2 (https://www.youtube.com/yts/jsbin/player-en_US-vfl8LqiZp/base.js:4005:210)
at i2.create (https://www.youtube.com/yts/jsbin/player-en_US-vfl8LqiZp/base.js:6950:321)
at zh.<anonymous> (https://www.youtube.com/yts/jsbin/www-embed-player-vflxTxlSH/www-embed-player.js:428:269)
at zh.k.lb (https://www.youtube.com/yts/jsbin/www-embed-player-vflxTxlSH/www-embed-player.js:428:308)
at Dh (https://www.youtube.com/yts/jsbin/www-embed-player-vflxTxlSH/www-embed-player.js:426:143)
at zh.k.pa (https://www.youtube.com/yts/jsbin/www-embed-player-vflxTxlSH/www-embed-player.js:419:176)
at https://www.youtube.com/yts/jsbin/www-embed-player-vflxTxlSH/www-embed-player.js:461:420
The JS code is as follows:
document.getElementById('player').setAttribute("style","height:"+(window.innerHeight * 0.87)+"px;");
document.getElementById('youtube_frame').src="http://www.youtube.com/player_api";
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: "100%",
width: "100%",
videoId: start_video,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
player_ref = event.target;
event.target.playVideo();
}
// when video ends
function onPlayerStateChange(event) {
if(event.data === 0) {
event.target.loadVideoById(start_video);
}
}
Playback also broke on another prototype that I run. Everything used to work fine until a couple of days ago. I cannot find anything online, perhaps someone can shed some light?
----- UPDATE ----
Embedding playback is broken again:
Uncaught TypeError: a.g.setActionHandler is not a function
at M_ (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:3788:24)
at new N_ (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:3783:111)
at new a2 (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:3978:367)
at new g2 (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:3999:210)
at g2.create (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:6995:333)
at Gi.<anonymous> (https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:507:269)
at Gi.l.jb (https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:507:308)
at Ki (https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:505:143)
at Gi.l.oa (https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:498:176)
at https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:557:378

The issue has been resolved by Google and now YouTube videos play ok!
Wonder what happened?
----- UPDATE 23/02/2017 ------
Embedding playback is broken again:
Uncaught TypeError: a.g.setActionHandler is not a function
at M_ (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:3788:24)
at new N_ (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:3783:111)
at new a2 (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:3978:367)
at new g2 (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:3999:210)
at g2.create (https://www.youtube.com/yts/jsbin/player-en_US-vflqOi6vK/base.js:6995:333)
at Gi.<anonymous> (https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:507:269)
at Gi.l.jb (https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:507:308)
at Ki (https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:505:143)
at Gi.l.oa (https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:498:176)
at https://www.youtube.com/yts/jsbin/www-embed-player-vfl-i_LLs/www-embed-player.js:557:378

I have this problem in Chrome 56.0.2924.87 (64-bit) when "experimental functions" are enabled.
base.js:7046 Uncaught TypeError: a.g.setActionHandler is not a function
at bY (https://www.youtube.com/yts/jsbin/player-ru_RU-vfleBND20/base.js:3618:24)
at new cY (https://www.youtube.com/yts/jsbin/player-ru_RU-vfleBND20/base.js:3613:111)
at new z1 (https://www.youtube.com/yts/jsbin/player-ru_RU-vfleBND20/base.js:3983:268)
at new j2 (https://www.youtube.com/yts/jsbin/player-ru_RU-vfleBND20/base.js:4044:209)
at Object.j2.create (https://www.youtube.com/yts/jsbin/player-ru_RU-vfleBND20/base.js:7045:317)
at Object.ytplayer.load (https://www.youtube.com/watch?v=n-AdoTkXwbc:241:75024)
at https://www.youtube.com/watch?v=n-AdoTkXwbc:241:75172
at https://www.youtube.com/watch?v=n-AdoTkXwbc:241:75181
We can disable this option here: chrome://flags/#enable-experimental-web-platform-features
-- UPDATE 10.03.2017 --
Chrome 57.0.2987.98 (64-bit) is published today and works fine!

Whatever the current problem is it is related to the MediaSession object while trying to attach an event (play in this case). This object is internal to Chrome so it seems something is corrupt there.
I'm seeing the same problem on any other website that uses YouTube - so don't waste your time trying to debug your own site. That's not the problem.
I've rebooted and tried to disable all extensions. Not seeing any fixes yet.
Mainly wanted to post this so people don't waste time thinking their code is bad.

Related

Is there a way to get OscillatorNode to produce a sound on an iOS device?

I'm working on a music web app that has a piano keyboard. When a user presses a piano key, I'm using OscillatorNode to play a brief tone corresponding to the key:
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
function playNote(note) {
let oscillator;
let freq = notes[note];
console.debug(note + " (" + freq + " Hz)");
oscillator = audioCtx.createOscillator(); // create Oscillator node
oscillator.type = wavetypeEl.val(); // triangle wave by default
oscillator.frequency.setValueAtTime(freq, audioCtx.currentTime); // freq = value in hertz
oscillator.connect(audioCtx.destination);
oscillator.start();
oscillator.stop(audioCtx.currentTime + 0.5);
}
$('#keyboard button').on('click', (e) => {
playNote(e.target.dataset.note);
});
This works on all the desktop and Android browsers I've tried, but iOS stubbornly refuses to play any sound. I see that I need a user interaction to "unlock" an AudioContext on iOS, but I would have thought calling playNote() from my click function would have done the trick.
According to Apple, I should be able to use noteOn() on my oscillator object, instead of oscillator.start() the way I've got it in my example. But that doesn't seem to be a valid method.
I must be missing something simple here. Anybody know?
If everything seems to be working fine it could be that the device itself is on mute. For some reason (or for no reason at all) Safari doesn't play any sound coming from the Web Audio API when the device is muted. But it plays everything else.
There are some hacky ways to circumvent this bug which basically work by playing something with an audio element first before using the Web Audio API.
unmute-ios-audio is for example a library which implements the hack mentioned above.
I have an iPhone XS Max and the demo works on it producing sound as you have it right now... I've also read that for iOS the element needs both onClick handler and a style of {cursor: pointer} set to work properly.(as of a few years ago) seems like it's working though.

JavaScript play() function does not working in Chrome

I created an audio object and want to play it when user leave the window. So, my code is here:
$('body').on('mouseleave', function(){
var audio = new Audio( 'quite-impressed.mp3' )
audio.play()
})
It works well in Firefox. It also works in Chrome if I click in the page and then leave mouse outside of the body. But, when I leave the mouse without clicking in the page an error showed in the console and the audio does not play
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
But, in this example site it works fine without interacting with the page. How can I make it possible? Thanks in advance.
It seems they use an AudioContext to play that sound.
Chrome did came back a few months ago about blocking the AudioContext API, because a lot of fair uses were not prepared for such restriction and thus got broken by it.
But M71, which will get released in December 2018 will reenable that restriction, you can read about it here: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes#webaudio
// this will work in Chrome < 70 but not af
onmouseout = e => {
const ctx = new AudioContext();
const osc = ctx.createOscillator();
osc.connect(ctx.destination);
osc.start(0);
osc.stop(1);
}
Outsourced live example, since Stacksnippets are always granted the user gesture anyway: https://jsfiddle.net/zy3ev8ka/
Try this:
window.audio = new Audio( 'quite-impressed.mp3' )
$('body').on('mouseleave', function(){
audio.play()
})
This worked for me on Chrome 77:
On address bar: chrome://settings/content/sound
Turn off "Allow sites to play sound (recommended)"
Turn it on again
if your js play function is not running and if your code is correct then this may help,you have to allow your browser to get that sound file
just goto settings =>privacy and security => site-settings =>sound.
and then add your local url at add to play section..

Getting CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED when opening video file with VIDEO.js -

The error only happens when i try to view the website(video) over the internet.
Everything works perfectly when i am running locally in visual studio and it also works perfectly when i remote desktop into the production webserver where i published the site to and browse to the site locally there.
If i had to guess it seems like something is timing out when it goes over the internet or maybe there is something on our firewall preventing the movie from streaming to me from the production webserver. I doubt the firewall is the issue because i can view other videos streamed with video.js from other sources.
My developertools console window shows this (I tried to post a screenshot but i didnt have enough rep points):
GET http://166.62.34.149/Videos/Walgreens_8700SKedzieAve.m4v net::ERR_CONNECTION_ABORTEDvideo.js:118 s.loadvideo.js:65 Tvideo.js:75 s.loadVideo.aspx?VideoName=Walgreens_8700SKedzieAve.m4v:59 (anonymous function)video.js:36 s.Hvideo.js:28 t.a.t.ua.extend.ivideo.js:6 dvideo.js:57 t.Player.t.a.extend.ivideo.js:6 dvideo.js:2 tVideo.aspx?VideoName=Walgreens_8700SKedzieAve.m4v:57 (anonymous function)
here is my code:
<script type="text/javascript">
var videoName;
//videojs.autoSetup();
videoName = document.getElementById('lblVideoName').innerHTML;
videojs('my_video_1', {}, function(){
this.src({ type: "video/mp4", src: "/Videos/" + videoName });
this.load();
this.play();
});
videojs('my_video_1').ready(function () {
// Store the video object
var myPlayer = this, id = myPlayer.id();
var aspectRatio = 478 / 850;
function resizeVideoJS() {
var width = document.getElementById(id).parentElement.offsetWidth;
myPlayer.width(width).height(width * aspectRatio);
}
resizeVideoJS();
window.onresize = resizeVideoJS;
});
function PausePlayer() {
var myPlayer = videojs('my_video_1');
myPlayer.pause();
};
</script>
I have set my IIS mime type, so that isnt the issue. Any help you have provide would be greatly appreciated.
Thanks everyone!
I know this is an old oner but just to let you know that I came across this with our website and after digging deep into mime types, changing sources, removing cache and so on, a simple options --> advanced --> "Reset" made everything work fine.
This will obviously only be the case if you can test it working on other PC's somewhere else to confirm all the mime types and video work in the first place.
Hope this is of help to someone in the future as it was the top Google result for me.
Regards
Liam

new YT.Player() working in development but not production

It seems that new YT.Player() is working in development but not production.
var player = new YT.Player(domId, {
events: {
onReady: function() {
// because of a bug in the youtube iframe api
var p;
player.addEventListener('onStateChange', function(e) {
if (e.data === 1) {
p = $interval(function() {
var elapsedTime = Math.floor(player.getCurrentTime());
$scope.skim.sections[len-1].startTime = elapsedTime;
setHMS($scope.skim.sections[len-1], elapsedTime);
}, 1000);
}
else {
$interval.cancel(p);
}
});
console.log("onReady fired");
updateStartTimeAndSeekTo($scope.skim.sections[len-1]);
player.pauseVideo();
}
}
});
This code is supposed to update some input fields when the video plays. It does this in development, but not production.
This is the live page. This is a video explaining how it is supposed to work. And this is the relevant GitHub code.
I really don't know how to debug this.
For some reason the console.log() statements don't seem to be appearing in production. Without those I don't know what to do.
I checked the network tab and it seems that the api code is being downloaded successfully.
And heroku logs shows no errors.
<iframe style="height: 156.443444006753px;" src="https://www.youtube.com/embed/3eMA0GvpXl0?showinfo=0&enablejsapi=1&origin=http://localhost:9000" ng-class="{ 'unloadedFrame': !skim.videoUrl }" class="subsection-iframe" responsive-height="" resize-on-load="" allowfullscreen="" frameborder="0" ng-src="skim.embedUrl" id="subsection-0-0"></iframe>
Check the iframe source url contain origin=http://localhost:9000 hardcoded. If you removed the origin parameter from url. It started working.
The problem could be in the production environment config file. Adding
config.assets.debug = true to production.rb fixed it for me.

YouTube embed API issue on IOS and Android

An issues popped up in the last few days with the YouTube embed API. The issue is that when you embed a video with the official API, it simply doesn't allow you to access to the API. When you try to access to the API, you got error message on the log (IOS) and if you try to play the video through the API the video blacks out. If you load it via the API, but you do not use the API, the user is able to play the video with tap.
The issue persist on the following browsers:
IOS 7 Safari on iPad and iPhone
IOS 7 Chrome on iPad and iPhone
Android 4 Chrome
(My play button uses the API to play the video and that produce the error)
JSfiddle: http://jsfiddle.net/frdd8nvr/6/
Error message:
Unable to post message to https://www.youtube.com. Recipient has origin http://fiddle.jshell.net.
postMessage[native code]:0
Jwww-widgetapi.js:26:357
Nwww-widgetapi.js:25
(anonymous function)[native code]:0
html5player.js:1201:97
Blocked a frame with origin "https://www.youtube.com" from accessing a frame with origin "http://jsfiddle.net". The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "http". Protocols must match.
Some debug info:
As I see the API create the iframe on the site. The src is sometime http and sometime https.
http://www.youtube.com/embed/ZPy9VCovVME?enablejsapi=1&origin=http%3A%2F%2Ffiddle.jshell.net&autoplay=0&modestbranding=1&wmode=opaque&forceSSL=false
My test showed that most of the times YouTube servers simply LOCATION: https://... the request to the https url, but around 10% they served the http request with proper content.
I think somehow the issue related with the forced https, but I was not able to figure out the solution.
Have you experienced the same? Do you have some kind of solution for this problem? Is it a YouTube bug?
My test code:
<div id="myvideo"></div>
<button id="play-button">Play</button>
JS:
var tag = document.createElement("script");
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
onYouTubeIframeAPIReady = function () {
var vars = {
enablejsapi: 1,
origin: window.location.protocol + "//" + window.location.host,
autoplay: 0,
modestbranding: 1,
wmode: "opaque",
forceSSL: false
};
if (+(navigator.platform.toUpperCase().indexOf('MAC') >= 0 && navigator.userAgent.search("Firefox") > -1)){
vars.html5 = 1;
}
var playerobj = new YT.Player('myvideo', {
videoId: 'ZPy9VCovVME',
wmode: 'opaque',
playerVars: vars,
events: {
onReady: function(){
$('#play-button').on('click', function(){
playerobj.playVideo();
});
//playerobj.playVideo();
},
onStateChange: function(state){
switch(state.data){
case YT.PlayerState.PLAYING:
break;
//case YT.PlayerState.PAUSED:
case YT.PlayerState.ENDED:
break;
}
}
}
});
}
First, I think this is a duplicate of the following question: YouTube IFrame API play method doesn't work before touch on some Android tablets
I could reproduce the same problem on the YouTube Player Demo page.
The error
Unable to post message to https://www.youtube.com. Recipient has origin http://fiddle.jshell.net.
is only occuring on your jsfiddle. On the demo page this error is not occuring, therefore your observed bug seems not to be related to the error logged in the console. I checked this with chrome on Android 4.4.4.
Workaround
I have a dirty workaround which works on chrome on Android 4.4.4 (Nexus5) and 4.1.2 (S2). I have no iOS Device to test this. The workaround works on my phones, because the video always starts the second time I click the play-button.
http://jsfiddle.net/kjwpwpx8/6/
I can always start the video on click-Events after the playVideo function was called once before. In my workaround I put two iframes on the page. One is hidden while the other one is visible. If the page is viewed by a mobile browser I call the playVideo function of the second video after the OnReady-Event. The video won't play as the browser blocks this.
Now when our play-button is pressed the first video becomes hidden and stopped and the second video becomes visible and the playVideo function is called again.
Here is the important code:
var playerOptions = {
videoId: 'ZPy9VCovVME',
wmode: 'opaque',
playerVars: vars,
events: {}
};
var playerobj1 = new YT.Player('myvideo1', playerOptions);
var playerobj2 = null;
playerOptions.events.onReady = function(){
$('#play-button').on('click', function(){
$("#videowrapper .video1wrapper").hide();
playerobj1.stopVideo();
$("#videowrapper .video2wrapper").show();
playerobj2.playVideo();
});
if(isMobileBrowser)
playerobj2.playVideo();
};
playerobj2 = new YT.Player('myvideo2', playerOptions);

Categories

Resources