Pause YouTube iframe embed when playing another - iframe

I have multiple YouTube iFrames embedded on a page. If one of the movies is already playing, and a user then decides to start playing a different movie, is it possible to stop playing the first movie so there is only ever one playing at a time?
I have looked at the 'YouTube Player API Reference for iframe Embeds' https://developers.google.com/youtube/iframe_api_reference but if i'm honest I just don't understand it. My developer skills are very limited.... clearly.
Pitiful I know, but this is all I have at the moment (just the iFrames)... http://jsfiddle.net/YGMUJ/
<iframe width="520" height="293" src="http://www.youtube.com/v/zXV8GMSc5Vg?version=3&enablejsapi=1" frameborder="0" allowfullscreen></iframe>
<iframe width="520" height="293" src="http://www.youtube.com/v/LTy0TzA_4DQ?version=3&enablejsapi=1" frameborder="0" allowfullscreen></iframe>
I thought all I needed to do was add '&enablejsapi=1' at the end of the video URLs.
Any help would be much appreciated.
Thank you in advance.

Here is an advanced version of #Matt Koskela's version. It does not require you to create the videos by JavaScript. It works for example if the videos are generated on the PHP side (think Wordpress).
JsFiddle demo here.
<script>
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
var $ = jQuery;
var players = [];
$('iframe').filter(function(){return this.src.indexOf('http://www.youtube.com/') == 0}).each( function (k, v) {
if (!this.id) { this.id='embeddedvideoiframe' + k }
players.push(new YT.Player(this.id, {
events: {
'onStateChange': function(event) {
if (event.data == YT.PlayerState.PLAYING) {
$.each(players, function(k, v) {
if (this.getIframe().id != event.target.getIframe().id) {
this.pauseVideo();
}
});
}
}
}
}))
});
}
</script>
One:
<iframe frameborder="0" allowfullscreen="1" title="YouTube video player" width="160" height="100" src="http://www.youtube.com/embed/zXV8GMSc5Vg?enablejsapi=1&origin=http%3A%2F%2Ffiddle.jshell.net"></iframe>
<br/>
Two:
<iframe frameborder="0" allowfullscreen="1" title="YouTube video player" width="160" height="100" src="http://www.youtube.com/embed/LTy0TzA_4DQ?enablejsapi=1&origin=http%3A%2F%2Ffiddle.jshell.net"></iframe>
Edit: Check out Jennie Sadler's fine-tuned version below if your videos start as thumbnails.

Instead of using iframes, you actually want to use the iFrame Player API. Depending on how many videos you actually wanted to embed, you might want to make this javascript more dynamic, but this working example should give you enough to get started.
Basically what I'm doing here is initializing the two players, and pausing the opposite video when a player state changes to play.
You can play with the following code at http://jsfiddle.net/mattkoskela/Whxjx/
<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() {
player1 = new YT.Player('player1', {
height: '293',
width: '520',
videoId: 'zXV8GMSc5Vg',
events: {
'onStateChange': onPlayerStateChange
}
});
player2 = new YT.Player('player2', {
height: '293',
width: '520',
videoId: 'LTy0TzA_4DQ',
events: {
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
stopVideo(event.target.a.id);
}
}
function stopVideo(player_id) {
if (player_id == "player1") {
player2.stopVideo();
} else if (player_id == "player2") {
player1.stopVideo();
}
}

vbence's solution is really close, but there's one edit I would suggest. You should check that the other players are playing before you pause them, otherwise, playing the first embed on the page will play/pause every other embed on the page, removing the preview thumbnail and creating startling side-effects.
<script>
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
var $ = jQuery;
var players = [];
$('iframe').filter(function(){return this.src.indexOf('http://www.youtube.com/') == 0}).each( function (k, v) {
if (!this.id) { this.id='embeddedvideoiframe' + k }
players.push(new YT.Player(this.id, {
events: {
'onStateChange': function(event) {
if (event.data == YT.PlayerState.PLAYING) {
$.each(players, function(k, v) {
if (this.getPlayerState() == YT.PlayerState.PLAYING # checks for only players that are playing
&& this.getIframe().id != event.target.getIframe().id) {
this.pauseVideo();
}
});
}
}
}
}))
});
}
</script>
One:
<iframe frameborder="0" allowfullscreen="1" title="YouTube video player" width="160" height="100" src="http://www.youtube.com/embed/zXV8GMSc5Vg?enablejsapi=1&origin=http%3A%2F%2Ffiddle.jshell.net"></iframe>
<br/>
Two:
<iframe frameborder="0" allowfullscreen="1" title="YouTube video player" width="160" height="100" src="http://www.youtube.com/embed/LTy0TzA_4DQ?enablejsapi=1&origin=http%3A%2F%2Ffiddle.jshell.net"></iframe>

The above script of vbence works perfectly.
Here is the same script in javascript.
var tag = document.createElement("script");
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
var i,
frames,
players = [];
frames = document.getElementsByTagName("iframe");
const arr = Array.from(frames);
const arrnew = arr.filter((e) => {
return e.src.indexOf("https://www.youtube.com/") == 0;
});
arrnew.forEach((ele, index) => {
if (!ele.id) {
ele.id = "embeddedvideoiframe" + index;
}
players.push(
new YT.Player(ele.id, {
events: {
onStateChange: (event) => {
if (event.data == YT.PlayerState.PLAYING) {
players.forEach((ply) => {
if (ply.getIframe().id != event.target.getIframe().id) {
ply.pauseVideo();
}
});
}
},
},
})
);
});
}

I'm super new to this. I am posting this to see if this is fine.
Also I do not know jQuery so this was just a simpler way for me.
I also only have one iframe and change src. Is this a problem???
I put an id on an iframe to populate it with an array of videos.
I ran into a problem where it would keep playing it after I closed a modal box.
After looking for answers I decided to try making the iframe reference nothing.
It works but probably is not the best solution if you want both videos on screen.
function stopVid(){
var iframe = document.getElementById("videoPlayer");
iframe.src = "";
}

Vanilla JS based on answer by Jennie Sadler.
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
var players = [];
Array.prototype.slice.call(document.getElementsByTagName("iframe")).filter(function(e) {
return e.src.indexOf("https://www.youtube.com/") == 0;
}).forEach(function(youtubevideo, k, v) {
if (!youtubevideo.id) {
youtubevideo.id = 'embeddedvideoiframe' + k;
}
players.push(new YT.Player(youtubevideo.id, {
events: {
'onStateChange': function(event) {
if (event.data == YT.PlayerState.PLAYING) {
Array.prototype.slice.call(players).forEach(function(youtubevideo, k, v) {
if (youtubevideo.getPlayerState() == YT.PlayerState.PLAYING //# checks for only players that are playing
&& youtubevideo.getIframe().id != event.target.getIframe().id) {
youtubevideo.pauseVideo();
}
});
}
}
}
}))
});
}

Related

Add videos to Wordpress with autoplay and stop on scroll

I need to insert in my Wordpress page a video uploaded in Media Library. This video has to autoplay when is in browser view and has to stop on user scroll.
I tried to use tag with autoplay function and it's ok. Then I have add to my js folder (in theme folder) a file with some Javascript code in order to add stop on scroll function. I suspect that the code I have tried if fine only with YouTube link.
This is the code I have tried
//play when video is visible
var videos = document.getElementsByTagName("iframe"), fraction = 0.8;
function checkScroll() {
for(var i = 0; i < videos.length; i++) {
var video = videos[i];
var x = 0,
y = 0,
w = video.width,
h = video.height,
r, //right
b, //bottom
visibleX, visibleY, visible,
parent;
parent = video;
while (parent && parent !== document.body) {
x += parent.offsetLeft;
y += parent.offsetTop;
parent = parent.offsetParent;
}
r = x + parseInt(w);
b = y + parseInt(h);
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
playVideo();
} else {
pauseVideo();
}
}
};
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) {
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
//check at least once so you don't have to wait for scrolling for the video to start
window.addEventListener('load', checkScroll, false);
};
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
//console.log("event played");
} else {
//console.log("event paused");
}
};
function stopVideo() {
player.stopVideo();
};
function playVideo() {
player.playVideo();
};
function pauseVideo() {
player.pauseVideo();
};
Using a Youtube link the script pause video on scroll but don't autoplay. I expect both autoplay and pause on scroll using a video from my Wordpress media library
var autoPlayVideo = document.getElementById("ocScreencapVideo");
autoPlayVideo.oncanplaythrough = function() {
autoPlayVideo.muted = true;
autoPlayVideo.play();
autoPlayVideo.pause();
autoPlayVideo.play();
}
<video id="ocScreencapVideo" autoplay="autoplay" muted="muted" loop="loop" playsinline="playsinline" preload="metadata" data-aos="fade-up">
<source src="https://www.youtube.com/watch?v=W6NZfCO5SIk">
Your browser does not support MP4 Format videos or HTML5 Video.
</video>
Add this custom script to your wordpress. You can use plugins like Simple Custom CSS and JS for adding custom snippets.
Here the function checkVisible is taken from another answer here.
jQuery(document).ready(function ($) {
//To check if element is visible
function checkVisible(elm) {
var rect = elm.getBoundingClientRect();
var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
}
//To play-pause self-hosted videos in elementor only when it's visible
$(window).scroll(function () {
$(".elementor-video").each(function (i, obj) {
if (checkVisible(obj)) {
obj.play();
} else
obj.pause();
});
});
});
Rather than using a custom script, you can go with this [plugin][1] provided by Wordpress library to save time and efforts.
Another solution is to use this javascript for autoplay video:
https://codepen.io/bloodcrow777/pen/QBVKKy
var autoPlayVideo = document.getElementById("ocScreencapVideo");
autoPlayVideo.oncanplaythrough = function() {
autoPlayVideo.muted = true;
autoPlayVideo.play();
autoPlayVideo.pause();
autoPlayVideo.play();
}
<video id="ocScreencapVideo" autoplay="autoplay" muted="muted" loop="loop" playsinline="playsinline" preload="metadata" data-aos="fade-up">
<source src="http://clips.vorwaerts-gmbh.de/VfE_html5.mp4"
type="video/mp4">
Your browser does not support MP4 Format videos or HTML5 Video.
</video>

Hide youtube annotations

I'm a french designer (so, sorry for my english mistakes) and I'm trying to create an interactive video with different videos hosted on youtube.
These videos already use the youtube 'annotations' or 'cards', but I want to hide them to create my own solution.
Basically I just want to show two divs at a certain timecode of the video to allow user to click on one of them to go to a new url. This thing works.
My question is simple : how can I hide the existing annotations?
I've tried with css, but it doesn't seem to work…
I'm not a full-time developer, so if you know a simple solution, I would be happy to know it :)
Here is the code
<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: '360',
width: '640',
videoId: 'mVwQFmKc7mA',
playerVars: { 'autoplay': 1, 'controls': 1, 'rel': 0, 'showinfo': 0, 'iv_load_policy': 3 },
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(displayNewDivs, 2000);*/
done = true;
}
}
function displayNewDivs() {
// HERE THE CODE TO SHOW NEW DIVS
}
</script>
Thank you very much!

iframe api for multiple videos

I have a slideshow with youtube video's. But the problem now is that I can't trigger the onPlayerStateChange.
This is my code:
echo '<iframe id="youtube" src="http://www.youtube.com/embed/kOkQ4T5WO9E?enablejsapi=1&autoplay=1&rel=0</iframe>';
This is the JavaScript:
<script src="/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('youtube', {
events: { 'onStateChange': onPlayerStateChange }
});
}
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 onPlayerStateChange(event) {
if (event.data === 0) {
alert('Video finished, next slide');
slide.next();
}
}
</script>
Is there a way to reload the iframe api when the video has ended?
I apologize, as last I knew, the YouTube API was entirely deprecated and almost no longer supported.
You're going to need to load new videos with the loadVideoByUrl function
player.loadVideoByUrl(mediaContentUrl:String,
startSeconds:Number,
suggestedQuality:String):Void
Also, you should change event.data === 0 to event.data == YT.PlayerState.ENDED

onReady event not firing on IE11

onReady event are not being fired on IE11 & Edge, but it's working fine on IE10, Firefox, Safari and Google Chrome.
I'm using the javascript api to mute a video when the page is loaded.
This is the code i wrote. (Note. I'm using Drupal)
(function ($) {
function onPlayerReady(event) {
event.target.mute();
}
function muteVideos(video_ids) {
for (var iframe_id in video_ids) {
var player = new YT.Player(iframe_id, {
videoId: iframe_id,
playerVars:
{
"enablejsapi":1,
"origin":document.domain,
"rel":0
},
events: {
"onReady": onPlayerReady
}
});
}
}
function loadPlayer(video_ids) {
if (typeof (YT) == 'undefined' || typeof (YT.Player) == '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);
window.onYouTubePlayerAPIReady = function () {
muteVideos(video_ids);
};
} else {
muteVideos(video_ids);
}
}
Drupal.behaviors.eweev_media_youtube_video = {
attach: function (context, settings) {
// Array containing iframe ids of the youtube videos that should be
// muted provided using drupal_add_js
var video_ids = Drupal.settings.eweev_media_youtube_video;
loadPlayer(video_ids);
}
};
})(jQuery);
I wanna know if i'm missing something.
I did some research and found out that there is a temporary issue with the IFrame API.
For temporary fix, you may view the related Stack overflow below:
YouTube iframe player API - OnStateChange not firing and Youtube Iframe API not working in Internet Explorer (11)

Javascript event to catch when a Youtube video ends

I've some videos integrated through WordPress as iframe.
What I'm looking for is to redirect users to the homepage as soon as the video finishes playing.
Is there any event in Javascript to catch when existing Youtube video stops?
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() {
// first video
player = new YT.Player('player', {
events: {
'onReady': function(){ alert("Ready!"); },
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
console.log('player stopped');
}
}
Above code will work if your iframe looks as below
<iframe id="player" width="640" height="360" src="https://www.youtube.com/embed/ZdP0KM49IVk?enablejsapi=1" frameborder="0" allowfullscreen />
with id=player and ?enablejsapi=1

Resources