I'm really having a frustrating time handling YouTube's iFrame API. Everything was working fine until yesterday, when I noticed my .playVideo() and .pauseVideo() functions throw an "undefined is not a function" error. Now, I can see that none of my functions appear to work... the events "onready" and "onstatechange" don't appear to be firing either. Here's my code:
function addVideo(index, url){
$.getScript('https://www.youtube.com/iframe_api', function(){
processPlayer();
});
function processPlayer(){
var videos = document.getElementById("videos");
var individ = document.createElement("div");
individ.setAttribute("class", "individ");
var vid = document.createElement("div");
vid.setAttribute("id","vid"+index);
individ.appendChild(vid);
videos.appendChild(individ);
var player;
function onYouTubeIframeAPIReady() {
console.log("Are we here at least?");
player = new YT.Player('vid'+index, {
height: '165',
width: '100%',
videoId: url,
playerVars: { 'controls': 0, 'showinfo': 0, 'rel': 0},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
window.players.push(player);
//individ.innerHTML+="Added by "+namesList[index];
individ.innerHTML+="<div style='float: left;'><span class='sname'>Let it Burn</span><br/><span class='aname'>Dave Matthews Band</span></div><div style='position: relative;'><img class='s_user' src='http://i.imgur.com/1AmnCp4.png'/></div>";
window.players.push(player);
}
onYouTubeIframeAPIReady();
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
//event.target.playVideo();
console.log("We're ready");
}
// 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("HI?");
if(event.data === 0) {
if(window.currentIndex < window.players.length-1){
var videoID = window.players[window.currentIndex].getVideoUrl().split("v=")[1];
window.players[window.currentIndex].cueVideoById(videoID);
window.currentIndex++;
window.players[window.currentIndex].playVideo();
}
} else if(event.data === 2 ){
onYouTubeIframeAPIReady();
}
if(!window.playing){
//alert('playing');
window.playing = true;
} else {
//alert('stopping');
window.playing = false;
}
}
function stopVideo() {
player.stopVideo();
}
}
}
Any ideas why? I'd really appreciate some help on this. The video itself loads fine, and the YTPlayer object can be called from console... yet these functions don't work, and onready/onstatechange don't fire. The iframes by default have the "origin=" bit in there, so that fix didn't work either.
I see several problems in your code, but I'm not sure which one of them is the one that's bothering you.
First of all, you're not supposed to call onYouTubeIframeAPIReady directly.
Instead, you should execute the following and let the browser do it asynchronously:
var scriptElement = document.createElement("script");
scriptElement.src = "http://www.youtube.com/iframe_api";
var firstScriptElement = document.getElementsByTagName("script")[0];
firstScriptElement.parentNode.insertBefore(scriptElement,firstScriptElement);
Second, I believe that you should initialize at least the following player parameters:
playerVars:
{
"enablejsapi":1,
"origin":document.domain,
"rel":0
},
events:
{
"onReady":onPlayerReady,
"onError":onPlayerError,
"onStateChange":onPlayerStateChange
}
Here is the complete relevant piece of code that I have been using:
<body onload="LoadYouTubeIframeAPI()">
<div id="player">Loading Video Player...</div>
<script type="text/javascript">
var player = null;
function LoadYouTubeIframeAPI()
{
var scriptElement = document.createElement("script");
scriptElement.src = "http://www.youtube.com/iframe_api";
var firstScriptElement = document.getElementsByTagName("script")[0];
firstScriptElement.parentNode.insertBefore(scriptElement,firstScriptElement);
}
function onYouTubeIframeAPIReady()
{
var playerParams =
{
playerVars:
{
"enablejsapi":1,
"origin":document.domain,
"rel":0
},
events:
{
"onReady":onPlayerReady,
"onError":onPlayerError,
"onStateChange":onPlayerStateChange
}
};
player = new YT.Player("player",playerParams);
}
function onPlayerReady(event)
{
...
}
function onPlayerError(event)
{
...
}
function onPlayerStateChange(event)
{
...
}
</script>
</body>
Related
I have a simple Youtube API code to play videos in a playlist. All of a sudden I start getting the error like: an error occurred please try again later playback id: 2yVtrSo5yT1rs1EY
I did some searching and mainly found solutions for the PC user, like flushing cache/dns etc (I am on a windows laptop by the way).
Question: I was wondering however if it is possible to create a solution for this error(code), in the script in order to make it go to the next song? Or is this only a user based problem? I have an onPlayerError function that just makes the player go to the next song, whatever error occurs. However for the error mentioned above, it does nothing and just shows the error.
<?php
$yt_id='PLFgquLnL59anYA8FwzqNFMp3KMcbKwMaT';
$mymaxcounter = 100;
?>
<div id="player"></div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
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;
var numPl = Math.floor((Math.random() * <?php echo $mymaxcounter;?>) + 1);
var playlistId = "<?php echo $yt_id; ?>";
// 3. This function creates an <iframe> (and YouTube player)
function onYouTubeIframeAPIReady() {
player = new YT.Player("player", {
height: '390',
width: '640',
playerVars: {
autoplay: 1,
loop: 1
},
events: {
'onReady': onPlayerReady,
'onError': onPlayerError
}
});
}
// onPlayerReady
function onPlayerReady(event){
//More player vars
player.loadPlaylist( {
listType: 'playlist',
list: playlistId,
index: numPl
} );
//Set shuffle
setTimeout(function() {
player.setShuffle({'shufflePlaylist' : true});
}, 1000);
}
// onPlayerError
function onPlayerError(){
player.nextVideo();
}
</script>
Hi here i just want to know why my youtube api is not working.
my program work correctly at console.log("making youtube");
So, i search a lot i fond a solution like this ""Make sure your onYouTubeIframeAPIReady function is available at the global level, not nested (hidden away) within another function.""
But I am not able to understand anyone please update my code snippet.
here is my code.
var playYoutubeVideos = function (index, videoId) {
if (typeof videoId == "undefined") {
videoId = $('#list').find('li[index="'+index+'"]').attr('data-video_id');
}
jwplayer(playerId).stop();
$('.video-div').hide();
$('.transcript-container').hide();
$('.youtube_video_div').show();
var tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
/*$('.youtube_video_div').append('<center><iframe class="video_frame" src="https://www.youtube.com/embed/'+videoId+'?&autoplay=1" frameborder="0" allowfullscreen></iframe></center>');
animateFooterList(index);*/
console.log(videoId);
}
var vdid=videoId;
// 3. This function creates an <iframe> (and YouTube player)
//after the API code downloads.
var player;
//function onYouTubeIframeAPIReady() {debugger;
console.log("making youtube");
player = new YT.Player('yt_fram', {
height: '390',
width: '640',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
//}
console.log(player);
function stopVideo() {
player.stopVideo();
}
$('.video-div').hide();
$('.transcript-container').hide();
$('.youtube_video_div').show();
index = index + 1;
nextvideoId = $('#list').find('li[index="'+index+'"]').attr('data-video_id');
jwplayer(playerId).play();
if($('#list li[index='+index+']').hasClass('video_plus'))
{
playThis(index,'video_plus',nextvideoId);
//return;
}
else if($('#list li[index='+index+']').hasClass('ext_video'))
{
playThis(index,'ext_video','');
//return;
}
playThis(index,'','');
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
console.log("youtube player ready");
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("youtube player state change");
console.log("event");
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
utube api is not calling
To load a youtube player, I use the API in Jquery like this :
var youtube_player = document.createElement("div");
youtube_player.id = "youtube_player";
youtube_player.className = "youtube_player";
document.getElementById('media_container').appendChild(youtube_player);
var player = {
playVideo: function (container, videoId) {
if (typeof (YT) == 'undefined' || typeof (YT.Player) == 'undefined') {
window.onYouTubeIframeAPIReady = function () {
player.loadPlayer(container, videoId);
};
$.getScript('//www.youtube.com/iframe_api');
} else {
player.loadPlayer(container, videoId);
}
},
loadPlayer: function (container, videoId) {
new YT.Player(container, {
videoId: videoId,
width: 356,
height: 200,
playerVars: {
autoplay: 1,
controls: 1,
modestbranding: 0,
rel: 0,
showInfo: 0
}
});
}
};
var id_youtube = get_id_youtube_by_url(url_media);
player.playVideo(youtube_player.id, id_youtube);
And this code is working, a youtube player is created in the div 'media_container'.
But now, if I want to load a youtube player from an iframe in the parent page, it doesn't work.
I think that the problem comes from the attribute "container" in load_player.
But I don't know how to make this. Have you any idea ?
Thanks a lot for your help !
Not sure if this is helpful but try using the sample in this Github repo. It includes searching and playing youtube videos. You can try this live demo and compare with your project.
I am trying to make a youtube video loop at a specific section of a video.
https://www.youtube.com/v/zeI-JD6RO0k?autoplay=1&loop=1&start=30&end=33&playlist=%20zeI-JD6RO0k
From what I know:
To start and end:
start=30&end=33
To make it loop:
autoplay=1&loop=1&playlist=%20zeI-JD6RO0
The problem is that it doesn't start the next loop at the time I specify
You can use Youtube Iframe-API to loop a video section.
Place this tag in your HTML-page:
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
Load Youtube Iframe-API
// 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);
Create player and loop video:
var section = {
start: 30,
end: 33
};
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player(
'player',
{
height: '360',
width: '640',
videoId: 'zeI-JD6RO0k',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
}
);
}
function onPlayerReady(event) {
player.seekTo(section.start);
player.playVideo();
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
var duration = section.end - section.start;
setTimeout(restartVideoSection, duration * 1000);
}
}
function restartVideoSection() {
player.seekTo(section.start);
}
See this example in action
Note first, if one is not familiar with html or javascript beyond basics, the youtube player api link in the answer by maiermic will provide everything necessary to develop the solution provided there -on one page without a lot of skimming.
also, in case one would like to add a hh:mm:ss converter that accepts down to seconds - add / modify the code provided in the answer by maiermic with the following;
var timeStart = "HH:MM:SS";
var timeEnd = "HH:MM:SS";
var loopStart = getSeconds(timeStart);
var loopEnd = getSeconds(timeEnd);
var section = {
start: loopStart,
end: loopEnd
};
and add the function;
function getSeconds(str) {
var p = str.split(':'),
s = 0, m = 1;
while (p.length > 0) {
s += m * parseInt(p.pop(), 10);
m *= 60;
}
return s;
}
And in the case one would like to include slower playback up to normal speed with this code, alter the following function with
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
var duration;
var playerSpeed = player.getPlaybackRate();
if (playerSpeed == .25)
duration = (section.end - section.start) * 4;
else if (playerSpeed == .5)
duration = (section.end - section.start) * 2;
else if (playerSpeed == .75)
duration = (section.end - section.start) * 1.5;
else if (playerSpeed == 1)
duration = (section.end - section.start);
setTimeout(restartVideoSection, duration * 1000);
}
}
as well as
function onPlayerReady(event) {
player.seekTo(section.start);
player.setPlaybackRate(.25); // choose .25, .50, .75, or 1
player.playVideo();
}
Of course, you will have to modify the video id/ HH:MM:SS fields in the code every time you want a different video / section of video. Additionally, if one chooses to include support for variable player speed as above, those values will have to be added as desired. The playback speed can be altered via the player buttons once started if the code above is included, but if it is changed during play back, the duration will not refresh until the video begins at the start again.
I embed Youtube videos in my angular app using two directives which make use of the YouTube Iframe API. The first loads the library async
angular.module('myApp')
.service('youTubeService', function($rootScope, $window) {
var self = this;
self.ready = false;
$window.onYouTubeIframeAPIReady = function () {
self.ready = true;
console.log("Youtube service ready");
$rootScope.$broadcast('youTubeServiceReady', true);
};
var tag = document.createElement('script');
tag.src = '//www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
});
I then embed the video using the javascript library
angular.module('myApp')
.directive('youtube', function (youTubeService) {
return {
link: function (scope, element, attrs) {
var player;
var playerReady = false;
var playerState;
var callback;
var carouselScope = element.parent().parent().scope();
function createPlayer() {
player = new YT.Player(element[0], {
height: attrs.height,
width: attrs.width,
videoId: attrs.youtube,
playerVars: { 'start' : attrs.starttime, 'end' : attrs.endtime, 'origin': 'https://', showinfo: 0, modestbranding: 1 },
events: {
onReady: function () {
playerReady = true;
// if (callback !== null) {
// callback();
// }
},
onStateChange: function (event) {
//console.log("Time:" + getCurrentTime() + ", Duration:" + getDuration() );
playerState = event.data;
if (playerState === YT.PlayerState.PAUSED) {
carouselScope.play();
}
}
}
});
}
if (youTubeService.ready) {
createPlayer();
} else {
scope.$on('youTubeServiceReady', function () {
createPlayer();
});
}
...
This was working for months up until yesterday but now I get the following video as my embed in all desktop browsers as documented here
https://support.google.com/youtube/answer/6098135?hl=en-GB
My problem is I can't figure out what I should be changing because as far as I understand the iframe api is the correct one. Does anyone know what I should be changing?
So we were having the exact same issue with our site.
It turns out that our client, which uses code very similar to yours above is functioning correctly. Our problem ended up being the way in which we were adding videos and video meta data to our database.
This might not be your issue, but we were using
http://gdata.youtube.com/feeds/api/videos/<video id>?v=2&alt=json
to add videos to our system. As this turns out to be a deprecated endpoint, we had to upgrade to the v3 system which is explained here: https://developers.google.com/youtube/v3/docs/videos/list