So I have this audio tag:
<audio src=".....mp3" autoplay id="aud"></audio>
And 20 seconds later I fire this code:
var obj=$('#aud')
obj[0].volume=0;
obj[0].pause();
obj.prop('volume',0);
obj.trigger('pause');
obj.attr('src','');
obj.remove();
console.log('REMOVED!!');
But after all of this, the audio is still playing??
The audio tag has been successfully removed by obj.remove(), but the audio goes on.
The console.log() logs correctly. I get no errors. But despite using several methods to mute, pause and remove the audio tag, the audio goes on.
Can anyone explain why?
I need to purge this audio with salt and flame. Any help will be most appreciated, this is slowly sending me insane...
So I fiddled with this when writing this as an answer and I conclude the following:
Manually creating the audio tag with autoplay property causes it to play even before being added to the DOM tree 2 times(on older jquery implementations). Even after adding that element to the DOM tree, it will be usually impossible to stop both audio streams - prolly one of the streams gets disconnected from the element when second stream is played. Did not dig into that too deeply. I reproduced the issue here:
http://jsfiddle.net/2gaBs/3/
When you click Create w/o autoplay button you can pause it properly, but when you click Create autoplay it will start immedietally (even before adding to the DOM tree) 2 times! You probably didn't notice the 2nd playback(neither did I) because when mp3 is on the same machine 2 audio streams are almost perfectly in sync. Pressing Try stop will stop one of the audio streams (you need to wait 5 seconds, note the setTimeout).
Also note that if you switch to jQuery ver to 1.8.3 or above this issue no longer occurs, so it seems that both of us were working on old jQuery libs that day^^
So 2 solutions are: update jquery version to 1.8.3 or above, or create the element without autoplay property and start it later.
I'm working on an audio player using the HTML5 <audio> element and am trying to iron out a few issues cross-browser.
This player is configured to switch between audio tracks when a link for a different track is clicked. Internally, it pauses the <audio> element, sets its currentTime to 0 (as explained in HTML5 audio not playing multiple times in Android 4.0.4 device Native Browser) and removes it from the DOM before a new <audio> element is created with the new source track specified. The play() method is called on the element to load the track and start playing.
On desktop browsers, an iPhone and iPad, this works fine. It also works on a colleague's Samsung Galaxy S3 Mini. However on a different test phone, a full-size Samsung Galaxy S3, the playback of subsequent tracks fails - the track won't even play and it shows in the playback bar as having completed. This is also the case on the stock Android 4.1.2 browser on my Motorola Xoom tablet.
The first track specified on page load always works fine.
After adding a few debugging statements among the JavaScript code, particularly the timeupdate callback function, I have found that in the cases where playback fails, the <audio> element's duration has a value of 1 in the two instances when timeupdate is raised. Normally, the duration is reported as anything from 350 to just over 1000 for a 3-4 min track. This explains why the playback bar immediately showed the newly-loaded track as having completed playback.
I'm thinking that the subsequent track isn't being loaded properly; even if it has been previously loaded and cached on the phone, surely it must be able to be loaded correctly. All tracks are MP3s and are able to be played in the respective browsers.
What am I missing here? Any idea what the problem is and how to get this to work?
Many thanks.
More Info:
I've hooked up other events to the <audio> element to trace what may be happening:
progress (with a report on the buffered ranges)
loadedmetadata
canplay
error
On desktop (where this works correctly), the events are as follows:
timeupdate (with NaN duration), progress x3 (0 buffered ranges), loadedmetadata, canplay, timeupdate with duration of 121.172368, progress with 1 buffered range [0, 11.507715], followed by a sequence of timeupdate and progress events as the track continues to play. The iPhone has a similar sequence of events.
On the Samsung S3, I get the following events: timeupdate with a duration of 1, followed by progress (0 buffered ranges), loadedmetadata, canplay, and finally a timeupdate with duration still at 1.
This page has been very useful in explaining the events and data structures: http://www.sitepoint.com/essential-audio-and-video-events-for-html5/
Well I finally solved it:
Firstly, I updated the audio implementation to reuse the same <audio> element when switching tracks, making sure that I paused the audio before changing the src, etc. This may or may not have had any positive effect, though it was a way to guarantee that we didn't have too many <audio> elements potentially floating around in memory, especially if some unknown phone can only handle one instance at a time.
Before switching tracks, I added a guard clause to stop any currently-playing audio and ensure that neither pause() nor setting currentTime caused an error if no audio had been loaded:
if (audioPlayerElement.readyState > 0)
{
audioPlayerElement.pause();
audioPlayerElement.currentTime = 0;
}
Since subsequent tracks are auto-played, the ordering of statements needed fixing.
The misreporting of the track duration was a symptom of a larger issue in the way the <audio> element was being used. Previously, I had initialised the audio player as follows:
Create the <audio> element / set the src to the new URL of the MP3 track
Call load() on the <audio> element
Bind the timeupdate and ended events
Since this was an auto-play, added the autoplay attribute to the <audio> element
Since this was an auto-play, called play() on the <audio> element
(The binding of loadedmetadata, canplay, progress events for debug tracing was performed between steps 1 and 2 above.)
The problems that I found with this sequence were:
Calling play() is redundant if the autoplay attribute is set; and
Adding the autoplay attribute should happen before load() is called, since load() automatically starts playing the track once enough data has been buffered.
Thus, the final steps that work are:
Set the src attribute of the <audio> element to the new URL of the MP3 track
Bind the timeupdate and ended events
Since this is an auto-play, add the autoplay attribute to the <audio> element
Call load() on the <audio> element
The play() function only applies when clicking the play/pause button or starting playback from a particular position on the track bar.
Finally, it's worth noting that on iOS devices and some Android devices (depending on browser), auto-play is ignored if the player is initialised to start playing on page load. On such devices, auto-play will only work if the execution can be traced back to a click event (or similar). Bear this in mind when updating visuals to indicate 'playing' state - the canplay event handler seems a good place to do this.
I'm going to fully answer your question because it is useful for me as well - if you have a better solution please let me know :)
I'm going to be keeping a hash of all the metadata I'll need for each sound. This hash is probably going to be just a json response from the server - eg:
app.sounds.metadata = {
"enter the sandman": {
"artist": "Metaliica",
"album": "Metallica.",
"description": "Lorem ipsum dolor sit amet."
"genre": "metal",
"duration": 19920,
"playcount": 312
},
"piano man": {
"artist": "Billy Joel",
"album": "You're my home",
"description": "Lorem ipsum dolor sit amet."
"genre": "Soft rock",
"duration": 16200,
"playcount": 135,
}
}
And my audio elements will be declared such that:
<audio data-sound="piano man">
<source src="piano_man.ogg" type="audio/ogg">
<source src="piano_man.mp3" type="audio/mpeg">
</audio>
Now when I'm using my sound I can just use:
var html5offset = 1000
var meta = app.sounds.metadata[sound.getAttribute("data-sound")];
var soundduration = meta.duration || sound.duration*html5offset;
I have a problem with the .load(); function on my ipad.
$(this).bind('ended',function() {
$('video').load();
});
It's a simply function for loading the same content after the Video ends.
Any idea why this function does not work on an iPad?
The .load() method loads the video into the tag. The .play() method starts the currently loaded video. One more thing to keep in mind is this, is the video the right format? The tag can load quite a few formats but not every browser can handle every format. iOS browser like iPad/iPhone and even Safari on OSX/Windows can play m3u8 playlists encoded with h264/AAC and mp4 encoded with h264/AAC files but will not play webm, vp8 or avi. So you need to keep all of this in mind when building this type of tag. You might want to look into just building the the player with straight Javascript and supplying multiple tags and then let the browser determine the video it can play. (I did this at a past job and it is a lot easier than you might think) And I believe that with certain browsers you need to reset the 'play pointer' and tell it to start at position 0
jsfiddle [dot] net/nexxuz/XuLCC/15/
(will not let be post link without code)
And I was able to get this working playing multiple videos too (once one ended played another) (Ad video plus content video) also I was able to get a mid roll video working too. (at x seconds into video play another video and then once that video is done resume the first video)
I have modified this example in order to run it with my own videos.
It does not work for any video.
In particular, it does not start to play if the video has a duration > 5 sec (I mean the complete video file, not a chunk) what just does not seem reasonable at all and I couldn't find out why this happens.
I get INVALID_STATE_ERR: DOM Exception 11 every time I call the method append() and endofstream()
By the way, I tried with a lot of different videos changing parameters and it does not seem to depend on the file size but only on the duration. So that a small part of a video does work.
webkitsourceopen event is fired but not webkitsourceend.
Where could this 'restriction' come from?
I'm having an issue with the AUDIO tag. I have an HTML page (with javascript) where 4 sound files play in succession. In iOS 5, and latest safari, things play wonderfully, but in 4.3(.2) things aren't working.
Below are the MANY solutions I have tried. It should be noted that playing ONE sound file on a page is not a problem. I have Voice Over audio playing on page-load for most of my pages and that works fine.
All of the below methods work perfectly in 5.0 and latest desktop safari, just not in iOS 4.3 simulator/device:
1) Have a hidden div, set innerHTML = an tag with the appropriate src file
1a) onended - clear div innerHTML, load next audio file
1b) setTimeout, delay 2 seconds between each file (which is 1 second long) then load next sound
2) Hidden div, set innerHTML = 4 audio tags
2a) onended - .play() next audio file
2b) setTimeout - .play() next audio file
3) replaced with EMBED
4) replaced with OBJECT
5) Used javascript only:
a = new Audio(src); a.play();
The behavior is best described as "wonky". Sometimes only 1 sound will play, others two will play, rarely 3. Sometimes the first will repeat 4 times (while the debug displays that 4 different sounds should have played)
My ultimate goal is to have a random sequence of 4 sounds played in succession.
It seems like if I do everything with 1 javascript audio control, things work better...
I created a global audio control:
var a=new Audio();
Whenever I wanted to play a sound I did:
a.pause();
a.src='newfile.m4a';
a.play();