Strange one: embedded YouTube videos, once played (either by clicking 'play' or autoplaying on page load) will not play again.
I'm using the standard iFrame embed copied straight from YouTube. This happens with several different short videos and across all browser/OS combinations I've tested (Chrome/Safari/Firefox/IE on Windows/Mac).
Here's the code:
<iframe width="420" height="315" src="//www.youtube.com/embed/OuSdU8tbcHY" frameborder="0" allowfullscreen></iframe>
and you can see it in action at this fiddle.
So it appears that the issue is NOT related to video length; it's a problem with the flash player. If the flash player is loaded, and there is no user interaction with the controls at all, then when the player finishes it will not reload the iframe (despite the fact that it raises the 'video ended' event ... when you try to reload it won't issue the right call to reload the video and hence can never restart playback). You can test longer videos as well; if you start watching them and don't use the scrub bar, they'll exhibit the same behavior. Likewise, on your very short video, if you start playback and then scrub a bit (even backwards in time), that will trigger an iframe reload (akin to what #SuperMan noted), and so when the video finishes, then the reload will work just fine.
This is most likely a recently introduced bug in the Flash player, and it is not present in the HTML5 player; so if your use case allows it, the simplest solution would be to force the HTML5 player by appending ?html5=1 to the source of your iframe.
However, if having the flash player as a possibility is an iron clad requirement, then you can hack your code to force it to reload itself when finished (rather than waiting for a user to hit the reload or replay button).
<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 player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
events: {
onStateChange: 'onPlayerStateChange'
}
});
}
function onPlayerStateChange(event) {
if (event.data===YT.PlayerState.ENDED) {
event.target.cueVideoById(event.target.getVideoData().video_id);
}
}
</script>
<iframe width="420" height="315" src="//www.youtube.com/embed/OuSdU8tbcHY" frameborder="0" allowfullscreen id="player"></iframe>
</body>
</html>
Note that this requires giving your iframe an id attribute, so that you can bind to it with the iframe API.
This also avoids having to overlay any DOM elements over the video (which is not in any way a bad solution as long as you don't have any odd wmode requirements; a very strict reading of the YouTube TOS might also lead to the conclusion that you can't overlay anything over any portion of the player even if it's transparent...).
One drawback of my solution is that it won't display the 'related videos' at the end of the video, so if that's a deal breaker then this is a no-go (in other words, my solution is more akin to adding the rel=0 attribute to your iframe source).
Okay, I don't know how to fix the problem but here's a work around.
The general idea is to place a div over the reload button when the video finishes, and when the div is clicked the video reloads, since the normal method doesn't work.
Here's the code I used, in the code the div is blue for visualization purposes
<!DOCTYPE html>
<html>
<body>
<div id="player_prop" style="position:relative;"><iframe id="player" type="text/html" width="640" height="390"
src="http://www.youtube.com/embed/OuSdU8tbcHY?enablejsapi=1"
frameborder="0"></iframe></div>
<script>
// 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;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
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.
//from mantish http://stackoverflow.com/questions/3452546/javascript-regex-how-to-get-youtube-video-id-from-url
function youtube_parser(url){
var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var match = url.match(regExp);
if (match&&match[2].length==11){
return match[2];
}else{
//error
}
}
//end of Lasnvs code
function restart_vid()
{
el = document.getElementById("fake_replay_button");
vid_id = youtube_parser(document.getElementById('player').src);
player.loadVideoById(vid_id);
el.parentNode.removeChild(el);
}
function fakeplay()
{
el = document.getElementById("player_prop");
var xPos = el.offsetLeft
var yPos = el.offsetHeight - 30;
var pseudoPlay = document.createElement('div');
pseudoPlay.setAttribute('style', 'background-color:blue; cursor:pointer; display:block; width:55px; height:25px; position:absolute; top:'+yPos+'px;');
pseudoPlay.setAttribute('onclick','restart_vid()');
pseudoPlay.setAttribute('id','fake_replay_button');
el.appendChild(pseudoPlay);
}
function onPlayerStateChange(event)
{
if(event.data==YT.PlayerState.ENDED)
{
fakeplay();
}
}
</script>
</body>
</html>
To use this code all you have to do is copy and paste the script portion, and instead of only using this
<iframe width="420" height="315" src="//www.youtube.com/embed/OuSdU8tbcHY" frameborder="0" allowfullscreen></iframe>
give it an id=player, enable jsapi by adding ?enablejsapi=1 at the end of the src and enclose the iframe in a div with id = player_prop, make sure the div has property position:relative, or else the alignment of the button would be off, it should look like this
<div id="player_prop" style="position:relative;">
<iframe id="player" type="text/html" width="640" height="390" src="http://www.youtube.com/embed/OuSdU8tbcHY?enablejsapi=1" frameborder="0"></iframe>
</div>
And of course here's a link to the Fiddle
In simple and fine way is that you have to add two addition parameter in youtube url first one is loop=1 and second is playlist=videoid
However, you can extract videoid from the url. It will be after embed slash
<iframe src="https://www.youtube.com/embed/J3jB4CS0x34?autoplay=1&mute=1&loop=1;playlist=J3jB4CS0x34" width="100%" height="100%" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="">
</iframe>
Maybe something like this:
JsFiddle
It's not a perfect solution, cause you interect with video outside of iframe, but maybe it will get you going(changing src will always reload the video).
$('iframe').attr("src", "//www.youtube.com/embed/OuSdU8tbcHY?autoplay=1"); // restarts the video
Related
I currently have a Vimeo video added to my website through an embed code from Vimeo's end. I do not own this video so I can't manually alter it. Originally, I wanted to automatically pause the video at the 1:50 mark for anyone using my site and viewing the video. With help from a wonderful user in this thread, I have a working script that does just that. But now, I'd like to reflect that change in the UI of the video player. So instead of the video showing "6:34" as the video duration, I want the video UI to show the end of the video being 1:50 (110 seconds as shown in the script below).
Here is the video embed code's HTML:
<iframe id="vidz" src="https://player.vimeo.com/video/401649410?h=11d74aa27c&portrait=0" width="450" height="253" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen=""></iframe>
And here is the aforementioned script:
<script src="https://player.vimeo.com/api/player.js"></script>
<script>
var iframe = document.querySelector('iframe');
var player = new Vimeo.Player(iframe);
function foo() {
player.getCurrentTime().then(function(time) {
console.log('time:', time);
if(time >= 110){
player.pause()
}
});
setTimeout(foo, 1000);
}
player.on('play', function() {
foo();
});
</script>
Is there a way to manipulate the video player's UI/timeline to reflect a new endtime of 1:50?
I'm working on a website, and i'm trying to get an youtube video in an <iframe> tag to play and pause with one button. I can get it to play or pause with separate buttons, but I can't seem to get the if statement to work in order to control the video with just one button.
I'm still relatively new to JavaScript, so it may just bee something simple I missed, but I'v searched online for a while now, and could not find anything that solved my problem.
Below is the code I use right now. The first time I click the button the YouTube video play's, but the second time nothing happens.
I also tried turning autoplay on for the embedded video, but then when I press the button, nothing happens at all.
This is the code I'm currently using:
HTML
<div class="iframe">
<iframe id="iframe1" width="360" height="203" src="https://www.youtube-nocookie.com/embed/videoseries?list=PLb-Mg8r29XuOV9CbkXVDQ5NdQG__WbJqI&controls=0&showinfo=0&enablejsapi=1" frameborder="0" allowfullscreen></iframe>
<a href="#" onclick="iframe1play();return false;">
<div id="iframe1play">
</div>
</a>
</div>
JavaScript
function onYouTubePlayerAPIReady() {
iframe1 = new YT.Player('iframe1');
}
function iframe1play() {
if (event.data == YT.PlayerState.PLAYING && !done) {
iframe1.pauseVideo();
document.getElementById("iframe1").style.opacity = "0";
} else {
iframe1.playVideo();
document.getElementById("iframe1").style.opacity = "1";
}
}
var tag = document.createElement('script');
tag.src = "//www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
Any suggestions are appreciated!
Ok so the main problem was that you didn't have event object in your function.
this should do the trick
if (player.getPlayerState() == YT.PlayerState.PLAYING) {
player.pauseVideo();
document.getElementById("iframe").style.opacity = "0";
} else {
player.playVideo();
document.getElementById("iframe").style.opacity = "1";
}
Use jQuery or other framework, if you can,for injecting functions to elements.
Maybe I don't understand your question. Because I tried your code and it works.
I can see a page with a youtube video. On clicking play button the video starts and when I click again on the video in pauses. So what is your problem. I'm sorry if I don't use comments but I can't yet.
I have some videos which are embedded from YouTube in my "index.php". I am able to watch several videos at the same time by clicking them repeatedly. So, as usual it can be done. But I want to block this somehow.
For example, I'm watching X video and I clicked play to watch Y video. The X video should stop when I do it. Then I should be able to continue watching the Y video. I saw this feature in a website which I don't remember the name of it. And I don't know how to do and have an idea.
What I can guess is that it can be done by using some JavaScript or jQuery.
Here is an example for YouTube video code:
<iframe width="426" height="240" src="//www.youtube.com/embed/lWA2pjMjpBs?rel=0" frameborder="0" allowfullscreen></iframe>
Here is my JavaScript (without jQuery) solution to allow only one YouTube video to play at the time.
DEMO.
First you need to add a Youtube API by simply adding the script to your HTML page:
<script src="https://www.youtube.com/iframe_api"></script>
Then paste as many embed videos as you need. Keep in mind that
?enablejsapi=1&version=3&wmode=transparent
needs to be added to each link in order to access API. I wrapped the videos in div with yt_videos class.
<div class="yt_videos">
<iframe class="video_groups" src="https://www.youtube.com/embed/r4CH0al0ucs?enablejsapi=1&version=3&wmode=transparent" frameborder="0" allowfullscreen></iframe>
<iframe class="video_groups" src="https://www.youtube.com/embed/lL9Zoc46ZG0?enablejsapi=1&version=3&wmode=transparent" frameborder="0" allowfullscreen></iframe>
<iframe class="video_groups" src="https://www.youtube.com/embed/s1NZ2mkW0hM?enablejsapi=1&version=3&wmode=transparent" frameborder="0" allowfullscreen></iframe>
</div>
Then in javascript I access onYouTubeIframeAPIReady() so I can control players behaviour. I loop through the iframes and assign unique id's:
var players = [];
function onYouTubeIframeAPIReady() {
var predefined_players = document.getElementsByClassName("yt_videos")[0].getElementsByTagName('iframe');
for(var i = 0; i < predefined_players.length; i++){
predefined_players[i].id = "player" + i;
players[i] = new YT.Player("player" + i, {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
}
function onPlayerStateChange(event) {
var link = event.target.a.id;
var newstate = event.data;
if (newstate == YT.PlayerState.PLAYING) {
players.forEach(function(item, i) {
if (item.a.id != link) item.pauseVideo();
});
}
}
See the DEMO.
You can use the Youtube JS API
https://developers.google.com/youtube/js_api_reference
With it you can handle youtube player events...
If you're using only 1 iframe and just have several links on the sides that would contain the src destination of the iframe you could change the src attribute of the iframe like this:
$('.YoutubeLink').click(function(event){
$('#myIframe').attr('src',$(this).attr('href'));
});
I am working with embeded youtube video. I need to replace it with the image and when the image is clicked the video starts playing which I have implemented:
<script type="text/javascript">
function start_video() {
var iframe = '<iframe title="YouTube video player" width="590" height="360" src="http://www.youtube.com/embed/nCgQDjiotG0?autoplay=1&rel=0&showinfo=0" frameborder="0" title="none" allowfullscreen></iframe>';
document.getElementById("video_player").innerHTML = iframe;
}
</script>
And html:
<div id="video_player"><img style="cursor: pointer;" onclick="start_video();" src="fake_image.jpg" alt="Play Video" /></div>
But now I have a problem stopping this video by clicking on some div or some other element and replacing video back with image at the same time.
I suggest that you read up on the javascript Youtube API which offers you a lot more control than embedding an iframe into your page
Why don't you just give the iframe an id and then remove the iframe and place the image there?
function stop_video() {
var elem = document.getElementById('video_iframe');
var parent = elem.parentNode;
parent.removeChild(elem);
var image = document.createElement('img');
image.setAttribute('src','yourImage.jpg');
parent.appendChild(image);
}
I also suggest that you do not set the innerHTML as you did, you should actually deal with objects like this one above.
function start_video() {
var iframe = document.createElement('iframe');
iframe.setAttribute('title','Youtube video player');
iframe.setAttribute('width','590');
iframe.setAttribute('height','360');
iframe.setAttribute('src','http://www.youtube.com/embed/nCgQDjiotG0?autoplay=1&rel=0&showinfo=0');
iframe.setAttribute('frameborder','0');
iframe.setAttribute('allowfullscreen','allowfullscreen');
document.getElementById('video_player').appendChild(iframe);
}
I have an iFrame that displays an embedded youtube video.
<iframe width="560" height="315" src="http://www.youtube.com/embed/xxx" frameborder="0" allowfullscreen></iframe>
What I would like to do is somehow capture the click event when the user clicks the you tube video so that I can call an http://myserver.com/dostuff rest api to update an external server counter tracking the number of clicks and of course allow the video to play as expected.
Any information would be greatly appreciated.
You can't, I believe. That would be a security risk. If you mainly want to do tracking and whatnot, you would probably be best off doing something like adding an image/button in the place of the video that the user clicks, causing the video to appear.
Edit: This solution may work too; I'm not sure if it'll work for iframes that aren't on the same domain.
window.postMessage could help. But you should have an access to source code of the page you're rendering in iframe.
So in case of embedding of youtube video, you probably can't deal with this.
Everybody had great feedback. Thanks for all who posted. After trying some hacks the bottom line is that trapping the click event is not natively supported via html or javascript.
The best artifact and cleanest solution that I have found is here.
//Its possible by recording the stateChange in the video.
//HTML code----
<!DOCTYPE html>
<html>
<body>
<div id='vidWrapper'>
//your iframe tag goes here.
<iframe id="video-id-first" src="https://www.youtube.com/embed/nNlEiuqiKAk?enablejsapi=1&origin=http%3A%2F%2F3.7.232.244" gesture="media" allow="encrypted-media" allowfullscreen="" data-gtm-yt-inspected-53610233_3="true" width="560" height="400" frameborder="0"></iframe>
</div>
</body>
</html>
//JS code ----
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;
var width = document.getElementById("video-id-first").getAttribute("width");
var height = document.getElementById("video-id-first").getAttribute("height");
var src = document.getElementById("video-id-first").getAttribute("src");
//splitting to get the videoId from src.
var partsArr = src.split("/");
var videoSource = partsArr[partsArr.length -1 ].split("?");
var videoId = videoSource[videoSource.length -2 ];
function onYouTubeIframeAPIReady() {
player = new YT.Player('vidWrapper', {
height:height,
width: width,
videoId: videoId,
events: {
'onStateChange': function(event) {
if (event.data == YT.PlayerState.PLAYING) {
startVideo();
}
if (event.data == YT.PlayerState.PAUSED) {
stopVideo();
}
}
}
});
}
function startVideo() {
//write your functionality here.
alert('Video Started');
}
function stopVideo() {
//write your functionality here.
alert('Video Paused');
}