Pause previous audio when new audio is played - javascript

When user clicks on an item, I am dynamically adding a unique audio element like this and playing an audio.
let sound = document.createElement("audio");
sound.id = "audio" + e.target.id;
app.audioBeingPlayed = sound.id;
sound.controls = "controls";
sound.src = selectedVoice[0][1].sample;
sound.type = "audio/mpeg";
sound.play()
Before doing this I am checking if an audio is already being played and want to pause that audio.
I tried doing this
if(app.audioBeingPlayed) {
$('audio #'+ app.audioBeingPlayed).pause()
}
before the code above.
When one item is clicked, it plays an audio. But when another item is clicked it gives an error saying
$(...).pause is not a function
I just want to pause the audio being played and play the new audio as created in the code in the first block.
Any help will be appreciated.

you need to change your code from
if(app.audioBeingPlayed) {
$('audio #'+ app.audioBeingPlayed).pause() // $('audio #'+ app.audioBeingPlayed) is not the audio object.
}
to this
....
....
app.audioBeingPlayed = e.target.id; // set the correct target id.
if(app.audioBeingPlayed) {
$('#'+ app.audioBeingPlayed).pause() // $('#'+ app.audioBeingPlayed) is the audio object so play/pause will work.
//or directly use the id to pause.
$('#'+ e.target.id).pause()
}

Related

flickity.js play/pause video based on current cell

I am using Flickity to create a slider of images and videos. When changing slides, I want to play the video on the current slide (which has a class of .is-selected), and then pause again once I move to the next slide.
The code below manages to find any videos within the slider, but plays them on any slide change, rather than specifically for the slide they are within. Any help would be much appreciated.
// Init Flickity
var $carousel = $('.carousel');
$carousel.flickity();
// On slide change
$carousel.on('change.flickity', function() {
// Find videos
var currentSlide = $(this).find('.is-selected');
var video = $(this).find('video');
// Play videos
video[0].play();
});
What you want to do is pause all videos on every slide change and only play the one on the selected slide. I did something similar (without jQuery):
var carousel = document.querySelector(".carousel");
var flkty = new Flickity(carousel, {
// ..
});
flkty.on("change", function() {
console.log("Flickity active slide: " + flkty.selectedIndex);
flkty.cells.forEach(function(cell, i) {
if (cell.element == flkty.selectedElement) {
// play video if active slide contains one
// use <video playsinline ..> in your html to assure it works on ios devices
var video = cell.element.querySelector("video");
if (video) {
console.log("playing video " + i);
video.play();
}
return;
}
// pause all other videos
var video = cell.element.querySelector("video");
if (video) {
console.log("pausing video " + i);
video.pause();
}
});
});
As I stated in the comment, you might wanna use the "playsinline" attribute for your videos, otherwise you'll run into problems on iOS.
Also: using the "settle" event instead of "change" allows you to start playing once the active slide settled at its end position.

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.

Play different audio by clicking on class element

after many hours looking for a solution by myself, I'm asking for your help.
I'd like to play audio by clicking on an img and this is how I organised my code in HTML, audio will be different for each class : a_ru.mp3, b_ru.mp3 etc.
<span class="btn-audio-lexique">
<audio src="http://localhost/linguami-offline/fr/mp3/a_ru.mp3"></audio>
<img src="http://localhost/linguami-offline/img/circled-play.png">
</span>
<span class="btn-audio-lexique">
<audio src="http://localhost/linguami-offline/fr/mp3/b_ru.mp3"></audio>
<img src="http://localhost/linguami-offline/img/circled-play.png">
</span>
JS part which is unfortunately not workings looks like that
var classname = document.getElementsByClassName("btn-audio-lexique");
function playSound() {
var audio = classname.firstElementChild;
audio.play();
};
Array.from(classname).forEach(function(element) {
element.addEventListener('click', playSound);
});
I also tried with a for loop
for (var i = 0; i < classname.length; i++) {
classname[i].addEventListener('click', playSound);
}
console returns me a "audio is undefined error".
I would like to avoid creating a different id for all the audio in my page.
does anyone have an idea how should I organise my code for this works?
Thanks in advance !
You have few mistakes in your code:
I. Do not add event listener to each action element. It's bad for performance reasons. You should add event listener to some common parent element, which holds all the children buttons.
document.querySelector('.myAwesomeContainer').addEventListener('click', function(e) {
var target = e.target;
if (target && target.classList.contains('btn-audio-lexique')) {
var audio = target.firstElementChild;
// var audio = target.querySelector('audio');
if (audio) {
audio.play();
}
}
});
II. You don't necessarily need to mess up with audio elements. You can use AudioAPI and play sounds like:
var audio = new Audio('audio_file.mp3');
audio.play();
III. DO NOT use <span>, <div> or any HTML tag as clickable stuff except <button>, <a> Because you're destroing semantic markup and reducing accessability of you're application to the ground.
The actual reason of error in your current code, is hidden in that row:
var audio = classname.firstElementChild;
You're trying to get audio element not from the actual SPAN which user clicked, but from the array-like object of all your spans. Because classname is a LIST of all spans. What can you do in that situation? Just add event param to your playSound function. Because addEventListener will pass that param when event will be triggered:
var classname = document.getElementsByClassName("btn-audio-lexique");
function playSound(e) {
// Get actual clicked element
var target = e.target;
var audio = target.firstElementChild;
if (audio) {
audio.play();
}
};
Array.from(classname).forEach(function(element) {
element.addEventListener('click', playSound);
});

audio auto play next song when previous is finished

I want to create an audio background player where user can only click on image to play or stop the playback. I have trouble creating or rewirting existing codes to make a playlist for it, that automatically plays next song when previous is finished. I want to do it in vanilla js.
Here is what I have so far:
https://jsfiddle.net/rockarou/ad8Lkkrj/
var imageTracker = 'playImage';
swapImage = function() {
var image = document.getElementById('swapImage');
if (imageTracker == 'playImage') {
image.src = 'http://findicons.com/files/icons/129/soft_scraps/256/button_pause_01.png';
imageTracker = 'stopImage';
} else {
image.src = 'http://findicons.com/files/icons/129/soft_scraps/256/button_play_01.png';
imageTracker = 'playImage';
}
};
var musicTracker = 'noMusic';
audioStatus = function() {
var music = document.getElementById('natureSounds');
if (musicTracker == 'noMusic') {
music.play();
musicTracker = 'playMusic';
} else {
music.pause();
musicTracker = 'noMusic';
}
};
here is the trick to trigger next song:
music.addEventListener('ended',function(){
//play next song
});
How to play another song on same audio tag:
music.pause();
music.src = "new url";
music.load();
music.play();
Now here is a cool example of a playlist in html5, you can load each song at the time, case some clients (mobile) will not be happy when you consume the traffic, in next example all audios are loaded at same time to have a smooth transition from song to song,
loading the songs:
//playing flag
var musicTracker = 'noMusic';
//playlist audios
var audios = [];
$(".song").each(function(){
var load = new Audio($(this).attr("url"));
load.load();
load.addEventListener('ended',function(){
forward();
});
audios.push(load);
});
//active track
var activeTrack = 0;
Highlighting witch song is playing, with a bit of jquery, yeah, case yeah I'm lazy, lazy:
var showPlaying = function()
{
var src = audios[activeTrack].src;
$(".song").removeClass("playing");
$("div[url='" + src + "']").addClass("playing");
};
Fiddle here
Note: If the sound's doesn't play, manually check if audio url's are accessible
[Here a non vanilla solution.] My playlist consists of four songs, they are named 0.mp3, 1.mp3, 2.mp3 and 3.mp3.
<html>
<head><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script></head>
<body>
<audio id="player" autoplay controls><source src="0.mp3" type="audio/mp3"></audio>
</body>
<script>
var x = 0;
var music = document.getElementById("player");
$("#player").bind("ended", function(){
x=x+1;
music.src = x%4 + ".mp3";
music.load();
music.play();
});
</script>
</html>
The playlist is repeated indefinetely.
Vanilla Javascript variant:
const audioArray = document.getElementsByClassName('songs'); //Get a list of all songs
let i = 0; //Initiate current Index
const player = document.getElementById('player'); //get the player
player.src = audioArray[i].getAttribute('data-url'); //set first Song to play
player.addEventListener('ended',function(){ //when a song finished playing
i++; //increase index
if (i < audioArray.length) { //If current index is smaller than count of songs
player.src = audioArray[i].getAttribute('data-url'); //set next song
return; // stop further processing of this function for now
}
// current index is greater than count of songs
i = 0; // therefore we reset the current index to the first available song
player.src = audioArray[i].getAttribute('data-url'); // and set it to be played
});
In this example you don't set an initial src for the audioplayers source-tag but instead have a list of class 'song'-items with an data-url attribute containing the url/path to the tracks.
I added comments to learn what and why this code is doing what it does.
Of course it could be better but it's a quick throwup of code ;)

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