Play random youtube video from list/playlist and loop - javascript

We have a number of clients who have youtube video advertisements. These are currently in a YouTube playlist, but by embedding the playlist, the same video is always displayed first on the website so we want to randomise which video is displayed on pageload from the playlist. I have a code snippet which will load a random video from the input video url however when the video is finished it does not move on to the next video in the list. Could anyone suggest how I can accomplish what I am trying to do? My code is below.
<!-- Youtube video loop playlist -->
<script>
var videos = ["https://www.youtube.com/embed/9bZkp7q19f0", "https://www.youtube.com/embed/dQw4w9WgXcQ", "https://www.youtube.com/embed/CzJ-h7W1hVw"];
window.onload = function () {
var playerDiv = document.getElementById("random_player");
var player = document.createElement("IFRAME");
var randomVideoUrl = videos[Math.floor(Math.random() * videos.length)];
player.setAttribute('width', '528');
player.setAttribute('height', '330');
player.setAttribute('src', randomVideoUrl);
playerDiv.appendChild(player);
};
onStateChange: function(e){
var id = 'qzZuBWMnS08';
if(e.data === YT.PlayerState.ENDED){
player.loadVideoById(videos);
}
}
</script>
<div id="random_player"></div>
Thank you in advance.
Donna

The function loadVideoById can either get a single ID or a single video in an object syntax. It can't receive an array of videos or a playlist.
Here's my implementation
http://jsfiddle.net/thatkookooguy/e11oy0eu/2247/
(code also embedded at the end)
Notice that the setTimeout is used since there's a bug with the youtube API. if you set either setShuffle or playVideoAt immediately, nothing happens (or the playlist resets and starts from the beginning).
You can add anything else you want to change in the player's playback options (shuffle, loop). If it doesn't work as is, try to add those parameters to the setTimeout as well.
reference: youtube API - setShuffle don't work
// 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);
var player;
// load the playlist
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
events: {
'onReady': onPlayerReady
},
playerVars: {
listType: 'playlist',
list: 'PLOy0j9AvlVZPto6IkjKfpu0Scx--7PGTC'
}
});
}
// when the video player is ready, generate a random number, and play from that
function onPlayerReady(event) {
// create a random number between 0 and 149
num = Math.floor(Math.random() * 150);
// the timeout is set because of a bug with the youtube API. if you do any of this line without it, it won't affect anything
// see: https://stackoverflow.com/questions/12916017/youtube-api-setshuffle-dont-work
setTimeout(() => {
player.playVideoAt(num);
}, 1000);
}
<div id="player"></div>

Related

custom youtube playlist with custom start and end time

I am trying to make a custom youtube playlist based on the example here.
However, the youtube player gets "jammed" and skips videos (in my case the middle video is skipped). The code is supposed to iterate through the arrays below and play one video at a time with each video having separate start/end times.
How would one go about making this work properly. (note that the code below needs to be uploaded to a website to work. Apparently from a local computer, it does not work)
Here is the code I am using:
<html>
<body>
<div id="ytplayer"></div>
<script>// Load the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var i = 0;
var videoId_arr = ['O57DyNMRGY8','-Yh2QGJBd2U','M7lc1UVf-VE'];
var startSeconds_arr = [41,26,17];
var endSeconds_arr = [50,40,30];
// Replace the 'ytplayer' element with an <iframe> and
// YouTube player after the API code downloads.
var player;
var playerConfig = {
height: '360',
width: '640',
videoId: videoId_arr[i],
playerVars: {
autoplay: 1, // Auto-play the video on load
controls: 1, // Show pause/play buttons in player
showinfo: 1, // Hide the video title
modestbranding: 0, // Hide the Youtube Logo
fs: 1, // Hide the full screen button
cc_load_policy: 0, // Hide closed captions
iv_load_policy: 3, // Hide the Video Annotations
start: startSeconds_arr[i],
end: endSeconds_arr[i],
autohide: 0, // Hide video controls when playing
},
events: {
'onStateChange': onStateChange
}
};
function onYouTubePlayerAPIReady() {
player = new YT.Player('ytplayer', playerConfig);
}
function onStateChange(state) {
if (state.data === YT.PlayerState.ENDED) {
i++;
if(typeof videoId_arr[i] === 'undefined')
return;
player.loadVideoById({
videoId: videoId_arr[i],
startSeconds: startSeconds_arr[i],
endSeconds: endSeconds_arr[i]
});
}
}
</script>
</body>
</html>
I have tested your code and I figured out that the state is changing for some unknown reasons very quickly. The state has sometimes the value 0 which equals YT.PlayerState.ENDED although the video was not played.
You can see it by console logging state.data within the onStateChange function.
A small change fixed the problem:
function onStateChange(state) {
var _video_url = state.target.getVideoUrl();
var _video_id = _url.split('v=')[1];
var _current_index = videoId_arr.indexOf(_video_id) +1;
console.log('State: ', _video_id, _current_index, state );
// ensure that the video has been played
if (state.data === YT.PlayerState.ENDED && player.getCurrentTime() >= endSeconds_arr[i]) {
i++;
if(typeof videoId_arr[i] === 'undefined'){
i = 0; // rest the counter
return;
}
}
}
For the code to run properly you should disable browser plugins like Video Resumer or similar - since they can change the state of a youtube video or resumes the videos from where you stopped them last
fiddle: https://jsfiddle.net/_kdts/Lx91ehdw/
I it possible to loop the videos? I was trying by changing i=1
if(typeof videoId_arr[i] === 'undefined'){
i = 1; // rest the counter
return;
}

how can I get my YouTube playlist to shuffle on start and play random videos until the full playlist has played without repeating any of the videos?

OK... been working on this for a couple of months with no working results as of yet... So, now asking for help! I have a YouTube playlist, ID: PLl_KM23gznEAZW-INW8ty4QNaHH8JCnNW. This playlist has close to 1500 videos on it. I am needing a code that will call the list, and play a random video from the list. and I need it to play all 1500 videos in a random order without repeating any of the videos. then after the playlist is completed, it needs to start over, continuing to play the videos in a completely different random order.
I have tried several code snippets and can't seem to get it all to come together. I either get a shuffle with repeats, or I get just a list that doesn't play anything, or it will randomly pick the first video, then maybe the second one, but it will start playing in order from either the first or the second video. And the current youtube player that is working will only call the videos in a 200 song list. IE: if the payer starts in order, only will play 1 through 200, then stop. Or, I can set it to start with any song in the playlist, for instance, # 999, it will go to that video, but will only play videos fromm 999 to 1198.
I have to randomly pick the song and put it in my code to get it to do that.
I need it to start in shuffle mode, choosing any song from the list of 1500 videos, then continue randomly choosing and playing any other video within the list except those that have already played, until it has played all the videos, then loop the playlist and continuing to play a random video from the playlist in no certain order, including the order it just played. My main thing to avoid... having to create the list array manually. I need to be able to call the url of the playlist, and retrieve a list of the videos either by number, video ID, name of the song, etc. Using the easiest, cleanest code.
PS: having comments in place is extremely helpful for my learning process.
And please don't worry about anything, I am 51, disabled, and trying to remind myself of the coding syntaxes after getting a degree in 2003 and not using a bit of it since! I am working on a project for myself, more or less trying to get myself back into being able to read, repair, and create coding for myself. This part though, has me totally stumped!
I hope this is making sense to someone, I'm getting confused just trying to ask the question!!!
tried this one, got nothing... just a blank page...
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() {
var player = new YT.Player("player", {
height: '390',
width: '640',
events: {
'onReady': function (event) {
event.target.cuePlaylist({list: "PLl_KM23gznEAZW-INW8ty4QNaHH8JCnNW"});
event.target.playVideo();
setTimeout(function() {
event.target.setShuffle({'shufflePlaylist' : true});
}, 1000);
}
}
});
}
this one will load the player, but doesn't shuffle or play randomly. just starts with the first video, then continues in order...
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: '390',
width: '640',
events: {
'onReady': onPlayerReady
},
playerVars: {
listType:'playlist',
list: 'PLl_KM23gznEAZW-INW8ty4QNaHH8JCnNW'
}
});
}
function onPlayerReady(event) {
num = _.random(0, 1500);
setTimeout(() => {
player.playVideoAt(num);
}, 1000);
}
this one will start with a random video, but then continues in order from there...
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() {
var numPl = Math.floor((Math.random() * 1500) + 1);
var player = new YT.Player("player", {
height: '390',
width: '640',
playerVars: {
listType:'playlist',
list:'PLl_KM23gznEAZW-INW8ty4QNaHH8JCnNW',
index: numPl,
autoplay: 1,
},
events: {
'onReady': function (event) {
event.target.cuePlaylist({list: "PLl_KM23gznEAZW-INW8ty4QNaHH8JCnNW"});
event.target.playVideo();
setTimeout(function() {
event.target.setShuffle({'shufflePlaylist' : true});
}, 1000);
}
}
});
}
function onPlayerReady(event) {
event.target.mute();
setTimeout( function() {
event.target.setShuffle(true);
event.target.setLoop(true);
}, 2000);
}
function getRandomId() {
var random_id = 0
while(played_idx.indexOf(random_id) != -1) {
random_id = Math.floor(Math.random * playlist.length)
}
return random_id
}
I'm pretty sure there were more, but can't find them at the moment.

Access 'Stats for nerds' data in youtube iFrame

I'm currently doing measures on the quality of a video youtube depending on given network conditions. I wrote a custom Chrome extension to play videos and get buffering informations thanks to the youtube player api.
What I would need now is the content of the 'Stats for nerds' panel that appears when you right-click on the video (example).
I can display it thanks to UI automation. But, when I try to access the content of this panel with javascript, I get an error because of Cross-origin resource sharing (CORS).
I only want to read the Current/OptimalRes of the panel. Do you have any idea of a way to get it?
I've been searching for an answer to this question for long now. It has been mentioned here, but the answer to this post is not what I'm looking for as it only gives the general information about the video, not the resolution that is actually being played.
Apologies that this code is in 'AutoIT', but it should be easy to pipe to Javascript or any other similar language. This is a complete list of the 'Stats for Nerds' data:
#include <IE.au3>
;Attach to open YouTube player within browser
$oIE = _IEAttach ("https://www.youtube.com", "url",1)
;Get a reference to the movie player
$oPlayerRef = $oIE.document.getElementById("movie_player")
;Video ID / sCPN
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).video_id_and_cpn)
;Viewport / Frames
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).dims_and_frames)
;Current / Optimal Res
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).resolution)
;Volume / Normalized
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).volume)
;Codecs
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).codecs)
;Connection Speed
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).bandwidth_kbps)
;Network Activity
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).network_activity_bytes)
;Buffer Health
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).buffer_health_seconds)
;Mystery Text
msgbox(0,"",$oPlayerRef.getStatsForNerds(0).debug_info)
player.getPlaybackQuality();
Just call this function in the code given below
This code is from https://developers.google.com/youtube/iframe_api_reference
<!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',
playerVars: {
'playsinline': 1
},
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 am struggling with setting up the loop for youtube api by using my code each time loop video is loading.I have put only one video in loop

Here is my video
http://dynamitechefs.ch/
I have put one video to loop. The video is loading each time. How can I remove video loading?
Here is my code
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: mediaParams['height'],
width: mediaParams['width'],
videoId: mediaParams['v'],
playerVars: {
controls: 1,
showinfo: 0 ,
startAt:1,
rel:0,
loop:1,
playlist : 'BmAL33M0jcI'
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
Thanks in advance.
Based from the documentation of IFrame API Player Parameters, when you play a single video player, a setting of 1 causes the player to play the initial video again and again. In the case of a playlist player (or custom player), the player plays the entire playlist and then starts again at the first video.
Just take NOTE that currently, the loop parameter only works on the
AS3 player when used in conjunction with the playlist parameter. To
loop a single video, set the loop parameter value to 1 and set the
playlist parameter value to the same video ID already specified in the
Player API URL:
https://www.youtube.com/v/VIDEO_ID? > version=3
&loop=1
&playlist=VIDEO_ID
For more information, use this demo to know how the different parameters of IFrame API works.
You could use the player.seekTo function to seek to the beginning of the video when the video is close to the end (i.e. 99% complete) to keep the player buffer in memory and prevent a reload. You can see this example in the code below:
var player;
// Callback for when the YouTube iFrame player is ready
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
// Set Player height and width
height: '390',
width: '640',
// Set the id of the video to be played
videoId: 'Rykmwn0SMWU',
// Setup event handelers
events: {
'onReady': onPlayerReady,
}
});
};
function onPlayerReady() {
var interval = setInterval(function(){
console.log(player.getCurrentTime() / player.getDuration())
if (player.getCurrentTime() / player.getDuration() > .99) {
player.seekTo(0)
}
},500);
}

Youtube API using unrelated worker?

This is very weird. I'm using youtube JavaScript API to embed a playlist on my website. It would be all good except my recent check what's happening in my workers. It seems that the API decided to send it's messages to one of it.
here's the data which my worker is receiving.
bubbles: falsecancelBubble: falsecancelable: falsecurrentTarget: Windowdata: "{"event":"infoDelivery","info":{"currentTime":109.455757,"videoBytesLoaded":1,"videoLoadedFraction":1},"id":1}"defaultPrevented: falseeventPhase: 0lastEventId: ""origin: "https://www.youtube.com"path: Array[1]ports: Array[0]returnValue: truesource: WindowsrcElement: Windowtarget: WindowtimeStamp: 1428083437641type: "message"__proto__: MessageEvent
Also as I've seen in another question Youtube API does this
www-embed-player.js:167 GET chrome-extension://enhhojjnijigcajfphajepfemndkmdlo/cast_sender.js net::ERR_FAILED
I wasn't expecting Google to create such faulty API. Is there a way to disable those things?
Quick experiment rendered a solution. Moved all youtube code to a separate html and embedded in my parent page.
<iframe id="youtubePlayer" src="mediaPlayer.html">
You can still access youtube api from your main page like that
var mediaPlater = document.getElementById('youtubeFrame').contentWindow.player;
// i.e. skip to next video
mediaPlayer.nextVideo();
This solved totally unexpected worker activity. This console error remained but after reading that it's a won't-fix it doesn't bother me.
www-embed-player.js:167 GET chrome-extension://
Content of my mediaPlayer.html
<div id="ytplayer" class="musicPlayer"></div>
<script>
var player = null;
// Load the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = 'https://www.youtube.com/player_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// Replace the 'ytplayer' element with an <iframe> and
// YouTube player after the API code downloads.
function onYouTubePlayerAPIReady() {
player = new YT.Player('ytplayer', {
height: '180',
width: '280',
playerVars: {
autoplay: 1,
controls: 0,
listType: 'playlist',
list: 'RD4-OlYiH1DXI'
},
events: {
'onReady': onPlayerReady,
'onError': function () {
setTimeout(function () {
player.nextVideo();
}, 200);
}
}
});
}
function onPlayerReady() {
// fixes firefox ignoring first onerror if the first video is faulty
player.nextVideo();
}
</script>

Categories

Resources