Toggle multiple play/pause buttons using Howler.js - javascript

I searched SE for a bit and I saw similar questions but nothing quite like what I needed help with.
I'm using Howler.js to stream audio on my site. The issue I ran into is that there are many songs on each page so when one song is playing, clicking the next song does not toggle the buttons...the music does start playing but the first song doesn't. I am aware that this is because I am using an ID such as Id="bodyPlayBtn" but I need it to toggle the buttons from the js currently. I thought of using this.toggleClass(ion-ios-play ion-ios-pause) in the function clickSongPlay() but that didn't quite seem to work. What is the best way to approach this?
Here is the relevant code:
HTML:
<div><i class="icon ion-ios-play" id="bodyPlayBtn" onclick="clickSongPlay('#song.Artist','#song.Title','#song.URL','#song.Album.ImageURL');"></i><i class="icon ion-ios-pause" id="bodyPauseBtn"></i></div>
If you are visual like me, this is what that div controls (blue arrow)
player.js
// Show the pause button.
if (sound.state() === 'loaded') {
bodyPlayBtn.style.display = 'none';
bodyPauseBtn.style.display = 'inline-block';
} else {
loading.style.display = 'block';
bodyPlayBtn.style.display = 'none';
bodyPauseBtn.style.display = 'none';
}
// Show the play button.
bodyPlayBtn.style.display = 'inline-block';
bodyPauseBtn.style.display = 'none';
// Bind our player controls.
bodyPlayBtn.addEventListener('click', function () {
player.play();
});
function clickSongPlay(artist, title, url, imageURL) {
//debugger;
player.playlist.push(
{
title: title,
artist: artist,
file: url,
imageURL: imageURL,
howl: null
}
);
player.skipTo(player.playlist.length - 1);
player.play();
}
bodyPauseBtn.addEventListener('click', function () {
player.pause();
});
This code works really well with just one play button, but when two enter the picture is when things get messy!

Related

JavaScript Audio Object how to play next track on clicking next

I am making a music web app where users can load song or load array of music. I tried to make a button where user can skip the track and play the next track from the array. I tried in my own method and it actually working quiet well.
heres my music object:
getNextSong()
{
if(this.songArray && this.i > -1 && this.i<this.songArray.length){
const nextSong = this.songArray[this.i+1]
//this.playSong(nextSong)
return nextSong
}else{
return null
}
}
getPreviousSong()
{
if(this.songArray && this.i > 0 && this.i<this.songArray.length){
const nextSong = this.songArray[this.i-1]
console.log(nextSong)
//this.playSong(nextSong)
return nextSong
}else{
return null
}
}
loadSongs(song, playlist_song = "song")
{
if(playlist_song === "playlist"){
this.songArray = song
song.forEach(song=>{
this.audio.src = song.src.aduioURL
this.audio.load()
})
}else if(playlist_song === "song"){
this.songArray.push(song)
}
}
playSong(song)
{
this.song = song
this.audio.src = song.src.aduioURL
this.play(song)
}
and in audio player:
function next(){
const nextSong = song.getNextSong()
if(nextSong)
{
song.playSong(nextSong)
}
}
function previous(){
const previousSong = song.getPreviousSong()
if(previousSong)
{
song.playSong(previousSong)
}
}
It works perfectly but the problem of it is, i cannot change/skip the track from browser control. for eg:- in soundcloud and other apps If i am using it in mobile then i can skip the track from my lockscreen, There will be a small browser audio control and we can skip it from there. But from my app i cant do that for some reason.
heres the picture of what i am talking about:
soundcloud:
myapp:
as you can see here I cant control it from here. Where as in sound cloud i can change the tracks. And in soundlocud, it also displays title of the song where as in my it doesnt, it just displays title of my page.
I am using react for the development
Please checkout MediaSession documentation
Media Session Doc

How to switch between 2 audio tracks but 1 video file?

I am a total JavaScript amateur. I want to create a section where people can switch between 2 audios with a video running along with it. I want to show a before and after version of the audio.
Basically, the video should run with the "before" version of the audio initially. Then there should be a button to switch the audio to the "after" version, and go back and forth.
I tried the "audioTracks" method, but the browser compatibility is not good with it. What is the best possible way to achieve it?
Thanks in advance.
You just use two HTML Audio elements and then sync their times:
var audio1 = new Audio()
var audio2 = new Audio()
audio1.src = 'pathToSource',
audio2.src = 'pathToSource2',
var video = document.getElementByID('myvideo');
video.muted = true; //mute video cuz we have audio already
function switchAudio(one, two, vid) {
if(one.paused) {
two.pause();
one.currentTime = vid.currentTime;
one.play
} else {
one.pause();
two.currentTime = vid.currentTime;
two.play()
}
}
That did it :) I made some changes though. The audio seems to be working great. I could play and switch it. But the video was not starting up with the button. So I changed the code to this:
function switchAudio(one, two, vid) {
if (one.paused) {
two.pause();
vid.play();
one.play();
one.currentTime = vid.currentTime;
} else {
vid.pause();
one.pause();
vid.play();
two.play();
two.currentTime = vid.currentTime;
}
}
After this the video is playing along with the audio. But when I switch the audio, their timing does not match. The audio seems to be playing just a little bit late.

Button to mute/unmute video bg on divi theme

I'm making a website for a client using the divi theme. The site has a background video with sound. The customer wants in the video a button to turn the sound on and off.
With the following code I was able to mute but I can not make a button to turn on and off.
Can someone help me?
jQuery (document) .ready (function () {
jQuery (". et_pb_section_video_bg video"). prop ('muted', true);
});
Try with volume level!
Edit
And here are the functions for some volume down/up buttons.
$(document).ready(function(){
// Video element
var myVideo = $(".et_pb_section_video_bg video")[0];
// On load state (muted)
myVideo.volume = 0;
$("#sound_up").on("click",function(){
var actual_volume = myVideo.volume;
if(actual_volume<1){
myVideo.volume += 0.2;
}
});
$("#sound_down").on("click",function(){
var actual_volume = myVideo.volume;
if(actual_volume>0){
myVideo.volume -= 0.2;
}
});
});
Assuming the et_pb_section_video_bg video class is on the video element...

Javascript / jQuery check which button is currently playing a song

I'm currently trying to make a song selection list where a user can hit a button to preview a song. I'm struggling with the logic behind setting a buttons innerHTML to read 'Stop preview' when that buttons song is playing and also have the buttons HTML change when a user clicks another button.
Currently my script looks something like:
var playedBy;
var song;
var playing = false;
var audioPlayer = document.getElementById("demo");
function setSong(value, idForPlayed) {
song = value;
audioPlayer.src = song;
audioPlayer.play();
playedBy = idForPlayed;
var currentIdPlayingValue = document.getElementById(idForPlayed).value;
console.log(currentIdPlayingValue);
}
function valueGetter(button) {
song = button.value;
button.className += " playing";
var idForPlayed = button.id;
var value = song;
setSong(value, idForPlayed);
}
function doEnd() {
playing = false;
console.log('we have an end');
document.getElementById('demo').pause();
document.getElementById('demo').currentTime = 0;
}
With the value of the buttons being the URL i'm passing the audio object.
Any help is appreciated here, very unsure on the approach i should take.
Thanks all!
Simple example in code pen : http://codepen.io/anon/pen/XXwXYV
You could toggle the innerHtml and all of the other buttons html on click.
Something like
$('.btn').on('click', function(){
//Add or remove a class for the clicked button to determine if it's playing.
$(this).toggleClass('playing');
if($(this).hasClass('playing')){
//Set all buttons back to play
//And probably call some sort of Stop Playing function
$('.btn').html('Play').removeClass('playing');
$(this).html('Stop Playing').addClass('playing');
}else{
$('.btn').html('Play').removeClass('playing');
}
});

Dynamic sounds not playing after two plays

I have a little html5 application where you can play a sound by clicking a button.
I have a function that adds an <audio> tag to a <div> with an id "playing." The sound removes itself when it is done.
function sound(track){
$("#playing").append("<audio src=\"" + track + "\" autoplay onended=\"$(this).remove()\"></audio>");
}
For the button I have:
<button onclick="sound('sounds/tada.mp3')">Tada</button>
When I click the button, an <audio> briefly appears in the element inspector and disappears when it is finished, just the way I want it, but after triggering it two times, it just stops working in Chrome, at least. There are no errors in the console either.
What is going on?
Get rid of the onclick/onend in your HTML and reference the button in your js:
HTML
<button id='tada' sound_url='sounds/tada.mp3'>Tada</button>
And the JS
var sound = function(track){
$("#playing").append("<audio id='played_audio' src='\" + track + \"' autoplay='true'></audio>");
}
$('#tada').on('click', function () {
var sound_url = $(this).attr('sound_url');
sound(sound_url);
});
$('#playing').on('end', 'played_audio', function() {
$(this).remove();
});
Okay, lets see..
var audioURL = "http://soundbible.com/mp3/Canadian Geese-SoundBible.com-56609871.mp3";
var audioEl = null;
function removeAudio() {
if (audioEl && audioEl.parentNode)
audioEl.parentNode.removeChild(audioEl);
}
function sound() {
removeAudio();
audioEl = document.createElement("audio");
audioEl.src = audioURL;
audioEl.controls = true;
audioEl.addEventListener("ended", removeAudio); // <-- Note it's ended, not end!
document.getElementById("playing").appendChild(audioEl);
audioEl.play();
}
document.getElementById("tada").addEventListener("click", sound);
<div id="playing">
</div>
<button id="tada">Tada</button>
I'm not seeing any problems with this script.
Decide audioURL, set audioEl to null as it will be used later
When the element with ID "tada" is clicked, run our sound function.
Remove the audio.
Create the audio element.
When the audio is finished, remove the audio.
Append the audio to the element with ID "playing".
Play the audio.
One thing to note is that I use the ended event, not the end event.
(This answer is here because Andrew really wants us to answer it.)

Categories