Loading Audio Element After Dynamically Changing the Source - javascript

I have a couple of audio elements that appear in the body of my page. They look like this.
<audio id="sound1" preload="auto">
<source id="sound1source" src="../../Content/Audio/gau.mp3">
//add .ogg here later
</audio>
<audio id="sound2" preload="auto">
<source id="sound2source" src="../../Content/Audio/mah.mp3">
//add .ogg here later
</audio>
The audio plays when a user mouses over certain divs. Here's the code that triggers it.
var audio = $("#sound1")[0];
$("#ChoiceA").mouseenter(function () {
audio.play();
});
var audio2 = $("#sound2")[0];
$("#ChoiceB").mouseenter(function () {
audio2.play();
});
Everything above works fine. My problem occurs when I attempt to dynamically change the source element after making an ajax call. Here's my javascript that accomplishes that.
var src1 = "../../Content/Audio/" + data.nouns[0].Audio1 + ".mp3";
var src2 = "../../Content/Audio/" + data.nouns[1].Audio1 + ".mp3";
$("#sound1source").attr("src", src1);
$("#sound2source").attr("src", src2);
When I inspect the page after triggering the ajax call to change the source path for the audio elements, I see that the source is updated. No problem there. The problem is that the audio that the new paths point to does not play.
After hunting around I found this note on w3.org "Dynamically modifying a source element and its attribute when the element is already inserted in a video or audio element will have no effect. To change what is playing, either just use the src attribute on the media element directly, or call the load() method on the media element after manipulating the source elements."
The comment on w3.org seems to be related so I tried calling $('#sound1').load() and also $('#sound1source').load(). Neither solved my problem.
Can someone tell me what I've done wrong? If I need to cause the audio element to load again after dynamically changing the src, how do I do that?
-------------UPDATE-------------
Based on Swatkins suggestion I created the following function to create the audio tag when the user mouses over the target div. Unfortunately this has not solved the problem either.
function attachAudio1(src) {
$('#audio1').remove();
var audio = $('<audio>');
audio.attr("src", src);
audio.attr("id", "audio1");
audio.appendTo('body');
attachPlayAction();
};
function attachPlayAction() {
var audio = $("#audio1")[0];
$('#ChoiceA').live('mouseenter', function () {
audio.play();
});
};

You should call load like this:
var audio = $("#sound1")[0];
$("#ChoiceA").mouseenter(function () {
audio.load();
audio.play();
});
var audio2 = $("#sound2")[0];
$("#ChoiceB").mouseenter(function () {
audio.load();
audio2.play();
});
Have not tested doing it like above, but have testet this previously with a seperate function looking something like this:
<audio id="sound1" preload="auto" src="../../Content/Audio/gau.mp3">
function changeAudio(){
audio = document.getElementById("sound1");
audio.src = "../../Content/Audio/" + data.nouns[0].Audio1 + ".mp3";
audio.load();
audio.play();
}
$("#ChoiceA").mouseenter(function () {
changeAudio();
});
and that worked fine for me?
EDIT: Adding a fiddle, maybe that will help you figure this out?
http://jsfiddle.net/Z3VrV/

This is tricky. I would try replacing the whole <audio> element instead of just changing its source. This way, the new audio element hasn't been added to the page, so it will be forced to load the file.

load() followed by play() right away leads to trouble. Trying listening for the canplay event before attempting to play the audio as suggested in https://stackoverflow.com/a/8705478/1374208

Related

Stop embedded Javascript song from autplaying on Chrome?

I have the following line:
<embed src="/sounds/move.wav" autostart="0" width=0 height=0 id="move_sound" enablejavascript=true>
Which autoplays the song on Chrome regardless of any parameters I play with (autoplay, etc.).
Anyone know how to stop it from playing?
EDIT: Not the same as the above, I'm dealing only with embed tags and not video tags.
Try using an audio tag:
<audio src="/sounds/move.wav">
Your browser does not support the <code>audio</code> element.
</audio>
This tag will not autoplay the sound.
You could set src to empty string
var embed = document.getElementById("move_sound");
var audio = embed.src; // save `src`
embed.src = "";
Not really sure but maybe you could stop the audio from playing. with a function you call everytime you switch the src?
http://www.w3schools.com/tags/av_prop_currenttime.asp
Like this?
function start(){
var embed = document.getElementById("move_sound");
//load the video etc.
embed.currentTime = 0;
embed.pause();
}
function playPause() {
if (embed.paused)
embed.play();
else
embed.pause();
}

Please help me to use play/stop code so my code should stop and reset not pause [duplicate]

I am playing a small audio clip on click of each link in my navigation
HTML Code:
<audio tabindex="0" id="beep-one" controls preload="auto" >
<source src="audio/Output 1-2.mp3">
<source src="audio/Output 1-2.ogg">
</audio>
JS code:
$('#links a').click(function(e) {
e.preventDefault();
var beepOne = $("#beep-one")[0];
beepOne.play();
});
It's working fine so far.
Issue is when a sound clip is already running and i click on any link nothing happens.
I tried to stop the already playing sound on click of link, but there is no direct event for that in HTML5's Audio API
I tried following code but it's not working
$.each($('audio'), function () {
$(this).stop();
});
Any suggestions please?
Instead of stop() you could try with:
sound.pause();
sound.currentTime = 0;
This should have the desired effect.
first you have to set an id for your audio element
in your js :
var ply = document.getElementById('player');
var oldSrc = ply.src;// just to remember the old source
ply.src = "";// to stop the player you have to replace the source with nothing
I was having same issue. A stop should stop the stream and onplay go to live if it is a radio. All solutions I saw had a disadvantage:
player.currentTime = 0 keeps downloading the stream.
player.src = '' raise error event
My solution:
var player = document.getElementById('radio');
player.pause();
player.src = player.src;
And the HTML
<audio src="http://radio-stream" id="radio" class="hidden" preload="none"></audio>
Here is my way of doing stop() method:
Somewhere in code:
audioCh1: document.createElement("audio");
and then in stop():
this.audioCh1.pause()
this.audioCh1.src = 'data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAVFYAAFRWAAABAAgAZGF0YQAAAAA=';
In this way we don`t produce additional request, the old one is cancelled and our audio element is in clean state (tested in Chrome and FF) :>
This method works:
audio.pause();
audio.currentTime = 0;
But if you don't want to have to write these two lines of code every time you stop an audio you could do one of two things. The second I think is the more appropriate one and I'm not sure why the "gods of javascript standards" have not made this standard.
First method: create a function and pass the audio
function stopAudio(audio) {
audio.pause();
audio.currentTime = 0;
}
//then using it:
stopAudio(audio);
Second method (favoured): extend the Audio class:
Audio.prototype.stop = function() {
this.pause();
this.currentTime = 0;
};
I have this in a javascript file I called "AudioPlus.js" which I include in my html before any script that will be dealing with audio.
Then you can call the stop function on audio objects:
audio.stop();
FINALLY CHROME ISSUE WITH "canplaythrough":
I have not tested this in all browsers but this is a problem I came across in Chrome. If you try to set currentTime on an audio that has a "canplaythrough" event listener attached to it then you will trigger that event again which can lead to undesirable results.
So the solution, similar to all cases when you have attached an event listener that you really want to make sure it is not triggered again, is to remove the event listener after the first call. Something like this:
//note using jquery to attach the event. You can use plain javascript as well of course.
$(audio).on("canplaythrough", function() {
$(this).off("canplaythrough");
// rest of the code ...
});
BONUS:
Note that you can add even more custom methods to the Audio class (or any native javascript class for that matter).
For example if you wanted a "restart" method that restarted the audio it could look something like:
Audio.prototype.restart= function() {
this.pause();
this.currentTime = 0;
this.play();
};
It doesn't work sometimes in chrome,
sound.pause();
sound.currentTime = 0;
just change like that,
sound.currentTime = 0;
sound.pause();
From my own javascript function to toggle Play/Pause - since I'm handling a radio stream, I wanted it to clear the buffer so that the listener does not end up coming out of sync with the radio station.
function playStream() {
var player = document.getElementById('player');
(player.paused == true) ? toggle(0) : toggle(1);
}
function toggle(state) {
var player = document.getElementById('player');
var link = document.getElementById('radio-link');
var src = "http://192.81.248.91:8159/;";
switch(state) {
case 0:
player.src = src;
player.load();
player.play();
link.innerHTML = 'Pause';
player_state = 1;
break;
case 1:
player.pause();
player.currentTime = 0;
player.src = '';
link.innerHTML = 'Play';
player_state = 0;
break;
}
}
Turns out, just clearing the currentTime doesn't cut it under Chrome, needed to clear the source too and load it back in. Hope this helps.
As a side note and because I was recently using the stop method provided in the accepted answer, according to this link:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events
by setting currentTime manually one may fire the 'canplaythrough' event on the audio element. In the link it mentions Firefox, but I encountered this event firing after setting currentTime manually on Chrome. So if you have behavior attached to this event you might end up in an audio loop.
shamangeorge wrote:
by setting currentTime manually one may fire the 'canplaythrough' event on the audio element.
This is indeed what will happen, and pausing will also trigger the pause event, both of which make this technique unsuitable for use as a "stop" method. Moreover, setting the src as suggested by zaki will make the player try to load the current page's URL as a media file (and fail) if autoplay is enabled - setting src to null is not allowed; it will always be treated as a URL. Short of destroying the player object there seems to be no good way of providing a "stop" method, so I would suggest just dropping the dedicated stop button and providing pause and skip back buttons instead - a stop button wouldn't really add any functionality.
This approach is "brute force", but it works assuming using jQuery is "allowed". Surround your "player" <audio></audio> tags with a div (here with an id of "plHolder").
<div id="plHolder">
<audio controls id="player">
...
</audio>
<div>
Then this javascript should work:
function stopAudio() {
var savePlayer = $('#plHolder').html(); // Save player code
$('#player').remove(); // Remove player from DOM
$('#FlHolder').html(savePlayer); // Restore it
}
I was looking for something similar due to making an application that could be used to layer sounds with each other for focus. What I ended up doing was - when selecting a sound, create the audio element with Javascript:
const audio = document.createElement('audio') as HTMLAudioElement;
audio.src = getSoundURL(clickedTrackId);
audio.id = `${clickedTrackId}-audio`;
console.log(audio.id);
audio.volume = 20/100;
audio.load();
audio.play();
Then, append child to document to actually surface the audio element
document.body.appendChild(audio);
Finally, when unselecting audio, you can stop and remove the audio element altogether - this will also stop streaming.
const audio = document.getElementById(`${clickedTrackId}-audio`) as HTMLAudioElement;
audio.pause();
audio.remove();
If you have several audio players on your site and you like to pause all of them:
$('audio').each( function() {
$(this)[0].pause();
});
I believe it would be good to check if the audio is playing state and reset the currentTime property.
if (sound.currentTime !== 0 && (sound.currentTime > 0 && sound.currentTime < sound.duration) {
sound.currentTime = 0;
}
sound.play();
for me that code working fine. (IE10+)
var Wmp = document.getElementById("MediaPlayer");
Wmp.controls.stop();
<object classid="clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6"
standby="Loading áudio..." style="width: 100%; height: 170px" id="MediaPlayer">...
Hope this help.
What I like to do is completely remove the control using Angular2 then it's reloaded when the next song has an audio path:
<audio id="audioplayer" *ngIf="song?.audio_path">
Then when I want to unload it in code I do this:
this.song = Object.assign({},this.song,{audio_path: null});
When the next song is assigned, the control gets completely recreated from scratch:
this.song = this.songOnDeck;
The simple way to get around this error is to catch the error.
audioElement.play() returns a promise, so the following code with a .catch() should suffice manage this issue:
function playSound(sound) {
sfx.pause();
sfx.currentTime = 0;
sfx.src = sound;
sfx.play().catch(e => e);
}
Note: You may want to replace the arrow function with an anonymous function for backward compatibility.
In IE 11 I used combined variant:
player.currentTime = 0;
player.pause();
player.currentTime = 0;
Only 2 times repeat prevents IE from continuing loading media stream after pause() and flooding a disk by that.
What's wrong with simply this?
audio.load()
As stated by the spec and on MDN, respectively:
Playback of any previously playing media resource for this element stops.
Calling load() aborts all ongoing operations involving this media element

redirecting to a new page when an html 5 audio file has finished playing

I am playing an audiobook chapter with the text and want it to automatically redirect to a new page with the next chapter text and audio when the html5 audio file finishes.
I am not a programmer so I could use some help.
I know I need to use the addEventListener with the ended function similiar to what is below but I do not know how to modify this to call a new page instead of a new audio file.
<audio id="audio" autoplay controls src="song1.mp3" type="audio/mpeg"></audio>
<script type="text/javascript">
document.getElementById('audio').addEventListener("ended",function() {
this.src = "song2.mp3?nocache="+new Date().getTime();
this.play();
});
</script>
Use the ended event and redirect:
http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#event-media-ended
function redirectHandler() {
window.location = 'http://example.com';
}
audio.addEventListener('ended', redirectHandler, false);
Demo: http://jsfiddle.net/tqam3zyf/2/
When you use
this.src = "song2.mp3?nocache="+new Date().getTime();
this.play();
you set the current source of the audio element.
If you want to load a new page instead of your current page you can use :
window.location = "your_url";

Using Javascript to play an audioelement (html5)

I'm trying to figure out how to trigger playing an audio from javascript. I got some html which looks like:
<div class='audio' >foo
<audio preload='auto' controls src='test.wav'>
<b>Your browser does not support the audio tag.</b>
</audio>
</div>
And I'm trying to trigger it with:
$(document).ready(function () {
$('.audio').each(function(){
var audio = $(this).find('audio').get();
$(this).click(function(){
audio.volume = 100;
alert('1 '+audio);
audio.play();
alert('2');
});
});
});
alert('1 '+audio); works as expected and reports audio as HTMLAudioElement. However alert('2'); is not called because I get the error 'audio.play' is not a function. What can I do to solve this problem?
Your code looks perfect. What is the error you are getting is it "alert.play" is not a function or "audio.play" is not a function.
I think
var audio = $(this).find('audio').get();
returns an array try this
var audio = $(this).find('audio').get(0);
Controlling audio without jQuery using just JavaScript is even easier if you give the audio tag an ID:
<audio id="myAudioTagID" type="audio/mpeg" src="sound.mp3"></audio>
then you can simply get the element and apply .pause(), .start(), stop() :
var audio = document.getElementById("myAudioTagID");
audio.play();
audio.pause();
audio.stop();

Jquery return original event on video

I have multiple video plays on a single page which I need to listen for onplay and onpause triggers, and execute custom functions which take the IDs from each of the videos tags. I need to be able to get the video id that was activated. Ive tried a few different ways, with the simple vid.onplay event works well when I know what ID is being called into. I've tried the $("video").onplay but doesn't seem to be working.
jQuery( document ).ready(function($) {
$("video").onplay = function() {
alert("The video has been paused");
};
var vid = document.getElementbyid("myVideo");
vid.onplay = function() {
alert("The video has been played");
};
});
<video class="mdia_video_player" id=myVideo poster="https://tcokchallenge.com/launch2/wp-content/uploads/2020/04/Carter.jpg?336660464" id="v0" onclick="doplayvideo(" 0")"="" controls="">
<source src="https://tcokchallenge.com/launch2/wp-content/uploads/2020/04/Carter.mp4?1222152426" type="video/mp4">
</video>```
In your first demo, it should be $("#video") to call by ID. It also says .onplay and then says that is was paused so you might want to fix that.
Ended up doing a much simpler answer, videos are within a php loop. So, I placed this within the tag
onpause="dopausevideo(<?=$vid ?>)"
onplay="doplayvideo(<?=$vid ?>)"

Categories