Reputation: 15
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
Reputation: 277
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
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
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
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