0

I have an array of mp4 videos that I need to display randomly with no repeats in a website header. After the last video plays, it should reshuffle and start over. The sequence needs to begin on page load. Each video needs to have an on hover text description specific to that video.

I am trying to use this shuffle code with this example of a no-repeat playlist

I haven't even gotten to the on-hover text because I can't get the shuffle sequence to work. I am not an expert.

This is the current version of my attempt. I know things are in the wrong order because I get "undefined" errors.

function shuffle(vids) {
    let currentIndex = vids.length,  randomIndex;
    while (currentIndex != 0) { 
             randomIndex = Math.floor(Math.random() * currentIndex); 
         currentIndex--;
         [vids[currentIndex], vids[randomIndex]] = [vids[randomIndex], vids[currentIndex]];
    }
        return vids;
        playvids();
}
function playvids() {
     var vids = ["vid1.mp4","vid2.mp4","vid3.mp4"];
     for(var i = 0; i < vids.length; ++i){
     document.getElementById("myvideo").addEventListener('ended', getnextfile);     
     document.getElementById("myvideo").src = "" + vids[i] + "";
     }
}                   
function getnextfile() {
     if(i >= vids.length){ 
          shuffle(vids);
     } 
     return vids[i++];  
        
}
} 
window.onload = playvids();
<video id="myvideo" src="" muted autoplay></video> 

The window.onload is supposed to play a video from the array, then the eventlistener should call getnextfile at the end of the video, which is supposed to check to see if it is the last video in the array - if it is, reshuffle, if it isn't, increment by 1 to play the next video in the array. And I would prefer it shuffle the array before it plays for the first time, but I couldn't figure out how to do that.

My results ranged from undefined vars, to the video playing once and nothing happening, to the videos playing randomly but often repeating the same video more than once.

AAColema
  • 1
  • 1

2 Answers2

0

After reading the code base I found some issue. hope this will help you understand.

The playvids() function should be called inside the shuffle() function so that the shuffled array is used to play the videos.

vids array outside the playvids() function so that it is accessible to other functions.

getnextfile() function should return the next video file to be played, not just the index of the next file.

var vids = ["vid1.mp4", "vid2.mp4", "vid3.mp4"];
var i = 0;

function shuffle(vids) {
  let currentIndex = vids.length,
    randomIndex;
  while (currentIndex != 0) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;
    [vids[currentIndex], vids[randomIndex]] = [vids[randomIndex], vids[currentIndex]];
  }
  playvids();
}

function playvids() {
  shuffle(vids); // shuffle the array before playing the videos
  document.getElementById("myvideo").addEventListener('ended', getnextfile);
  document.getElementById("myvideo").src = "" + vids[i] + "";
}

function getnextfile() {
  if (i >= vids.length) {
    shuffle(vids); // reshuffle the array if all videos have been played
    i = 0; // reset the index to 0
  }
  var nextFile = vids[i];
  i++;
  return nextFile;
}

window.onload = playvids;
raman
  • 960
  • 8
  • 18
  • From what I can tell, the above solution doesn't work. There is a recursive loop as shuffle(vids) calls playvids() which immediately calls shuffle(vids). If removed, a video plays once and then nothing happens. I tried adding for(var i = 0; i < vids.length; ++i){ to the playvids function, but then it runs without waiting for the first video to complete. – AAColema Mar 02 '23 at 14:35
0

Using some of raman's answer, I came up with a solution that works. I have also added a mouse-over pause that displays overlay text on the videos.

The below code correctly starts a shuffled playlist on page load, waits until a video finishes playing before playing the next video, then reshuffles and starts over once the last video has played. On mouseover, the video pauses and dims and a text overlay specific to that video is displayed.

Notes (some things I learned):

Eventlisteners must be removed after they are added, otherwise they can begin to fire multiple times. Jquery is better for this.

Multiple objects can be tied to one index in an array by defining the object sets and then adding/pushing them to the array.

var bannervid = document.getElementById("myvideo");

function playVid() {
  bannervid.play();
} // introduce a function to play or pause the video

function pauseVid() {
  bannervid.pause();
}

var vids = []; //push the objects to the array so that you can include multiple objects per index, in this case the video url and a text description
vids.push({
  url: "vid1.mp4",
  credits: "some text for vid 1"
});
vids.push({
  url: "vid2.mp4",
  credits: "some text for vid 2"
});
vids.push({
  url: "vid3.mp4",
  credits: "some text for vid 3"
});
var i = 0; //set the index to 0

function shuffle(vids) {
  let currentIndex = vids.length,
    randomIndex;
  while (currentIndex != 0) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;
    [vids[currentIndex], vids[randomIndex]] = [vids[randomIndex], vids[currentIndex]];
  }
  playvids(); //shuffle using Fisher-Yates algorithm then call the playvids function after the array has been shuffled
}

function playvids() {

  if (i >= vids.length) {
    i = 0;
    shuffle(vids);

  } //if the index has reached the end and the last video has played, reshuffle
  else { // otherwise, play the next video and increment the index by 1 
    var nextFile = vids[i].url;
    var nextCredits = vids[i].credits;
    $('#myvideo').bind('ended', function() {
      $('#myvideo').unbind('ended');
      playvids();
    }); //jquery code to correctly bind and then unbind the event listener so that it waits until the video has played to the end before playing the next video

    document.getElementById("myvideo").src = "" + nextFile + ""; //insert the current video's url into the video html element
    var creditspar = document.getElementById("bannercredits");
    creditspar.textContent = "" + nextCredits + ""; //insert the text description of the current video from the array into an html element, in this case a P element inside a div wrapping the video
    i++; //increment the index by 1 
  }
}


window.addEventListener("load", (event) => {
  shuffle(vids); //begin the entire sequence on page load
});
#bannercredits {
  text-align: end; //justify the video description text (optional)
}

.video_wrapper_text {
  position: absolute; //make the text overlay
  top: 15px; //your preference
  right: 62px; //your preference
  opacity: 0; //hide the text until mouse hover
  -webkit-transition: all 800ms ease; //fading effect for text
  transition: all 800ms ease;
}

.video_wrapper:hover .video_wrapper_text {
  opacity: 1; //fade in text
}

.bannervid {
  -webkit-transition: all 800ms ease; //fading effect for video brightness
  transition: all 800ms ease;
  ;
}

.video_wrapper:hover .bannervid {
  filter: brightness(0.3); //darken video on mouse hover
}

.video_wrapper {
  position: relative;
}
<div class="video_wrapper" onmouseover="pauseVid()" onmouseout="playVid()">
  //pause video on mouse hover, unpause when mouse leaves. wrapping the video in a div allows more css manipulation

  <video class="bannervid" id="myvideo" src="" muted autoplay></video> //make sure video autoplays, muted is optional

  <div class="video_wrapper_text">

    <p id="bannercredits"></p> //the video description will appear here

  </div>

</div>
AAColema
  • 1
  • 1