player.mute() not working in YouTube API with playlist - javascript

I want to mute a video after it plays for 9 seconds. I tested various things including cuePlaylist and other stuff.
Following is the code -
<div id="topplayer" align="center"></div>
<script>
jQuery(document).ready(function( $ ) {
var done = false;
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
});
function onYouTubeIframeAPIReady() {
topplayer = new YT.Player('topplayer', {
height: '315',
width: '560',
events: {
'onReady': onTopPlayerReady,
'onStateChange': onTopPlayerStateChange
}
});
}
function onTopPlayerReady(event) {
event.target.loadPlaylist({
listType:'playlist',
list: 'PL55713C70BA91BD6E',
index: 0,
});
event.target.playVideo();
}
function onTopPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(muteVideo, 9000);
done = true;
}
}
function muteVideo() {
topplayer.mute();
}
</script>
Now, with this code Video Playlist loads and autoruns (which I want) but it never mutes.
PS. I tried default example provided in official developers.google.com for YouTube API and changed player.stopVideo() to player.mute() and it works. So, I believe the problem is somewhere coming when am trying to load a playlist instead of a single video. The following code works well (it autoruns and mutes the video too) -
<div id="player"></div>
<script>
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() {
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();
}
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.mute();
}
</script>

You have a syntax error in your javascript; you define the done variable as local inside jQuery's ready method, and hence that variable is not available to any of the other methods (you can verify this by opening Chrome's dev tools while you run your code; you'll see that the onPlayerStateChange method is complaining that there is no done variable).
The solution would be to move the declaration of that variable outside of the ready method, like this:
var done = false;
jQuery(document).ready(function( $ ) {
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
});
Everything else can stay the same.

Related

Question about JavaScript scope and is it possible to accomplish what I am attempting to do

I am attempting to dynamically change the videoID of the YouTube API onclick. I have a list of items whose data src contains a YouTube URL. When a user clicks on a link, a modal pops up's playing that particular video. Once the video finishes, it redirects to another page.
If I hard code the ID, it works beautifully, but I cannot do that.
My only concern is I cannot get the videoID due to JavaScript scope. Is there anything you'd recommend I try?
$(document.body).on('click', ".video-btn", function (e) {
var $videoSrc = $(this).data("src");
console.log($videoSrc);
var **getVidID** = $videoSrc.substring(26);
console.log(getVidID);
});
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
playerVars: {
'controls': 0
},
width: 1920,
height: 1080,
videoId: **getVidID,** I'd like to use the videoID here
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
};
function onPlayerReady(event) {
event.target.playVideo();
};
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED && !done) {
alert('Taking you to Review Material Now..')
window.location.replace("http://www.google.com");
done = true;
}
};
Here's one way to do it:
var getVidID;
$(document.body).on('click', ".video-btn", function (e) {
var $videoSrc = $(this).data("src");
console.log($videoSrc);
getVidID = $videoSrc.substring(26);
console.log(getVidID);
});
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
console.log(getVidID);
player = new YT.Player('player', {
playerVars: {
'controls': 0
},
width: 1920,
height: 1080,
videoId: **getVidID,** I'd like to use the videoID here
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
};
Be aware: getVidID may not have a value, depending on where/when you call onYouTubeIframeAPIReady(). The click event function must run before it gets the id. So, you may want to validate that it has a value before you use it in that other function. Also, be aware that the value of that variable only changes when the click event fires...

Cannot fire "loadVideoByUrl('...')" of Youtube's Iframe-API – undefined

it seems that I am missing something obvious here but I can not get
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() {
player = new YT.Player('player1');
// here everything is fine and I can see the
// function as part of player
console.log(player);
// but here it says "player.loadVideoByUrl()" undefined
player.loadVideoByUrl("https://youtu.be/bHQqvYy5KYo");
player.playVideo();
}
to work. Any ideas?
Thanks in advance!
I assume that player is not initialized while you're calling the loadVideoByUrl function. In documentation, they use
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
events of player. It seems player object constructs asynchronously. So if you use those events, code becomes like below:
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() {
player = new YT.Player('player1', {
events: {
'onReady': onPlayerReady
}
});
}
function onPlayerReady(){
player.loadVideoByUrl("https://youtu.be/bHQqvYy5KYo");
player.playVideo();
}

Embed youtube APi Custom button

im customizing my youtube player, but im getting a error, i already check if the problem was not wrapping in a ready function, but still getting the error
"Uncaught ReferenceError: YT is not defined"
Js:
//youtube script
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
onYouTubeIframeAPIReady = function () {
player = new YT.Player('player', {
height: '193',
width: '284',
videoId: 'jGa2J3RBPtQ', // youtube video id
playerVars: {
'autoplay': 0,
'rel': 0,
'showinfo': 0
},
events: {
'onStateChange': onPlayerStateChange
}
});
}
onPlayerStateChange = function (event) {
if (event.data == YT.PlayerState.ENDED) {
$('.start-video').fadeIn('normal');
}
}
$(document).on('click', '.start-video', function () {
$(this).fadeOut('normal');
player.playVideo();
});
html:
<div id="player"></div>
<button class="start-video">Play</button>
Have you tried switching to the HTTPS protocol?
Worked for me here
tag.src = "https://www.youtube.com/iframe_api";

Multiple iframe embeds with youtube api

My coding knowledge is mostly self-taught and limited.
I have a forum which I have set to replace youtube URLs in posts with iframe embeds of the video. The one unique aspect to it was that it was forcing the embeds to play at 720p quality (if available) even if the player was smaller than youtube recommends. The "why" is a long story but I want to keep doing it that way. I'm trying to get the same thing working with the new API.
In the sample code below I can get it working for one video on a page but not both on the same page. I imagine it has something to do with duplicate functions or something along those lines.
<html><body>
<script>
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 xyzplayer;
function onYouTubeIframeAPIReady() {
xyzplayer = new YT.Player('xyzplayer', {
events: {
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
event.target.setPlaybackQuality('hd720');
}
}
</script>
<iframe id="xyzplayer" type="text/html" width="832" height="468" src="http://www.youtube.com/embed/M7lc1UVf-VE?enablejsapi=1&html5=1" frameborder="0"></iframe>
<br><br><br>
<script>
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 abcplayer;
function onYouTubeIframeAPIReady() {
abcplayer = new YT.Player('abcplayer', {
events: {
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
event.target.setPlaybackQuality('hd720');
}
}
</script>
<iframe id="abcplayer" type="text/html" width="832" height="468" src="http://www.youtube.com/embed/IwfUnkBfdZ4?enablejsapi=1&html5=1" frameborder="0"></iframe>
</body></html>
Because your code is loading the library twice, the second load overrides the functions you're defining in the first and hence events from the first one will never be handled. Try combining the player creation into a single method ... something like this (so that players for both embeds get their events listened to):
<html><body>
<iframe id="xyzplayer" type="text/html" width="832" height="468" src="http://www.youtube.com/embed/M7lc1UVf-VE?enablejsapi=1&html5=1" frameborder="0"></iframe>
<br/><br/><br/>
<iframe id="abcplayer" type="text/html" width="832" height="468" src="http://www.youtube.com/embed/IwfUnkBfdZ4?enablejsapi=1&html5=1" frameborder="0"></iframe>
<script>
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 abcplayer,xyzplayer;
function onYouTubeIframeAPIReady() {
abcplayer = new YT.Player('abcplayer', {
events: {
'onStateChange': onPlayerStateChange
}
});
xyzplayer = new YT.Player('xyzplayer', {
events: {
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
event.target.setPlaybackQuality('hd720');
}
}
</script>
</body></html>

Youtube iFrame (with javascript API) loads the first time, but not the second one. Why?

I am using the iFrame Youtube API with the following code. I call this view with Ajax to render it and append it in a div.yt-player within my page. It works the first time I call the view, but after I close the video (it empties the div.yt-player) and click on another link that calls my view, the video doesn't load at all (blank). I've been struggling and still don't see why it happens, especially that it works the first time. Any kind of help would be much appreciated.. Thanks.
PS: Both the html and the javascript are rendered by the view.
Html
<div id="player"></div>
Javascript:
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() {
player = new YT.Player('player', {
height: '486',
width: '864',
videoId: '#{#media['youtube_url']}',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
},
playerVars: {
'showinfo': 0,
'iv_load_policy': 3,
'color': 'white',
'fs': 1,
'autoplay': 1,
'vq': 'hd720'
}
});
}
function onPlayerReady(event) {
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();
}
Just check if the script has been defined.
if(document.getElementById('iframe_api') === null){
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
tag.id = "iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
}
else
runPlayer();
function runPlayer(){
var player;
player = new YT.Player(element.children()[0], {
playerVars: {
autoplay: 1,
html5: 1,
controls: 1,
showsearch: 0,
showinfo: 0
},
height: scope.height,
width: scope.width,
videoId: scope.videoid,
events: {
onStateChange: function (event) {
if (event.data == YT.PlayerState.ENDED) {
scope.$emit('VideoEnded');
}
}
}
});
}
$window.onYouTubeIframeAPIReady = function () {
runPlayer();
};
I debugged the problem. onYouTubeIframeAPIReady() is called only the first time the YouTube API is loaded (when the user refreshes the page and clicks on the link to the view for example), and because I'm calling my views in Ajax, it didn't get fired up the following times.
So I replaced the first block of code by wrapping it in a conditional:
if (typeof youtube_api_init == 'undefined') {
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
}
and
if (typeof youtube_api_init != 'undefined') {
onYouTubeIframeAPIReady();
}
and at the end of the script, I set the youtube_api_init for the browser to remember the YouTube API has already been loaded:
var youtube_api_init = 1;
PS: the first time I tried, I called my variable yt_api_init instead of youtube_api_init, and it didn't work cause it happens that's a name YouTube already uses in its api...

Categories

Resources