This is a video that plays on my site but the user can't actually see it, they can only hear it. I want to create a button so that if the user want's to mute the video at anytime then they can just select that button and all sound on the site will stop but if they click it again then they should be able to hear it again. If your struggling to understand what I mean please post a comment as it would be really helpful. Thanks!
// create youtube player
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '0',
width: '0',
videoId: 'a5SMyfbWYyE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// autoplay video
function onPlayerReady(event) {
event.target.playVideo();
}
// when video ends
function onPlayerStateChange(event) {
if(event.data === 0) {
//alert('done');
}
}
First create a button in your html with an ID :
<input id="mute-toggle" type="button"/>
And get the ID with JQuery :
$('#mute-toggle').on('click', function() {
var mute_toggle = $(this);
if(player.isMuted()){
player.unMute();
mute_toggle.text('volume_up');
}
else{
player.mute();
mute_toggle.text('volume_off');
}
});
Related
When I create an instance of YT.Player(HTMLIFrameElement, { options }) I get back an object that has:
destroy
setSize
getIframe
addEventListener
getVideoEmbedCode
getOptions
getOption
But not playVideo, pauseVideo etc as described in the documentation.
I got a demo here: http://siesta-annotations.surge.sh/Siesta_webviewer_test/?page=3
I am creating the iframes via the DOM in trait.playable.youtube.js and adding the iframe to a documentFragment that eventually will be added to a div:
const element = document.createElement('iframe')
element.src = `https://www.youtube.com/embed/${id}?rel=0;&autoplay=${this.options.autostart ? 1 : 0};&enablejsapi=1;&origin=${location.hostname};`
element.style = this.inlineStyle
I then create an instance of YT.Player:
// nasty initialization because we're outside webpack and this is a demo
if (global.YT.loaded) {
this.player = new global.YT.Player(element, {
events: {
'onStateChange': this.stateHandler,
'onReady': onPlayerReady
}
})
} else {
const oldHandler = global.onYouTubeIframeAPIReady
global.onYouTubeIframeAPIReady = () => {
if (oldHandler) oldHandler()
this.player = new global.YT.Player(element, {
events: {
'onStateChange': this.stateHandler,
'onReady': onPlayerReady
}
})
}
}
The instance of YT.Player looks something like this:
It looks like the minification process went very wrong. What am I doing wrong - how should I initialise YT.Player for my use-case?
This is my second post, I hope that I can solve your problem.
I am not 100% sure about how your code works, but I suspect ...
It seems like a double instantiation of the YT.Player object, which will cause the YT.Player object unstable.
I myself also struggled for a long time (ps: I am an amateur programmer.๐
)
As an example, the following snippets is modifed from Youtube Iframe API website and an example of how the second instantiation will break the player object try it! JS Bin:
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
</br>
<button onclick="instantiateOneMore()">
Call
<pre>new YT.Player('player')</pre>
</button>
<button onclick="pauseVideo()">
pauseVideo();
</button>
<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', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
let callTime = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
callTime ++;
console.log(callTime);
//document.querySelector('#dd').innerHTML = player.pauseVideo;
}
function pauseVideo(){
player.pauseVideo();
}
instantiateOneMore = () => {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
//document.querySelector('#dd').innerHTML = player.pauseVideo;
}
// 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();
} */
</script>
</body>
</html>
Furthermore, the second onPlayerReady(), won't even be called. So if you intend to put some counter to see how many times the new YT.Player(...) is called, you will suspect it only be called once. Which makes the effect ghost away from debugging.
Strangely enough you do not get access to the YTPlayer API until 'onReady' is called in the constructor player options object. https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
function onYouTubeIframeAPIReady() {
new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': function (event) {
onPlayerReady(event.target)
},
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(player) {
player.playVideo();
}
This of course only works for one player, so you need to roll out your own YouTube player manager if you want to handle multiple players. (I know the API is insane)
A quick solution could be the following if you have iframes with youtube videos (untested):
const YTManager = {
videos: [],
youtubeApiReady = false,
initialize () {
const matchId = /[^/]+$/
this.youtubeApiReady = true
document.querySelectorAll('iframe[src*="youtube"]')
.forEach(iframe => this.videos.push({
dom: iframe,
player: null,
videoId: iframe.src.exec(matchId) ||ย iframe.src.exec(matchId)[0]
}))
},
createPlayers () {
if (this.youtubeApiReady === false) return
this.videos.forEach(v => {
new YT.Player(v.dom.id, {
videoId: v.videoId,
events: {
'onReady': function (event) {
v.player = event.target
}
}
})
})
},
find (id) {
return this.videos.find(v => v.id === id)
},
play (id) {
const video = this.find(id)
if (this.youtubeApiReady && video && video.player) {
video.playVideo()
}
},
pause (id) {
const video = this.find(id)
if (this.youtubeApiReady && video && video.player) {
video.pauseVideo()
}
},
}
window.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
// YouTube client side script has been loaded
YTManager.youtubeApiReady = true
YTManager.createPlayers()
}
document.addEventListener("DOMContentLoaded", function() {
// all iframes has been parsed by the browser
YTManager.initialize()
});
Of course you can not call YTManager.play or YTManager.pause without having the ID and wait for the YouTube script to load and then the video initialization to finish. All in all, a real mess. I'm sure you can come up with a better manager. I have written one at work that is better but also works with completely different objects and requirements, so it's not a good fit for general purpose YouTube video manager. But the one above is the gist of my current player.
I recommend using iframes from the beginning - if anything goes wrong in your script, the videos will still be playable, you will just not have any control of them.
Iframed youtube videos looks like this:
<iframe
id="uniqueDOMElementID1"
width="560"
height="315"
src="https://www.youtube.com/embed/bHQqvYy5KYo"
frameborder="0"
allow="autoplay; encrypted-media"
allowfullscreen></iframe>
I am developing an website where my client wants to be able to play an youtube video when he clicks an image and when the video finishes, the video disappears and the same image reappears again.
For example, view the website below and click the image on the home page.
https://www.oldbankruptcypapers.com/
You can use the youtube Iframe API (https://developers.google.com/youtube/iframe_api_reference) to resolve this.
Here is the example script:
$('#yourImage').on('click', function () {
var player = new YT.Player('yourDivToAppendVideo', {
// height: '1080',
// width: '1920',
videoId: 'putVideoIdHere',
playerVars: {
'autoplay': 1,
'controls': 0,
'showinfo': 0,
// and other options
},
events: {
'onReady': function (event) {
// Write your logic to HIDE the image here
event.target.playVideo(); // play video
},
'onStateChange': function (event) {
if (event.data == YT.PlayerState.ENDED) {
// Write your logic to UNHIDE the image here
}
}
}
});
}
You can follow below approach to achieve that :
When you click on the image, hide it and make your player container div visible. Bind onStateChange event of your YT Player to check for video ending and then hide the player or remove it and make your image visible.
Below is the code snippet :
<img src="http://d3gnp09177mxuh.cloudfront.net/tech-page-images/java.png" id="javaImg">
<div id="playerContainer">
<div id="player" width="300" align="left" height="238" style="margin-right:30px;"></div>
</div>
$("#javaImg").click(function(){
if($("#player").is("div"))
{
$(this).hide();
player = new YT.Player('player', {
height: '335',
width: '596',
playerVars: { 'controls': 1,'autohide':1},
videoId: 'r59xYe3Vyks',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
else {
player.autohide=1;
player.playVideo();
}
function onPlayerReady(event) {
event.target.playVideo();
}
function onPlayerStateChange(event) {
if(event.data === 0) {
$("#player").remove();
$("#playerContainer").append('<div id ="player" width="300" align="left" height="238" style="margin-right:30px;"></div>');
$("#javaImg").show();
}
}
});
I have also created a fiddle, https://jsfiddle.net/qLzpg27g/
From the API :
function onPlayerStateChange(event) {
if(event.data === 0) {
//replace video with image
}
//status states from API
// -1 โ unstarted
// 0 โ ended
// 1 โ playing
// 2 โ paused
// 3 โ buffering
// 5 - Video Cued
https://developers.google.com/youtube/iframe_api_reference#Retrieving_video_information
I can load and play Youtube Video via the iFrame API, but I can't figure out how to change the player parameter for the second video. I want no controls on the first video and then when user click on my custom Play Video, I want to play the second video with controls bar. I can set the playerVars on player initiation, but I don't know how to change it when the player is already loaded. Any ideas?
Thanks much.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
videoId: 'M7lc1UVf-VE',
playerVars: { 'autoplay': 1, 'controls': 0 },
events: {
'onReady': onPlayerReady,
'onPlaybackQualityChange': onPlayerPlaybackQualityChange,
'onStateChange': onPlayerStateChange,
'onError': onPlayerError
}
});
}
function onPlayerReady {
var $btn = '<button id="play">Play Button</button>';
$('#nav').prepend($btn);
$('#play').click(function() {
player.loadVideoByUrl('http://youtu.be/GBHxL-LXJbs?controls=1');
});
}
I load and play a youtube video in a fancybox. It all works perfectly, except when I close the fancybox it starts the video again.
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '480',
width: '853',
videoId: 'I76i-TCaUCY',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// autoplay video
function onPlayerReady(event) {
event.target.playVideo();
}
// when video ends
function onPlayerStateChange(event) {
if (event.data === 0) {
$.fancybox.close();
}
}
The user should be able to play it again if needed, so I can't delete it.
How do I play it for the first time only?
I don't know if there is an easier way, but this is how I have fixed it for my needs:
I added var played = false and:
// autoplay video
function onPlayerReady(event) {
//This ensures that it is autoplayed only once.
if (!played) {
event.target.playVideo();
played = true;
}
}
It now works as I was expecting.
I've spent the day banging my head on this. I've made some good progress, but this last part has me stuck.
I'm using YouTube's API. I have a listener event configured, and the video autoplays, and autocloses on completion. All of that works great.
What I want to do is have more than one video on a single page (5, actually) assigned by DIV. Is there a way to do that with this code?
// create youtube player
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '488',
width: '800',
videoId: '49QKXdRTX-A',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// autoplay video
function onPlayerReady(event) {
event.target.playVideo();
}
// when video ends
function onPlayerStateChange(event) {
if(event.data === 0) {
$("#player").hide();
}
}
Additionally, it's worth mentioning that I will have a couple of these videos auto-show another DIV on completion, so something like this:
function onPlayerStateChange(event) {
if(event.data === 0) {
$("#player").hide();
$("#gallery-main").show();
ANY help would be greatly appreciated. Thanks!