I have a iframe generated on my site. The src of the iframe is video id from database. I would like to know, how can I detect that the video finishes playing.
My embeded youtube video:
echo "<iframe width='50%' height='60%' id='cc' src='https://www.youtube.com/embed/" . $data_song[0] . "' frameborder='1' allowfullscreen></iframe><br>";
Thanks for any advice.
Okay, Since you are using the iframe to stream youtube videos, what you want can be achieved by this,
When Player.Status = 0 that means the video has stopped. I have commented those for you to understand easily.
<script type="text/javascript">
var player;
$(document).ready(function () {
onYouTubePlayerAPIReady();
});
function onYouTubePlayerAPIReady() {
player = new YT.Player('ytplayer', {
events: {
'onStateChange': getStatus
}
});
}
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function getStatus() {
var sStatus;
sStatus = player.getPlayerState();
if (sStatus == -1) {} //Video has not started yet
else if (sStatus == 0) {
// video has stopped. This is the event that you want
}
else if (sStatus == 1) { } //Video is playing
else if (sStatus == 2) {} //Video is paused
else if (sStatus == 3) { } //video is buffering
else if (sStatus == 5) { } //Video is cued.
}
</script>
If you use a tag <video> is better.
For example:
Your HTML
<video id="videoplayer">.
Your JS
var myvideo = document.getElementById('videoplayer');
myvideo.addEventListener('ended',function() {
// The video's callback
} ,false);
Related
I have an app where I inject a youtube iframe player (full iframe html snippet) at some point in time when a user requests a specific video. This could happen e.g. 30 seconds after loading the app or at any point in time, just not right after loading the app.
This seems to be a problem for the youtube API. In my code example below, you can see that the example isn't working because I'm adding the iframe player after a 1 second time. When you lower the timeout from 1000 to just 1ms, the code works fine.
Because of that test, I found out that the YT events aren't triggering because of my player being injected at a later point when the app has already been loaded for some time.
Is there a way to make the events trigger when the player isn't immediately added to the dom? Or can someone explain why the events only work when the player is added immediately to the page (even when the element itself is added after the script)
https://jsbin.com/vuhibelabi/1/edit?html,output
<div id="test" style="display:none;"></div>
<script type="text/javascript">
var tag = document.createElement('script');
tag.id = 'iframe-demo';
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('existing-iframe-example', {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
document.getElementById('existing-iframe-example').style.borderColor = '#FF6D00';
}
function changeBorderColor(playerStatus) {
var color;
if (playerStatus == -1) {
color = "#37474F"; // unstarted = gray
} else if (playerStatus == 0) {
color = "#FFFF00"; // ended = yellow
} else if (playerStatus == 1) {
color = "#33691E"; // playing = green
} else if (playerStatus == 2) {
color = "#DD2C00"; // paused = red
} else if (playerStatus == 3) {
color = "#AA00FF"; // buffering = purple
} else if (playerStatus == 5) {
color = "#FF6DOO"; // video cued = orange
}
if (color) {
document.getElementById('existing-iframe-example').style.borderColor = color;
}
}
function onPlayerStateChange(event) {
changeBorderColor(event.data);
}
function go(){
var player = `<iframe id="existing-iframe-example"
width="640" height="360"
src="https://www.youtube.com/embed/M7lc1UVf-VE?enablejsapi=1"
frameborder="0"
style="border: solid 4px #37474F"
></iframe>`;
document.querySelector("#test").innerHTML = player;
document.querySelector("#test").style.display = "block";
}
setTimeout(function(){
go();
}, 1000)
</script>
For anyone in the same situation, I have switched to using the JS-based solution instead of injecting a full iframe and that seems to work fine.
For the college I work for I am trying to get a youtube video to auto play in the banner of the webpage. The API is not loading every time properly. I am not sure what I could do to try to fix this.
I have tried:
Moving the adding of the youtube API script to only when the DOM is ready.
Placing the code on the top and bottom of the page.
Checking to see if the player object was created properly and if not try to recreate it which I learned breaks the API.
If I strip the page of everything and just have the banner the video loads more often but still not 100% of the time.
Here I provided the script on the page that is loading the video via the YouTube API.
Update:
From what I can tell by logging to the console the player object is not being fully initialized.
When it is not created correctly this is what the object print out looks like:
Y {b: null, a: null, h: null, closure_uid_165988549: 1, g: 1, …}
And here it is when is done correctly:
Y {b: Wa, a: iframe#ytplayer, h: div#ytplayer, closure_uid_16195269: 1, g: 1, …}
I was wrong about it not finding the videoId. The video is set every time before the function is called so it should not be an issue.
<div id="ytplayer"></div>
<script>
defer(function() {if(window.mobile === true) { $('#ytplayer').remove(); }});
var ready;
// Replace the 'ytplayer' element with an <iframe> and
// YouTube player after the API code downloads.
var player;
// var videoId = 'ZCESafUzSRo';
function onYouTubeIframeAPIReady() {
checkFunction();
}
function checkFunction() {
console.log("checkFunction called");
setYTready(ready);
}
function setYTready(ready) {
console.log("setYT ready called");
ready = true;
mtuPlayerCreate(player);
}
function mtuPlayerCreate(player) {
console.log("mtu create called");
if((player == undefined) && ( document.getElementById("play-yt") != null)) {
console.log("Creating player");
player = new YT.Player('ytplayer', {
height: '52.65%',
width: '100%',
playerVars: {
'controls': 0,
'showinfo': 0,
'rel': 0,
'iv_load_policy': 3
},
videoId: videoId,
events: {
'onReady': onPlayerReady,
// Removing the following if loop shouldn't be enabled
onStateChange:
function(e){
if (e.data === YT.PlayerState.ENDED) {
player.playVideo();
}
}
}
});
}
console.log("player redo below");
console.log(player);
if(player.A == false) {
//setTimeout(function() {location.reload();}, 2000);
} else {
return;
}
}
function onPlayerReady(event) { /* configuring default playing and mute settings */
console.log("on ready has been called")
var autoPlay = 1;
var autoMute = 1;
if(autoPlay === 1) { event.target.playVideo(); }
if(document.getElementById('play-yt') && autoPlay === 1) { document.getElementById('play-yt').className = 'pause'; }else if(document.getElementById('play-yt')) { document.getElementById('play-yt').className = 'play'; }
if(autoMute === 1) { event.target.mute(); }
if(document.getElementById('mute-yt') && autoMute === 1) { document.getElementById('mute-yt').className = 'mute'; }else if(document.getElementById('mute-yt')) { document.getElementById('mute-yt').className = 'loud'; }
if(document.getElementById('yt-yt')) { document.getElementById('yt-yt').className = ''; }
}
window.onload = function() { /* this handles what happens when the player and its buttons are clicked on */
document.getElementsByClassName('media-black')[0].onclick=function(e) {
if(e.target.id !== 'yt-yt' && e.target.id !== 'mute-yt') {
if(player.getPlayerState() === -1 || player.getPlayerState() === 2 || player.getPlayerState() === 5) {
player.playVideo();
if(document.getElementById('play-yt')) { document.getElementById('play-yt').className = 'pause'; }
if (window._gaq) _gaq.push(['_trackEvent', 'Wide Video', 'Played', window.location.href]);
}else{
player.pauseVideo();
if(document.getElementById('play-yt')) { document.getElementById('play-yt').className = 'play'; }
if (window._gaq) _gaq.push(['_trackEvent', 'Wide Video', 'Paused', window.location.href]);
}
}
else if(e.target.id === 'yt-yt' && e.target.id !== 'mute-yt') {
window.open('http://www.youtube.com/watch?v=' + videoId, '_blank');
player.pauseVideo();
if(document.getElementById('play-yt') && document.getElementById('play-yt').className === 'pause') { document.getElementById('play-yt').className = 'play'; }
if (window._gaq) _gaq.push(['_trackEvent', 'Wide Video', 'Went to YouTube', window.location.href]);
}else{
if(player.isMuted() || player.getVolume() === 0) { player.unMute(); player.setVolume(100); document.getElementById('mute-yt').className = 'loud'; }else{ player.mute(); document.getElementById('mute-yt').className = 'mute'; }
if (window._gaq) _gaq.push(['_trackEvent', 'Wide Video', 'Sound Adjusted', window.location.href]);
}
};
}
//
//This could be improved, test if it's mobile and load if not instead of loading and then removing if mobile
//
// Load the IFrame Player API code asynchronously.
document.addEventListener("DOMContentLoaded", function(event) {
console.log("dom ready!");
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
});
</script>
</div>
What it needs to do is:
Load the API
Load the player object with the given video ID
Add the iframe to the correct spot
Autoplay the video.
It needs to do this every time the page loads.
I'm not sure why you're loading the YouTube iframe player in that way, but, I made this jsfiddle - by modifying your code - and I get the YouTube Player iframe working.
These are the modifications I made - you can find more comments in the modified code:
I commented the line mtuPlayerCreate - are you trying to add another YouTube Iframe?
Add the onPlayerStateChange function for set the functionality for HTML elements - able to control the iframe - "play/pause, (un)mute the video".
The controls value was 0, I set it to 1 for check whether it was properly controlling the YouTube iframe by clicking the HTML elements.
This is the jsfiddle code:
// No need for replace the elemnt - YouTube Iframe Player will load in this object and HTML element:
var player;
// This is your videoId "you had it commented".
// it was the video is not available:
//var videoId = 'ZCESafUzSRo';
// Video: "Microsoft Windows Mixed Reality update | October 2018" - by Microsoft Hololens.
var videoId = '00vnln25HBg';
// Check whether iframe is mute.
var isUnMuted = false;
// Here, the YouTube Player API will build the iframe in the "ytplayer" HTML element
// and in the "player" variable.
function onYouTubeIframeAPIReady() {
player = new YT.Player('ytplayer', {
height: '52.65%',
width: '100%',
playerVars: {
'controls': 1,
'showinfo': 1,
'rel': 0,
'iv_load_policy': 3,
'autoplay': 1,
'loop': 1,
},
videoId: videoId,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
// After loading the iframe, set the "playVideo" onclick event on "playButton" anchor element.
document.getElementById('play-yt').onclick = function() {
player.playVideo();
};
// Thanks to this answer, here you can check the status of "mute" - I culdn't make it work, in the "onPlayerStateChange" function though.
// Source: https://stackoverflow.com/a/36436765/4092887
document.getElementById('mute-yt').innerHTML = 'MUTE';
document.getElementById('mute-yt').onclick = function() {
player.mute();
};
document.getElementById('yt-yt').innerHTML = 'UNMUTE';
document.getElementById('yt-yt').onclick = function() {
player.unMute();
};
}
function checkFunction() {
console.log("checkFunction called");
setYTready(ready);
}
function setYTready(ready) {
console.log("setYT ready called");
// Not sure what you're doing here = do you want load another youtube iframe?
//mtuPlayerCreate(player);
}
function mtuPlayerCreate(player) {
console.log("mtu create called");
if ((player == undefined) && (document.getElementById("play-yt") != null)) {
}
console.log("player redo below");
console.log(player);
if (player.A == false) {
//setTimeout(function() {location.reload();}, 2000);
} else {
return;
}
}
/* configuring default playing and mute settings */
/* You only need set here the following line: */
function onPlayerReady(event) {
event.target.playVideo();
}
/* this handles what happens when the player and its buttons are clicked on */
/* You can do it in this way instead: */
function onPlayerStateChange(e) {
// Removing the following if loop shouldn't be enabled.
// This is for emulate "loop" functionality.
if (e.data === YT.PlayerState.ENDED) {
player.playVideo();
}
// If the video is PLAYING, set the onclick element for pause the video.
// Once the "playButton" is clicked, the video will be paused.
if (e.data == YT.PlayerState.PLAYING) {
document.getElementById('play-yt').innerHTML = 'PAUSE';
document.getElementById('play-yt').onclick = function() {
player.pauseVideo();
};
}
// If the video is PAUSED, set the onclick element for pause the video.
// Once the "playButton" is clicked, the video will resume the video = continue playing the video.
if (e.data == YT.PlayerState.PAUSED) {
document.getElementById('play-yt').innerHTML = 'PLAY';
document.getElementById('play-yt').onclick = function() {
player.playVideo();
};
}
}
//
//This could be improved, test if it's mobile and load if not instead of loading and then removing if mobile
//
// Load the IFrame Player API code asynchronously.
document.addEventListener("DOMContentLoaded", function(event) {
console.log("dom ready!");
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<div id="ytplayer"></div>
<p>
<div>
<span>Control your Youtube Iframe Player:</span>
</div>
<div id="play-yt">PLAY</div>
<div id="mute-yt">MUTE</div>
<div id="yt-yt">UNMUTE</div>
</p>
I'm trying to control a youtube iframe in my squarespace website. I want it to autoplay when the page loads and then if I scroll and it's not in the viewport anymore, I want it to pause.
Here is what I did:
This is my iframe:
<iframe id="ytplayer" width="560" height="315" src="https://www.youtube.com/embed/uuRC8Pmud3o?enablejsapi=1&rel=0&showinfo=0&controls=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
And this is my script:
<script>
// 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);
// This function YouTube player
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('ytplayer', {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// The API calls this function when the player's state changes.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
done = true;
}
// Loop the video
if (event.data == YT.PlayerState.ENDED) {
player.playVideo();
}
}
// On scroll Pause/Play the video player
$(window).scroll(function() {
var top_of_element = $("#ytplayer").offset().top;
var bottom_of_element = $("#ytplayer").offset().top + $("#ytplayer").outerHeight();
var bottom_of_screen = $(window).scrollTop() + $(window).height();
var top_of_screen = $(window).scrollTop();
if((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)){
// The element is visible, trigger play click event
player.playVideo()
}
else {
// The element is not visible, trigger pause click event
player.pauseVideo()
}
});
</script>
I tried adding the script to squarespace using many ways but it's not working. Where has the script to be injected?
What's wrong with my code?
According to Youtube IFRAME API, just add autoplay=1 at the end of your URL like:
<iframe id="ytplayer" type="text/html" width="640" height="360"
src="https://www.youtube.com/embed/M7lc1UVf-VE?autoplay=1&origin=http://example.com"
frameborder="0"></iframe>
I think this is also confirmed in the squarespace forum.
I have just figured this out.
Squarespace creates it's own players and also it dynamically creates iframes so it's a bit complicated. Also getting player using DOM element doesn't seems to work and all iframe elements have the same id = "player" so that adds up to the problem.
The code below is what I have come to literally 5min ago.
Just copy/paste to the header code injection in the Squarespace config.
What it does is it acquire all the original YouTube API players as soon as possible and pause playback to avoid horrible lag when my old GPU tries to video-decode all those video instances. Then I have a code which plays the video when it appears on the screen and pauses videos that are not visible anymore. Now it plays smoothly and I can add even more videos. In my case you can see one full-screen video at a time as you scroll down. I have 7x 720p videos stacked up. It looks cool, but I found out that my GPU is lagging badly when more than 5 videos were used, initially I was thinking that it's a network speed problem but my task manager showed 100% on GPU video-encoding. So far worked on Firefox and Chrome.
I have just managed to make this work so there is a lot of testing and tweaking to be done.
USE ON YOUR OWN RISK ! :)
<script type="text/javascript">
// Prepare YouTube iframe API ..
// this is probably redundant, but works fine
var tag = document.createElement ('script');
tag.id = 'iframe-api';
tag.src = 'https://www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName ('script')[0];
firstScriptTag.parentNode.insertBefore (tag, firstScriptTag);
// When Iframe is ready ..
var iframes = [];
var players = [];
function onYouTubeIframeAPIReady () {
// console.log ("onYouTubeIframeAPIReady");
var player_containers = document.querySelectorAll (".sqs-video-background.content-fill");
for (var i = 0; i < player_containers.length; i ++) {
player_containers [i].addEventListener ("DOMNodeInserted", function (e) {
var node = e.target;
if (node.tagName.toUpperCase () === "IFRAME") {
// console.log ("PLAYER : " + node.id + " TAG : " + node.tagName);
iframes.push (node);
// unfortunately it seems that we cannot catch the player creation event so
// the actual players are probably created after this code
// by calling this function we can catch previous players early on
// except the last one
initPlayers ();
}
}, false);
}
}
function initPlayers () {
// they have all the same id (!!!)
// however it seems it picks the last created one so not the same one over and over
// I didn't touched this, it works so far
var player = YT.get ("player");
if (player !== undefined) {
players.push (player);
pausePlayer (player);
}
}
function playPlayer (player) {
// this happends when player is not fully initialized yet
if (typeof player.pauseVideo === "function") {
player.playVideo ();
} else {
// if the player is not ready yet catch the event
player.addEventListener ('onReady', function (event) {
player.playVideo ();
});
}
}
function pausePlayer (player) {
// this happends when player is not fully initialized yet
if (typeof player.pauseVideo === "function") {
player.pauseVideo ();
} else {
// if the player is not ready yet catch the event
player.addEventListener ('onReady', function (event) {
player.pauseVideo ();
});
}
}
function isInViewport (element, edge) {
var h = window.innerHeight; // viewport height
var r = element.getBoundingClientRect (); // elements bounding rect in viewport coordinates
// console.log ("top : " + r.top);
// console.log ("bottom : " + r.bottom);
// console.log ("height : " + h);
// add extra margin to the viewport to ensure that
// big enough portion of the object is already visible
var e = h * Math.min (edge, 0.4); // relative viewport factor, max 40%
var top = r.top - e;
var bottom = r.bottom - e;
h = h - e*2;
return (!((top > h) || (bottom < 0)));
}
window.onload = function(e){
// console.log ("loaded");
initPlayers (); // to catch the last one !
// console.log ("players : " + players.length);
function onScroll () {
for (var i = 0; i < players.length; i ++) {
var player = players [i];
var iframe = player.getIframe ();
var container = iframe.parentNode;
if (isInViewport (container, 0.0)) {
playPlayer (player); } else {
pausePlayer (player);
}
}
}
// in the case object is already in the viewport
onScroll ();
window.addEventListener ("resize", onScroll);
window.addEventListener ("scroll", onScroll);
}
</script>
I'm currently loading a YouTube video inside a -UIwebView, this is working perfectly and the video starts playing automatically. but the problem is that once the video finishes inside the -UIwebViewit just stops and shows the play button. I would however want the video player to close so the users wouldn't have to manually hit the "Done" button every time.
Image of the screen when the video doesn't close.
Here's the link I launch the video inside the -UIwebview
NSString *youTubeVideoHTML = [NSString stringWithFormat:#"<!DOCTYPE html><html><head>
<style>body{margin:0px 0px 0px 0px;}</style></head> <body> <div id=\"player\"></div> <script>
var tag = document.createElement('script'); tag.src = \"http://www.youtube.com/player_api\";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
width:'320',
height:'200',
videoId:'%#',
events: {
'onReady': onPlayerReady,
}
});
}
function onPlayerReady(event) {
event.target.playVideo();
}
</script> </body> </html>", [[NSUserDefaults standardUserDefaults]
objectForKey:#"detailVideoURL"]];
EDIT:
I tried implementing the first answer into my code and this is how it ended up like. I'm still unsure what I should add into the callback ?
NSString *youTubeVideoHTML = [NSString stringWithFormat:#"<!DOCTYPE html><html><head><style>body{margin:0px 0px 0px 0px;}</style></head> <body> <div id=\"player\"></div> <script>
var tag = document.createElement('script'); tag.src = \"http://www.youtube.com/player_api\";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
width:'320',
height:'200',
videoId:'%#',
events: {
'onReady': onPlayerReady,
}
});
}
function onPlayerReady(event) {
event.target.playVideo();
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000); done = true;
}
if (event.data == YT.PlayerState.ENDED) {
window.location = "callback:nil"; }; }
function stopVideo() {
player.stopVideo();
}
</script> </body> </html>", [[NSUserDefaults standardUserDefaults] objectForKey:#"detailVideoURL"];
Image of the error : http://gyazo.com/31da955d8af98f40b82789a7f60c1edb
You can do it by calling your objective function from javascript using youtube api.
On the HTML/Javascript Side
<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 = "http://www.youtube.com/player_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 onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '300',
width: '250',
videoId: 'GUdYebAN-Fs',
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) {
event.target.destroy();
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 60000);
done = true;
}
if (event.data == YT.PlayerState.ENDED) {
event.target.destroy();//to close the video
window.location = "callback:anything"; //here's the key
};
}
function stopVideo() {
player.stopVideo();
}
</script>
</body>
</html>
onStateChange- From the google's API reference page
This event fires whenever the player's state changes. The data property of the event object that the API passes to your event listener function will specify an integer that corresponds to the new player state.
So in the javascript function you would be able to trace the End of the video time.Then just
add event.target.destroy() on entering the state end condition.
On the native/iOS side:
And even you can do the native stuff here by catching up the call back method using the webview delegate method.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ( [[[request URL] scheme] isEqualToString:#"callback"] ) {
//Video has ended up playing,you can perform native stuff here...
return NO;
}
return YES;
}
Note: Please make sure to test this code in your device,because sometimes the simulators won't be supporting.
Good Luck...Hope it helps...
This is how you can apply Puneeth's solution to Google's YTPlayerView so the player hides after the video finishes:
- (void)playerView:(YTPlayerView *)playerView didChangeToState:(YTPlayerState)state
{
if(state == kYTPlayerStateEnded) {
[self.youTubePlayer.webView stringByEvaluatingJavaScriptFromString:#"player.destroy();"];
// you'll have to recreate the player again since it's now destroyed
[self.youTubePlayer removeFromSuperview];
self.youTubePlayer = nil;
}
}
My HTML
<div id="player">
<!-- hardcoded for the moment -->
<div id="video">
<iframe class="youtube-player" id="video-frame" width="640" height="390" src="http://www.youtube.com/v/gSy4HeDjPvs?version=2&enablejsapi=1" frameborder="0" allowfullscreen></iframe>
</div>
</div>
JavaScript
var youtube_player; // global player variable
// adding YouTube controls
$(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);
});
function onYouTubeIframeAPIReady() {
//noinspection JSUnresolvedFunction,JSUnresolvedVariable
youtube_player = new YT.Player('video', {
height:'390',
width:'640',
videoId:'JW5meKfy3fY',
events:{
'onReady':onPlayerReady,
'onStateChange':onPlayerStateChange
}
});
}
// playing video in left pane
function play_video(id) {
console.log('play video', id);
//noinspection JSUnresolvedFunction
if (youtube_player) {
youtube_player.loadVideoById(id, 0);
}
}
function onPlayerReady(evt) {
evt.target.playVideo();
}
// when video is finished playing, what next video to play?
function onPlayerStateChange(event) {
if (event.data == 0) {
var id = get_next_video_id();
if (id == -1) {
// repeat = 0, reset video_index
reset_video_index();
} else {
play_video(id);
}
}
}
This runs fine in Safari but fails in Chrome. On console.log, it says
Uncaught TypeError: Object #<U> has no method 'loadVideoById' vlists.js:447
30
Unable to post message to http://www.youtube.com. Recipient has origin https://www.youtube.com.
Even though in YouTube API, loadVideoById exists.
After working through the YouTube API for a while, I am able to make it run for both Chrome and Safari
The demo is http://plnkr.co/edit/07Cq5KqIa5Pase8JYHbA?p=preview