Youtube API calling player functions after player is initated - javascript

This is my first use of the youtube api and I'm finding it hard understanding the documentation. Basically I have multiple videos on the page, when you click one it pops up in a lightbox and plays the correct video. All of this works fine.
The client now wants all the videos to be automatically muted on start, and once you finish the video they want the frame to skip to the right place.
If I use the youtube iframe api i can't seem to be able to update the videoId at all. Below is my code:
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '323',
width: '576',
videoId: 'Fy7Li0dMRSY',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
event.target.mute(); // this does not do anything
event.target.playVideo();
}
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
//setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
function loadVid(vidID, title){
// loads youtube video with video title & youtube video ID
$('.lightbox .title').html(title);
$('.lightbox iframe').prop('src','https://www.youtube.com/embed/'+vidID+'?rel=0&wmode=transparent&enablejsapi=1');
//player.mute() does not work here
showLightbox();
}
My problem is trying to call the player function to mute inside the loadVid function, it throws back an error (any function throws the same error) and I can't figure out how to use functions such as player.
The error is player.stopVideo is not a function
So how can I mute the video on start? Adding it to onPlayerReady does not work either.

Move the event.target.mute(); to the onPlayerStateChange function like this:
var done = false;
function onPlayerStateChange(event) {
event.target.mute();
if (event.data == YT.PlayerState.PLAYING && !done) {
//setTimeout(stopVideo, 6000);
done = true;
}
}

When you have multiple videos on the page, you still have to call onYouTubePlayerAPIReady for each one. You can pack all your player handlers in there at the same time, but depending on how you have to do it, that's not possible. Instead, you have to figure a way to trick the API. Take a look at my answer here loading multiple video players with youtube api

Related

player.stopVideo, player.playVideo, etc. not working outside of event functions calls with youtube-api

I am trying to create a button that allows the user to click it and stop the embedded youtube video. However, whenever I try and call the player object itself to use the function player.playVideo() I get an error saying the function is not defined.
Player is globally defined and set when the Youtube API loads (just like the tutorial on their website). Function calls to playVideo work just fine when events trigger their usage, but using it outside of those simply do not work.
'''javascript
// 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);
var player;
function onYouTubeIframeAPIReady() {
isReady=true;
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
playVideo();
}
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.pauseVideo();
}
function playVideo() {
player.playVideo();
}
//The function that is run when the button is pressed, only in this case
// stopVideo not work!
function togglePlay() {
if(isPlaying) {
stopVideo();
} else {
playVideo();
}
}
'''
Expected: Youtube video plays
Actual: Error player.playVideo is not a function
I solved the issue. Something weird happens with even setting up buttons with onclick functions that use the player before the player is finished loading. To solve this, I moved all button declarations and functions inside the onPlayerReady(event) function and used event.target.play or event.target.pause and that worked perfectly. My advice is just to contain any declarations of buttons that use the youtube player functions inside of the onPlayerReady.

Autoplay videos from google drive and alert when they finish JavaScript

This is the code I use for autoplaying youtube videos:
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '970',
width: '100%',
videoId: videos[index],
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// autoplay video
function onPlayerReady(event) {
event.target.playVideo();
}
// when video ends
function onPlayerStateChange(event) {
if(event.data === 0) {
location.reload();
}
}
And the html:
<script src="http://www.youtube.com/player_api"></script>
videos[index] - A variable in which all the videos are stored.
Is there any variation of the code that can play videos from google drive (or basically any code that can autoplay the video and alert when it's finished, it has to be in js)
I have looked for solutions to my problem for a few hours now and I tried them all out but without any success.
Does anyone have an idea on how I could accomplish this through JavaScript?
The answer is NO because Google Drive doesn't have an API, and it doesn't work like Youtube.

Youtube player.destroy(); throws 'this.a is null', even when validating player

So I've got a small app with two panels. Using the iframe API. Clicking on one panel will expand the panel full screen, as well as showing a 'play video' button with some additional information. Clicking a button in the top left will return the UI to it's standard state, closing down the video and shrinking the panels back to fit 50/50.
Now as we've got two videos, I've defined the videos as such, #vidPlayer2 being the second trigger.
$('#vidPlayer1').on('click', function(){
player = new YT.Player('player', {
height: '100%',
width: '100%',
videoId: '(video id here)',
controls: 0,
showinfo: 0,
autoplay: 0,
rel: 0,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
Similarly, we've got the default demo code, with a small modification:
function onPlayerReady(event) {
event.target.playVideo();
}
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
done = true;
}
if (event.data == YT.PlayerState.ENDED) {
resetView();
}
}
function stopVideo() {
player.stopVideo();
}
Then, we're trying to get the button to work. In some circumstances, not having clicked one of the vidPlayer buttons, no player is defined, so I threw in an if statement with some validation.
var resetView = function() {
// If a Youtube player is active, make sure we stop it.
if (player === undefined || !player || null) {
console.log("Player could not be found.");
} else {
player.stopVideo();
player.destroy();
}
// Additional code to reset the UI removed below. Works no matter what if the above code is removed.
};
Now for the most part, things work well UNTIL I try to go into a panel, play a video, reset UI, then try to enter and leave the next panel without playing a video. When I follow this exact series of steps, regardless of what panel starts first, I get a TypeError: this.a is null in console. I would've assumed that the validation would've done the trick, but apparently not.
So what I can distinguish from this is it works fine when initialized - i.e. var player is initialized. The return button works through just going back and forth without playing a video. The return button works when a video is actively playing, but the function fails if we try to use the return directly after the player is stopped and destroyed. It does work if we simply pop open another video, however.
Is there something I'm missing when I'm trying to reset the view? Does the youtube player have to be reinitialized? Any help or thoughts would be greatly appreciated. Thanks!
Edit: This is the note that's being thrown by the console. Something to note is main.js:44:5 is the player.stopVideo(); call, and main.js:70:3 is when resetView(); is called on a button click.
TypeError: this.a is null
www-widgetapi.js:120:73
f.C
https://s.ytimg.com/yts/jsbin/www-widgetapi-vflWgX7t4/www-widgetapi.js:120:73
V
https://s.ytimg.com/yts/jsbin/www-widgetapi-vflWgX7t4/www-widgetapi.js:112:97
Nb/</this[a]
https://s.ytimg.com/yts/jsbin/www-widgetapi-vflWgX7t4/www-widgetapi.js:130:124
resetView
file:///Users/cipher/Desktop/ERHS_video/js/main.js:44:5
<anonymous>
file:///Users/cipher/Desktop/ERHS_video/js/main.js:70:3
dispatch
file:///Users/cipher/Desktop/ERHS_video/js/jquery-3.2.1.min.js:3:10264
add/q.handle
file:///Users/cipher/Desktop/ERHS_video/js/jquery-3.2.1.min.js:3:8326
The problem here is player is NOT undefined. What's happening is you have a global player reference, and you're doing the following with it:
Creating a player in the first panel
Destroying it when the first panel closes
Calling player.stopVideo() on the already destroyed player (from the first panel) when the second panel closes
Currently, player holds a reference to whatever the last YouTube player you were using is, even if that player has already been destroyed.
What you should be doing is clearing out your reference to the player when you destroy it. Destroy won't (and can't) do that. You can also simplify your if condition since !player will check for null and undefined on its own:
var resetView = function() {
// If a Youtube player is active, make sure we stop it.
if (!player) {
console.log("Player could not be found.");
} else {
player.stopVideo();
player.destroy();
player = null; // Clear out the reference to the destroyed player
}
Highly inspired from IkeDoud's above answer and some others like this one, one year later, here is my way to avoid other video suggestions on play end in embedded API player:
<div id="player"></div>
<style>
#player{
min-width:auto;
min-height:auto;
}
</style>
<script>
// Load 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);
// Initialise the player with options
var player;
var playerOptions = {
videoId: 'ViDeOiD_HeRe',
events: {
'onStateChange': onPlayerStateChange
}
};
// Load the video whern player ready
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', playerOptions);
}
// On video end, reset the player back to poster image
function onPlayerStateChange(event) {
if(event.data === 0) {
$(PaReNt_sElEcToR).find("#player").replaceWith('<div id="player"></div>');
player = null;
player = new YT.Player('player', playerOptions);
}
}
</script>
No more irrelevant suggestions playable from the embedded video container.
And no autoplay (mobile forbids it anyway) to have the poster (thumbnail) image.
On event.data === 0, which is video end... Destroy and reload the Iframe.

Youtube video API onStateChange event cannot be used to change video

I want to use the onStateChange event provided by the Youtube API to listen to for the end of the video and then get a new video to play in the player. However, this does not seem to be possible for some reason.
function onPlayerStateChange(event) {
if(event.data === 0) {
console.log('done');
goNext();
}
}
function goNext() {
player.loadVideoById('JBJ1VPBrCl0', 0, 'default');
}
I register the event handler like this
player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '530',
width: '640',
videoId: '0Bmhjf0rKe8',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
Problem is: if I call my function goNext() manually, the video changes. If I wait for the video termination, the 'done' message is printed to the console, but the video does not change. Any ideas what am I doing wrong?
I've put up a fiddle here. Thanks!
http://jsfiddle.net/PHXY2/
FWIW, your fiddle example worked fine for me (after the video ends it automatically starts playing the "Short - Cat Meowing - Funny Cat Video - Red Laser" video ) Did you happen to have any YouTube-related browser extensions installed earlier? Some have been known to cause issues with the YT API.

Check if Embedded YouTube Video has Finished

So I'm writing a TamperMonkey script that sends specific videos to YouTube's embedded player however I want to automatically send them back once the video is finished.
So for example, video http://youtube.com/watch?v=XXXXX it would redirect to http://youtube.com/v/XXXXX. And then, once the video is complete, it would use window.history.go(-2) (as -1 would go to the normal page causing a loop).
The problem I'm having is that I haven't been able to get the second part, the function that runs when the video finishes, to work.
I have tried following the api and looking at other peoples problems and seeing what helped them but I can't seem to get it.
At the moment this is the code I have.
$(document).ready( function() {
var loc = document.location.href;
var l = loc.split('/');
var s = l[4];
var id = s.split('?')[0]
// create youtube player
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '100%',
width: '100%',
videoId: id,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// autoplay video
function onPlayerReady(event) {
event.target.playVideo();
alert('spotted');
}
// when video ends
function onPlayerStateChange(event) {
if(event.data === 0) {
window.history.go(-2);
}
}
});
I would appreciate it if someone would work with me to get this script working.
Thanks.

Categories