Tom
Tom

Reputation: 15

Random, shuffle JavaScript playlist

I know this has been asked before, but I am new to JavaScript and after having read other answers I can't understand specifically why my method isn't working. The first track that plays is random, but then when the song ends, the same track repeats over and over again instead of choosing a different random track. If audio.play chooses a random track the first time, why doesn't it choose a random track again when the song ends, but instead loops the same track? Help appreciated:

var audio_files = [
"TRACKS/1.mp3",
"TRACKS/2.mp3",
"TRACKS/3.mp3"
]

var random_file = audio_files[Math.floor(Math.random() * audio_files.length)];

var audio = new Audio(random_file);

audio.play();

audio.addEventListener('ended', function(){
audio.play();
}

Upvotes: 0

Views: 4213

Answers (4)

David Mukopa
David Mukopa

Reputation: 277

Open demo in codepen

To play the files in the playlist infinitely with the help of the cool underscore module, you can do the following

If you are a nodejs developer you can install the module using the following command

npm i underscore

To use it in nodejs you can do the following

const _ = require("underscore")

To use it on the frontend you can put the following script just before the closing tag of the html body tag

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.2/underscore-min.js"></script>

Now lets get started with the logic

Here is my html file

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>SHUFFLED PLAYLIST</title>
  </head>
  <body>
     <button id="playsong">play playlist</button>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.2/underscore-min.js"></script>
  </body>
  </html>

Here is my javascript file

  let played_files = [];
  let playsong = document.querySelector("#playsong");

  let audio = new Audio();

  let audio_files = [
    "songs/song_num1.mp3",
    "songs/song_num2.mp3",
    "songs/song_num3.m4a",
    "songs/song_num4.mp3",
  ];

  function random_file() {
    let file = _.sample(audio_files);
    let allSongsPlayed = _.size(played_files) === _.size(audio_files);
    if (_.contains(played_files, file) || allSongsPlayed) {
      if (allSongsPlayed) {
        played_files = [];
      }
      return random_file();
    } else {
      played_files.push(file);
      return file;
    }
  }

  function playSong() {
    let file = random_file();
    audio.src = file;
    audio.play();
  }

  playsong.addEventListener("click", () => {
    playSong();
  });

  audio.addEventListener("ended", playSong);

Upvotes: 1

oklas
oklas

Reputation: 8220

Your code need to be like this:

var audio_files = [
"TRACKS/1.mp3",
"TRACKS/2.mp3",
"TRACKS/3.mp3"
]

function random_file(){
  return audio_files[Math.floor(Math.random() * audio_files.length)];
}

var audio = new Audio( random_file() );

audio.play();

audio.addEventListener('ended', function(){
  audio.play( random_file() );
}

Your listner may be like this if player have another way to specify file for existing payer

audio.addEventListener('ended', function(){
  audio.src = random_file();
  audio.play();
}

or if your player have no such api method the only way is

function listner() {
  audio = new Audio( random_file() );
  audio.play();
  audio.addEventListener('ended', listner)
}

audio.addEventListener('ended', listner)

Upvotes: 1

AxelH
AxelH

Reputation: 14572

It would be easier to shuffle the array and simply iterate on it to get each file. With this solution, you will not get the same file twice because of the random solution.

Once you get to the end, do the same thing, shuffle the array and iterate again. Like this, the list will change giving the impression to selecting a different file in a random manner (but truly simply iterating).

Here is a pseudo code to it

function readFiles(){        
    array = shuffle(array);
    for(var i = 0; i < array.length; ++i){
         play(array[i]);
    }
    readFiles(); //to read undefinitly
}

Here and here, you will find a great threads to shuffle the array. I will not do it again, just follow the answer there.

In your case, you don't want a loop but you will use a counter the get the next file and shuffle the array again once you get to the end

function getNextFile(){
    if(currentFile >= array.length){ //reach the end
        shuffle(array);
        currentFile = 0;
    } 
    return array[currentFile+];
}

Upvotes: 3

Med Lazhari
Med Lazhari

Reputation: 618

Just install the famous underscoreJS module on client or server side with Node.js and invoke the sample function;

var random_file = _.sample(audio_files);

Upvotes: 0

Related Questions