YouTube Iframe API - Play video on mobile - javascript

After searching and finding many similar questions, I can't find the correct answer. So I'm working with the YouTube Iframe API, and I know that autoplay etc. won't work for mobiles. And I have created a element that displays on mobiles, so when the user click that button, it should play the video. But I only get this message: "Try restarting your device if playback does not start soon".
var playElement = document.createElement("div");
playElement.style.display = "none";
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
playElement.style.display = "block";
}
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player(child, {
width: '100%',
height: '100%',
videoId: youtubeID,
playerVars: {
'iv_load_policy': 3,
'enablejsapi': 1,
'disablekb': 1,
'autoplay': 1,
'loop': 0,
'controls': 0,
'showinfo': 0,
'rel': 0,
'mode': 'transparent'
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
playElement.onclick = function() {
player.playVideo();;
};
Anyone that does have an actual working solution?

Remember player refers to a div with the ID 'player'. You can start with the example code on youtube api doc. It will autoplay when the video has loaded. You can add your playerVar options as well.
A note for mobile video autoplay. You can have it autoplay but it has to be muted. So you can try adding player.mute() when you it loads and setup a click handler to unmute it again if that is what you prefer.
<!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 = "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
},
playerVars
});
}
// 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();
}
</script>
</body>
</html>

Related

Add video to page using YouTube Player API

I want to load a YouTube video on a button click using the Player API. The goal is that a user can input a video url, click a button, and then the video loads below (I excluded the form input below to make it a little simpler).
I've tried using location.reload(); to force reload the page, and checked out some other similar questions which aren't entirely helpful because they don't use the API (which I need to use for later when functionality added)
This example from the docs works fine:
<!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 = "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
}
});
}
// 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();
}
</script>
</body>
</html>
I want to get something like this (very similar version) to work. I'm not sure why it doesn't currently.
<!DOCTYPE html>
<html>
<body>
<input type="submit" value="Submit" id="submit">
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<script>
document.getElementById("submit").addEventListener("click", function() {
location.reload();
// 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
}
});
}
// 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();
}
});
</script>
</body>
</html>
You have two issues.
1) onYouTubeIframeAPIReady is never called because it is defined after the youtube API loads. You can see this by adding a console.log.
2) When you reload the page, the page reloads; i.e. your previous variables and video and everything are gone.
Here's a minimal example to load & play a youtube video on button click:
<input type="submit" value="Submit" id="submit">
<div id="player"></div>
<script src="https://www.youtube.com/iframe_api"></script>
<script>
document.getElementById('submit').addEventListener('click', () => {
new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
onReady: e => e.target.playVideo()
}
});
});
</script>
Note, the youtube code samples are either trying to be backwards compatible or just haven't been rigorously updated. They don't follow modern styles (e.g. they use var instead of let, == instead of ===, " instead of ', etc.

Youtube's onStateChange is not fired if play is triggered by postMessage

If the youtube playVideo is triggered by postMessage, the onStateChange will not be fired. (http://jsfiddle.net/nedvedyy/smx92nq0/). Any one runs into it before?
<script src="jquery-1.10.2.min.js"></script>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
<button class="button">BUTTON</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: '0Bmhjf0rKe8',
playerVars: {
'controls': 1
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
var playerReady = false;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
playerReady = true;
}
// 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.
function onPlayerStateChange(event) {
alert(event);
}
$(".button").on("click", function() {
document.getElementById('player').contentWindow.postMessage(JSON.stringify({
'event': 'command',
'func': 'playVideo',
'args': []
}), "*");
});
</script>
Strangely, if the playVideo is called like below, the onStageChange can be captured.
onPlayerReady=function(event) {
console.log("hey Im ready");
event.target.playVideo();
}
Did you complete your homework here? Go through complete manual, your solution is there from where you pasted.
https://developers.google.com/youtube/iframe_api_reference

Youtube - onStateChange working on one video but not another

The same code behaves differently, when you change the YouTube video ID.
The issue is that when you pull the progress slider, it fires the onStateChange event on one video, but not the other. Check the two examples below, and try to pull the timeslider on both examples and watch your console.log.
Why does only one of the videos react to onStateChange when you pull the time slider?
Both videos react fine to the play/pause button, but not the time slider... only one is working.
Am I missing something? Any help really appreciated
Youtube code 1 (working):
(http://jsfiddle.net/2t9omgwm/)
<!-- 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 = "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',
iv_load_policy: 3,
showinfo:0,
//videoId: 'Fj73JF_bhjc',
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) {
console.log('state changed');
//player.seekTo(0, true);
if (event.data == YT.PlayerState.PLAYING && !done) {
done = true;
}
}
</script>
And with another video its not working:
(http://jsfiddle.net/ctgomt7t/)
<!-- 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 = "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: '0Bmhjf0rKe8',
iv_load_policy: 3,
showinfo:0,
//videoId: 'Fj73JF_bhjc',
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) {
console.log('state changed');
//player.seekTo(0, true);
if (event.data == YT.PlayerState.PLAYING && !done) {
done = true;
}
}
</script>
`
The onPlayerStateChange event is fired for one of the following reasons:
-1 = unstarted
0 = ended
1 = playing
2 = paused
3 = buffering
5 = video cued
I think what you are seeing on the longer video is the event firing for (3) buffering when you move the slider. However, on the shorter video there is no buffering so you don't see the event.
You can see this by changing your code to read console.log('state changed : ' + event.data).

Insert YouTube iframe after the page is loaded

I have a main YouTube video and some related videos at the bottom. YouTube video is loaded from a costum video name parameter in my url. If a video name exists YouTube iframe is loaded on page load but if a video name dosen't exists YT iframe isn't loaded until the user clicks a related video at the bottom. If the user clicks an related video the iframe is loaded and the same function onPlayerReady, and onPlayerStateChange should be used as the iframe was loaded from the begining. How can I insert the iframe in page and use the same function I use as it was loaded from the beginning. ?
player.js
var tag = document.createElement('script'),
firstScriptTag = document.getElementsByTagName('script')[0],
player;
tag.src = "https://www.youtube.com/player_api";
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubePlayerAPIReady() {
player = new YT.Player('ytplayer', {
height: height,
width: width,
videoId: yt_id,
playerVars: {
wmode: "transparent",
controls: 0,
showinfo: 0,
rel: 0,
modestbranding: 1,
iv_load_policy: 3 //anottations
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
};
function onPlayerReady(event) {
//code here
//I want to use this code even when the player is loaded after the page is loaded (when the user clicks a related video at the bottom)
}
function onPlayerStateChange(event) {
//here too
}
insert_frame.js
var tag = document.createElement('script'),
firstScriptTag = document.getElementsByTagName('script')[0],
player;
tag.src = "https://www.youtube.com/player_api";
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
player = new YT.Player('ytplayer', {
height: height,
width: width,
videoId: yt_id,
playerVars: {
wmode: "transparent",
controls: 0,
showinfo: 0,
rel: 0,
modestbranding: 1,
iv_load_policy: 3 //anottations
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
How can I insert the iframe in page and use the same function I use as
it was loaded from the beginning. ?
If i understand correctly, you want to do that because some videos ID on the url may be false and the player iframe will not play the video.
Well you don't need insert a frame just because a video ID exist when use click on a related videoo the bottom, use onError parameter from YouTube Player API.
This event fires if an error occurs in the player. The API will pass
an event object to the event listener function. That object's data
property will specify an integer that identifies the type of error
that occurred. ...
If the videoID on the url doesn't exist an error will be send. Just hide the player for example and show it when the user click on a related video on the bottom.
With this solution you only need to load the player one and only one time without insert a frame into the code even if the id is wrong. A sample solution.
I made you a little example with a wrong videoID :
HTML
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div id="player"></div>
</body>
</html>
Javascript
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: 'l-gQLqv9f4',
events: {
'onError': onPlayerError,
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
$('#player').show();
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
}
}
function stopVideo() {
player.stopVideo();
}
function onPlayerError() {
console.log("error on the video id. Iframe is hiding");
$('#player').hide(); //or do what you want
}
Live demo: http://jsbin.com/mihikiqoma/1/edit?html,js,output

How can I play two Youtube videos without linking to a playlist?

I'm very new to Javascript. I'm embedding a youtube iframe here:
http://www.heartlandpokertour.com/indexbeta.php
Using this documentation:
http://code.google.com/apis/youtube/iframe_api_reference.html
I would like a second video to play, looped, after the first one is finished. I'm unable to set specific video parameters if I try and link/set the video id to a Youtube playlist.
I'm assuming I need to setup an event listener and function to trigger when YT.PlayerState.ENDED (or 0) is broadcast, but NO IDEA how to do this.
Update: Here is the current code I'm using for the player:
<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: '258',
width: '406',
videoId: 'MsTQNZmq5Pk',
playerVars: { 'autoplay': 0, 'rel': 0, 'showinfo': 0, 'egm': 0, 'showsearch': 0, },
events: {
'onStateChange': onPlayerStateChange,
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
player.stopVideo();
player.videoId = 'c5dTlLk5_x8';
player.playVideo();
}
}
</script>
In the first code listing on the api website, this event might help you:
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
You could change it to something like this (not tested I'm afraid):
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
player.stopVideo();
player.videoId = 'some id';
player.playVideo();
}
}
This would be the most logical in my opinion, but then again I'm not sure whether different videos can be played within one player instance. I've never come across your scenario I'm afraid.
Edit: You could try creating a new instance of the player. So basically you'd just create a new player, which will play the second video:
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
player.stopVideo();
player = new YT.Player('player', {
height: '258',
width: '406',
videoId: 'some id',
playerVars: { 'autoplay': 0, 'rel': 0, 'showinfo': 0, 'egm': 0, 'showsearch': 0, },
events: {
//'onStateChange': onPlayerStateChange, // not add this line because it would again create a new player after the second has stopped I guess!
}
});
player.playVideo();
}
}
I have got this working on my site, first you can stop the current video playing, then load in a new video with the loadVideoById() function from the Youtube API
function swapVideo() {
player.stopVideo();
player.loadVideoById(youtube_id);
}

Categories

Resources