We are embedding a youtube player into our page. Easy implementation of code and html5 support driven us to use the youtube iframe player.
Problem is that view count does not work with the api. No video does not autoplay and we are playing the video with youtube's default play button.
When I revert back to a AS3 player view count seems to work.
Is it a bug in the iframe api?
Anyone come across a solve?
Thanks!!!
Views that originate as a result of clicking on one of the native player UI elements (either the play button in the control bar or on the static player image) will normally count towards incrementing the views for a video. There are obviously other signals that could come into play, but all things being equal, there's no reason why using an <iframe> embed vs. an ActionScript 3 embed should prevent views from being counted.
If you have a specific example of your implementation that you want to pass along, I can take a look and see if you're doing anything unorthodox.
we have created a simple test html file with a video using the YouTube iFrame API, as the idea is to have the videoplayer fall back to the HTML5 videoplayer on mobile devices. However views are not being counted on click to play video:
http://www.youtube.com/watch?v=-LHUt9FGgys
In the body of the html we have the following:
<div id="player"></div>
<script>
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', {
height: '390',
width: '640',
videoId: '-LHUt9FGgys',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
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();
}
</script>
It would be interesting to see if you or someone else has a solution for this. Thanks!
Related
I am having a very frustrating experience trying to get videos to loop consistently using a basic iframe. I am not interacting with the API via code. I simply have an iframe with autoplay=1,mute=1,loop=1. I've tried using stand-alone videos and I've tried playlists (with list=[ID],listType=playlist) and I keep running into the same problem. Sometimes the player will loop the video and sometimes it will not. Every time I think I have it figured out and I'm ready to deploy the app, I test it again and the video fails to loop.
Windows 10
Chrome 71.0.3578.98
Angular 6.0.3
You can choose any of these options:
Check my answer where I described how you can set your URL for create a playlist (using a single videoId) and simulate a loop.
Use the YouTube iframe Player API for set your video and (once the video ended), call the playVideo() function for play the current video = hence, creating a loop.
This is the code: - unfortunately, you can't see it working here, but, you can see the working jsfiddle1
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// Variables of the divs (where the YouTube iframe will load):
var player;
function onYouTubeIframeAPIReady() {
// Div player:
player = new YT.Player('player', {
height: '360',
width: '640',
videoId: 'xPCZEoGJi_4',
playerVars: {
'autoplay': 1,
'loop': 1,
'mute': 1
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 5. The API calls this function when the player's state changes.
function onPlayerStateChange(event) {
// When the video ends, it will play again.
// See: https://developers.google.com/youtube/iframe_api_reference?hl=en#Events
if (event.data == YT.PlayerState.ENDED) {
player.playVideo();
}
}
// Div "player" - The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<div id="player"></div>
1 If the video (once has loaded) hasn't play, you have to play manually the video - this is due some kind of restrictions that jsfiddle has.
I have some YT videos to play in the VB Webbrowser, but playing it gives me the 'This video contains content from VEVO. It is restricted from playback on certain sites or applications' error. But when I try playing it using the default embed code provided in the Youtube link itself it plays perfectly. Example:
<iframe width="560" height="315" src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allowfullscreen></iframe>
On the custom HTML page made, this is the code I used
function main(vidid)
{
// 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;
window.onYouTubeIframeAPIReady = function() {
player = new YT.Player('player', {
height: '200',
width: '300',
playerVars: {
autoplay: 1,
enablejsapi : 1,
origin: "https://www.youtube.com",
vq: 'medium'},
videoId: vidid,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
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) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
}
Is there something that I'm missing, or is the video just blocked for API users? My apologies if my question is too bad.
Found the source of the problem. Turns out that I was hosting the webpage on PC, which Youtube doesn't allow. After I uploaded my html page to a web server, it works perfectly.
Ive made a pause button for a YouTube video. This worked fine however now I need to clone the video. This is due to how the carousel that im using works and also so the video can be displayed in a Lightbox.
Below is a simplified version of my code. Now the pause button only works on the first video. How can I make a button that will pause all cloned videos?
http://jsfiddle.net/36vr2kjv/2/
<p class="trigger">Trigger</p>
<p class="trigger2">Trigger2</p>
<div class="player-wrap">
<div id="player"></div>
</div>
<div id="player2"></div>
var player;
$(function() {
// 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.
onYouTubeIframeAPIReady = 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();
}
// 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) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
$('.trigger').click(function(){
//this works
player.pauseVideo()
});
return player;
});
$(function() {
setTimeout(function(){
$('.player-wrap').clone().appendTo('#player2');
}, 2000);
});
$(function() {
$('.trigger2').click(function(){
// this does not work
player.pauseVideo()
});
});
Actually there is concept of deep cloning and shallow cloning. Shallow cloning does not copy events hence you have to use deep cloning. Where ever you are using clone() instead use clone(true).
For example in above code snippet you can use:
$(function() {
setTimeout(function(){
$('.player-wrap').clone(true).appendTo('#player2');
}, 2000);
});
Issue Description:
What's happening in your code is you are cloning and creating two IDs within a single DOM load, which means your javascript will have conflicting IDs to deal with. The other issue being that the youtube API creation function binds to an ID and not a class.
So after you've cloned your iframe, your original function (held in player) is now pointed at two places... hence the confusion.
Solution:
To combat this, we can use a placeholder. Based on the Youtube Player API Reference, Youtube allows for loading videos to a player object.
player.loadVideoById(videoId:String,
startSeconds:Number,
suggestedQuality:String):Void
[See Youtube API#Queueing_Functions]
We can use classes and object references to reach your goal:
player;
placeholder;
playerCount = 1;
$(function() {
// ... Previous code ... //
/**
* Assuming you have more than one video to play,
* the function will change to allow for incrementing the ids
* of each player made. [UNIQUE IDS]
*/
onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
player = new YT.Player('player-'+playerCount, {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
placeholder = new YT.Player('placeholder', {
height: '390',
width: '640',
});
/**
* Now add a generic class so we can find all of these elements,
* and bind the object to a data instance for access later.
*/
$('#player-' + playerCount).addClass('youtube-player').data('YoutubeAPI', player);
playerCount++;
}
The placeholder comes into play now, when you carousel fires it's beforeChange event, you can access the player element from within the current/next/previous slide using the carousel's event handler and running a $(event.target).find('youtube-player') (or something like that, APIs are different, so YMMV) and access the player instance using $(event.target).find('youtube-player').data('YoutubeAPI') (or whatever you named your data variable).
Then you just find the video id from the original object (using the access scheme from above and taking the id from the youtubeAPI object) and load the video into the placeholder using the API call from above.
Let me explain my scenario. I want to use Youtube IFrame API to embed some videos on my website.
I tested the video with id wdGZBRAwW74 (https://www.youtube.com/watch?v=wdGZBRAwW74) on this page: Youtube IFrame Player Demo. And it works OK.
I try this example code:
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<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);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'wdGZBRAwW74',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
'onError': onPlayerError
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
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) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function onPlayerError(event){
console.log(event.data);
}
function stopVideo() {
player.stopVideo();
}
</script>
</body>
</html>
with some virtual host domains on my localhost and i got result:
with domain app.centaur.com/youtube/index.htm: IFrame API work OK, the video play without problems.
with domain app.music.com/youtube/index.html: IFrame API work OK, but the video can not play, API fires onError with error 150 and the embedded player show message "This video contains content from VEVO, who has blocked it from display on this website. Watch on Youtube"
with domain app.musiccentaur.com/youtube/index.htm: like first case, everything work ok
with domain app.centaurmusic.com/youtube/: like first case, everything work ok
As i know error 150 stand for "The owner of the requested video does not allow it to be played in embedded players". But i see it still work in case 1, 3, 4, so what is it mean ?
Seem all of videos by Vevo related to this problems. I'm not sure if Vevo defined some policy for embedding their videos.
Maybe the problem come from my domain music.com, but i'm not sure there is some rules of domain to embed Vevo's video on websites.
What if i buy a domain for my website then i got error 150, this is so bad. :(
Is there anyone deal with this before? Please give me some solutions. Thanks in advance.
Note: this error only occurs on Vevo's videos.
Content owners are allowed to set up a white/black list of domain names on which embedding is allowed/denied. There is no way to work around these restriction.
This blog post has a bit more info about content restrictions in general: http://apiblog.youtube.com/2011/12/understanding-playback-restrictions.html
I'd like to play two different youtube videos in the same player, first video being played BEFORE the second (serving as a pre-roll ad). Sort of custom playlist consisting of only two videos.
What i really need is that when the player is in idle state it has to show the image of the main video (the second one), not the pre-roll.
So, I thought I have to use the youtube api to load the main video, then to stop it, then to load the pre-roll and after playing the pre-roll to play the main video then stop.
I've tried to copy/paste same code for achieving these tasks but i'm stuck in it. Can anybody give me an working example for this? Or, at least some advice? Many thanks.
This is a little crude, but accomplishes your task by listening for the state change events; you could make it more responsive by integrating some smart lookahead monitoring based on cueing the main video as the preroll is getting close to finishing. But anyway, this should at least get you started:
<div id="player"></div>
<script>
var seenPreroll=false;
var preroll='rl1qKqlYy8M';
var mainfeature='u1zgFlCw8Aw';
var playingId='';
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', {
height: '390',
width: '640',
videoId: mainfeature,
events: {
'onStateChange': function(event) {
if (event.data==1&&seenPreroll==false) {
player.pauseVideo();
player.loadVideoById(preroll);
playingId=preroll;
seenPreroll=true;
player.playVideo();
}
else if (event.data==0&&playingId==preroll) {
player.loadVideoById(mainfeature);
playingId=mainfeature;
player.playVideo();
}
}
}
});
}
</script>