I'm attempting to create two audio players on the same page. I've seen a similar question, which suggested, "filtering tasks for each audio element and audio value," but my player is so different than the one in that question that I'm not sure how to apply it to mine.
Whenever I try to play the first player, the second starts instead and breaks if I start clicking around. The scripts for the two players are in different files, I've already changed the IDs so there aren't duplicates, and I also tried changing the variable and function names thinking that maybe they were having some impact. Nothing has worked.
I'm using the same code for each player, but with a different prefix on each ID:
/* global $ */
var audio;
//Hide Pause
$('#pause').hide();
initAudio($('#playlist').find('li:first-child'));
$('#playlist').on('click', function(event) {
initAudio($(event.target));
});
// Initiate play sequence
function initAudio(element){
var recording = element.attr('data-id');
var title = element.text();
var artist = element.attr('data-artist');
//Create audio object
audio = new Audio('public/audio_files/'+ recording);
//Insert audio info
$('.artist').text(artist);
$('.title').text(title);
$('#playlist li').removeClass('active');
element.addClass('active');
// Set timer to 0
$('#duration').html('0:00');
// Maintain volume on song change
audio.volume = $('#volume').val() / 100;
}
//Play button
$('#play').click(function() {
audio.play();
showPause();
showDuration();
});
//Pause button
$('#pause').click(function() {
audio.pause();
showPlay();
});
//Next button
$('#next').click(function() {
audio.pause();
var next = $('#playlist li.active').next();
if(next.length == 0){
next = $('#playlist li:first-child');
}
showPause();
initAudio(next);
audio.play();
showDuration();
});
//Prev button
$('#prev').click(function() {
audio.pause();
var prev = $('#playlist li.active').prev();
if(prev.length == 0){
prev = $('#playlist li:last-child');
}
showPause();
initAudio(prev);
audio.play();
showDuration();
});
//Playlist song click
$('#playlist li').click(function() {
audio.pause();
initAudio($(this));
showPause();
audio.play();
showDuration();
});
//Volume control
$('#volume').change(function() {
audio.volume = parseFloat(this.value / 100);
});
// Show play button, hide pause
function showPlay() {
$('#play').show();
$('#pause').hide();
}
// Show pause button, hide play
function showPause() {
$('#play').hide();
$('#pause').show();
}
// Automatically play next song
function autoPlayNext() {
if(audio.currentTime == audio.duration) {
var next = $('#playlist li.active').next();
if(next.length == 0){
next = $('#playlist li:first-child');
}
showPause();
initAudio(next);
audio.play();
showDuration();
}
}
// Time/Duration
function showDuration() {
$(audio).bind('timeupdate', function() {
//Get hours and minutes
var s = parseInt(audio.currentTime % 60, 10);
var m = parseInt(audio.currentTime / 60, 10) % 60;
if(s < 10) {
s = '0' + s;
}
$('#duration').html(m + ':'+ s);
var value = 0;
if(audio.currentTime > 0){
value = Math.floor((100 / audio.duration) * audio.currentTime);
}
$('#progress').css('width', value + '%');
autoPlayNext();
});
}
// Skip time via progress bar click
$('#progress-bar').bind('click', function (e) {
var $div = $(e.target);
var offset = $div.offset();
var x = e.clientX - offset.left;
audio.currentTime = ((x / 2.3)/(100 / audio.duration)); /* length of progress-bar is 230px hence (x/2.3) */
});
Any insight?
Related
When first loading the code, the pause button works fine, it pauses the audio and changes the HTML class of the button inside, the button continues to work after using the previous/next buttons to go to another song, however after the eventListener is triggered the pause button stops working, it doesn't pause the songs but the HTML inside still changes.
Edit: After a little bit of further debugging I found that the pause button is only able to pause the first time a track is loaded, once the audio.addEventListener('ended', nextTrack); is triggered it is unable to pause/play any audio.
let audio = new Audio;
let playing = false;
let playpause = document.getElementById('play-pause');
let root = document.documentElement;
let songname = document.getElementById('name');
let next = document.getElementById('next');
let prev = document.getElementById('previous');
let index = 0;
songlist = [
{"name":"Love Again"
,"artist":"The Kid LAROI",
"path":"resources/music/love-again.mp3",
},
{
"name":"Always Do",
"artist":"The Kid LAROI",
"path":"resources/music/always-do.mp3",
},
{
"name":"Bye Bye",
"artist":"Juice WRLD",
"path":"resources/music/bye-bye.mp3",
},
{
"name":"Understand",
"artist":"BoyWithUke",
"path":"resources/music/understand.mp3",
}
]
function progress_animation(){
var currentTime = audio.currentTime;
var duration = audio.duration;
$('#progbar').stop(true, true).animate({ 'width': (currentTime + .25) / duration * 100 + '%' }, 250, 'linear');
window.requestAnimationFrame(progress_animation);
};
function load(index){
songname.textContent = `${songlist[index].artist} - ${songlist[index].name}`;
audio.src = songlist[index].path;
audio.load()
};
audio.addEventListener('ended', nextTrack);
$('#play-pause').click(function (){
if (!playing) {
Play()
playing = true
} else {
Pause()
playing = false
}
});
function nextTrack(){
if (index < songlist.length - 1) {
index++;
} else {
index = 0;
}
load(index);
};
function prevTrack(){
if (index > 0) {
index--;
} else {
index = songlist.length - 1;
}
load(index);
};
function Play() {
audio.play();
playing = true;
playpause.innerHTML = '<i class="fa-solid fa-pause"></i>';
};
function Pause() {
audio.pause()
playing = false;
playpause.innerHTML = '<i class="fa-solid fa-play"></i>';
};
The pause button still changes its HTML class and sets the "playing" variable to false/true depending on the state of "playing" but doesn't actually pause the song
I want to use a custom audio player to play sound tracks hosted online.
For example I want to be able to feed the audio player a link like
example.com/path/to/track.mp3
and it should parse it and play it. I can play sound tracks hosted locally
Here is the code where I have the problem. I have an audio object that points to a local folder where the sound tracks are. I am not sure how to deal with this when it is not hosted locally.
When I replace the path with the URL the audio player just freezes.
$(function () {
var count = 0;
var audio;
//Hide Pause
$('#pause').hide();
initAudio($('#playlist li:first-child'));
function initAudio(element) {
var song = element.attr('song');
var cover = element.attr('cover');
var artist = element.attr('artist');
var title = element.text();
var temp = parseFloat($('#volume-slider').val() / 100);
//Create audio object
audio = new Audio('../media/books/' + song);
audio.volume = temp;
audio.addEventListener("loadedmetadata", function () {
minutes = parseInt(audio.duration / 60);
seconds = parseInt(audio.duration % 60);
if (seconds < 10) {
seconds = '0' + seconds;
};
if (minutes < 10) {
minutes = '0' + minutes;
};
$('#duration').html(minutes + ':' + seconds);
});
$("#auto-play").click(function () {
if (count === 1) {
$("#auto-play").css("background-color", "black");
count = 0;
} else {
$("#auto-play").css("background-color", "rgb(0,0,255)");
count = 1;
}
});
audio.addEventListener('ended', function () {
if (count > 0) {
var next = $('#playlist li.active').next();
if (next.length == 0) {
next = $('#playlist li:first-child');
}
initAudio($(next));
audio.play();
showCurrentTime();
}
});
//Inserts track info
$('.artist').text(artist);
$('.title').text(title);
$('#duration').text();
//Insert song cover. NOTE: the path below is relative to the
//html "img.cover" element not this js file.
$('img.cover').attr('src', '../media/books/covers/' + cover);
$('#playlist li').removeClass('active');
element.addClass('active');
};
});
You can avoid CORS errors with something like this.
For your local development it would be easy.
If you would like to go in production, it would be bit harder. The Server with the soundtracks has to accept your App.
My play/pause button works the first time I press pause and the first time I press play. But after that if I want to pause the slideshow again, it just plays the slideshow at a faster speed and I am no longer able to pause it.
I am thinking maybe it is to do with the fact I have two separate functions: one for the play/pause button icon toggle, and another for the actual play pause behaviour? (update: this has now been fixed, but still doesn't work)
Sorry, I am struggling with javascript, I have a lot to learn.
My script:
const playPause = document.querySelector('.pause');
let slideId;
// FUNCTION TO MOVE TO NEXT SLIDE
const moveToNextSlide = () => {
slides = getSlides();
if (index >= slides.length - 1) return;
index++;
slideGroup.style.transform = `translateX(${-slideWidth * index}px)`;
slideGroup.style.transition = '.8s';
}
// FUNCTION TO START SLIDESHOW
const startSlide = () => {
slideId = setInterval(() => {
moveToNextSlide();
}, interval);
playing = true;
};
// START AUTOMATIC SLIDESHOW UPON ENTERING THE PAGE
startSlide();
//PLAY PAUSE BUTTON - slideshow start/stop
playPause.addEventListener('click', () => {
if(!slideId) {
slideId = startSlide();
console.log('started');
} else {
clearInterval(slideId);
slideId = null;
console.log('stopped');
}
});
//PLAY PAUSE BUTTON - image change
function toggle(button) {
if (button.className != 'pause') {
button.src = 'img/pause.png';
button.className = 'pause';
}
else if (button.className == 'pause') {
button.src = 'img/play.png';
button.className = 'play';
}
return false;
}
HTML:
<input type='image' src='img/pause.png' class='pause' onclick='toggle(this);' />
This is what the console looks like when I try to pause the slideshow for a second time:
There are some details in your code that are missing and would be helpful to have, but I guess that you can get rid of the onclick handler and attach two event listeners:
let slideId;
// FUNCTION TO START SLIDESHOW
const startSlide = () => {
let interval = 2000; // using just as sample
playing = true;
return setInterval(() => {
console.log('moveToNextSlide();') // replaced just to test without missing code
}, interval);
};
//PLAY PAUSE BUTTON - slideshow start/stop
playPause.addEventListener('click', () => {
if(!slideId) {
slideId = startSlide();
console.log('started');
} else {
clearInterval(slideId);
slideId = null;
console.log('stopped');
}
});
//PLAY PAUSE BUTTON - image change
playPause.addEventListener('click', function toggle() { // the arrow function would not work in this case
var button = this;
if (button.className != 'pause') {
button.src = 'img/pause.png';
button.className = 'pause';
}
else if (button.className == 'pause') {
button.src = 'img/play.png';
button.className = 'play';
}
return false;
});
When I press the button, I want to play a song, when I press the second song a second time, and when the third one, the cycle repeats again, but the first song is shorter than the second one, and if you click many times, the long song plays simultaneously with its other copy. Is it possible to stop the previous music and move on to another?
Html:
< a id="Play">test< / a>
Script:
window.onload=function(){
let number = 0;
var t;
document.getElementById('Play').addEventListener('click',function(){
let audio = new Audio();
if ( number == 0 ) {
audio.src = '/assets/sound/test.mp3';
number = 1;
}
else
if ( number == 1 ) {
audio.src = '/assets/sound/curious&loony.mp3';
number = 0;
}
audio.autoplay = true;
});
}
sound.pause();
sound.currentTime = 0;
Use this for pause audio
Found a way.
How to:
<script>
var i = 1, player = new Audio();
player.src = "/assets/sound/sound1.mp3";
document.querySelector('#play-button').addEventListener('click', function(e) {
e.preventDefault();
if (i === 1) {
player.src = "/assets/sound/sound1.mp3";
i = 0;
} else if (i === 0) {
player.src = "/assets/sound/sound2.mp3";
i = 1;
}
player.play();
});
</script>
Play me harder
I can't seem to find useful code to make my playlist autoplay the first song when site loads and then when the song finishes, autoplay the next song.
I got this code following a tutorial, but they did not include these functions. I have looks all over and the code I have seen has not helped me with my issue.
var audio;
//Hide pause buton
$('#pause').hide();
//Initialize Audio
initAudio($('#playlist li:first-child'));
//Initializer Function
function initAudio(element){
var song = element.attr('song')
var title = element.text();
//Create audio object
audio = new Audio('media/' + song);
if(!audio.currentTime){
$('#duration').html('0.00');
}
$('#audio-player .title').text(title);
$('#playlist li') .removeClass('active');
element.addClass('active');
}
//PLay Button
$('#play') .click(function(){
audio.play();
$('#play') .hide();
$('#pause') .show();
$('#duration') .fadeIn(400);
showDuration();
});
//Pause Button
$('#pause') .click(function(){
audio.pause();
$('#pause') .hide();
$('#play') .show();
});
//Stop Button
$('#stop') .click(function(){
audio.pause();
audio.currentTime = 0;
$('#pause') .hide();
$('#play') .show();
$('#duration') .fadeOut(400);
});
//Next Button
$('#next').click(function(){
audio.pause();
var next = $('#playlist li.active').next();
if (next.length == 0) {
next = $('#playlist li:first-child');
}
initAudio(next);
audio.play();
showDuration();
});
//Prev Button
$('#prev') .click(function(){
audio.pause();
var prev = $('#playlist li.active').prev();
if (next.length == 0){
prev = $('playlist li:last-child');
}
initAudio (prev);
audio.play();
showDuration();
});
//Time Duration
function showDuration(){
$(audio).bind('timeupdate', function(){
//Get Hours & Minutes
var s = parseInt (audio.currentTime % 60);
var m = parseInt ((audio.currentTime)/ 60) % 60;
//Add 0 if less than 10
if(s < 10){
s = '0' + s;
}
$('#duration').html (m + '.' + s);
var value = 0;
if(audio.currentTime > 0) {
value = Math.floor((100 / audio.duration) * audio.currentTime);
}
$('#progress').css('width',value+'%');
});
}
//Playlist Song Click
$('#playlist li').click(function () {
audio.pause();
initAudio($(this));
$('#play').hide();
$('#pause').show();
$('#duration').fadeIn(400);
audio.play();
showDuration();
});
//Volume Control
$('#volume').change(function(){
audio.volume = parseFloat(this.value / 10);
});
Start playing the audio sounds pretty straightforward : you can trigger a click on the play button using
$('#play').trigger('click');
Playing the next song when one is over can be done in showDuration() :
if( audio.currentTime >= audio.duration) $('#next').trigger('click');