3

I'm trying to make an HTML5 audio playlist that will work in each major browser: Chrome,Safari, Firefox, IE9+. However, I can't figure out how to change the sources in a cross browser compatible way.

UPDATED For example, changing the <source> tag's srcs works in Chrome but not Safari. While @eivers88's solution below using canPlayType works it seems easier to me just to change the <source> tag's srcs. Can anyone explain to me why my code directly below works in Chrome but not Safari?

JS:

var audioPlayer=document.getElementById('audioPlayer');
var mp4Source=$('source#mp4');
var oggSource=$('source#ogg');
$('button').click(function(){    
  audioPlayer.pause();
  mp4Source.attr('src', 'newFile.mp4');
  oggSource.attr('src', 'newFile.ogg');
  audioPlayer.load();
  audioPlayer.play();
});

HTML:

<button type="button">Next song</button>
<audio id="audioPlayer">
  <source id="mp4" src="firstFile.mp4" type="audio/mp4"/> 
  <source id="ogg" src="firstFile.ogg" type="audio/ogg" />                      
</audio>

Inspecting the HTML after the button click, the <source src=""/> does change in Safari, its just that the HTTP request is not made, so they the files don't get load()ed and play()ed. Does anyone have any thoughts on this?

tim peterson
  • 23,653
  • 59
  • 177
  • 299

3 Answers3

5

Here is a working exapmle. It's a little bit different from what you have but hopefully this can be helpful.

HTML:

<button type="button">Next song</button>

Javascript/jquery:

    var songs = [
    '1976', 'Ballad of Gloria Featherbottom', 'Black Powder' 
]
var track = 0;
var audioType = '.mp3'
var audioPlayer = document.createElement('audio');

$(window).load(function() {

    if(!!audioPlayer.canPlayType('audio/ogg') === true){
        audioType = '.ogg' //For firefox and others who do not support .mp3
    }

    audioPlayer.setAttribute('src', 'music/' + songs[track] + audioType);
    audioPlayer.setAttribute('controls', 'controls');
    audioPlayer.setAttribute('id', 'audioPlayer');
    $('body').append(audioPlayer);
    audioPlayer.load();
    audioPlayer.play();

});

$('button').on('click', function(){
    audioPlayer.pause();
    if(track < songs.length - 1){
        track++;
        audioPlayer.setAttribute('src', 'music/' + songs[track] + audioType);
        audioPlayer.load();
        audioPlayer.play();
    }
    else {
        track = 0;
        audioPlayer.setAttribute('src', 'music/' + songs[track] + audioType);
        audioPlayer.load();
        audioPlayer.play();
    }
})
eivers88
  • 6,207
  • 1
  • 33
  • 34
  • Also, if you're on pc, make sure you have quick time player installed! A mistake I have made before! =D – eivers88 Jun 24 '12 at 04:27
  • -@eivers, thanks but this will fail on Firefox b/c there is no `ogg` mime-type. That is why I'm using the `` tag and not just the `audioPlayer`'s src attribute. Any suggestions for that? – tim peterson Jun 24 '12 at 04:59
  • That's why I added the `if(!!audioPlayer.canPlayType('audio/mp3') === true)` statement, if it is false you can add an `else { audioType = '.ogg' }` and then change the audioType variable to .ogg – eivers88 Jun 24 '12 at 05:04
  • Or you could even just have `if(!!audioPlayer.canPlayType('audio/ogg') === true){ audioType = '.ogg' }` so there is no need for an else statement – eivers88 Jun 24 '12 at 05:09
  • I'm still confused on why Safari can't use the `` tags (Chrome can), but it does look like this is the problem and just changing the `src` attribute on the ` – tim peterson Jun 24 '12 at 05:15
  • -@eivers, your solution (the link you provided) doesn't work on Firefox. Do you have the .ogg audio files for that? I'm wondering if the `canPlayType` is even working? – tim peterson Jun 24 '12 at 14:59
  • @timpeterson - Sorry about that, I should have just made it cross browser compliant in the first place, it should work now though. – eivers88 Jun 24 '12 at 16:01
  • -@eivers, thanks I'm trying to replicate your code on my localhost. The only problem is b/c I created the audio element with javascript, it doesn't know what the content header is and so it thinks the mime-type="text/html". Here's the error message: `"HTTP "Content-Type" of "text/html" is not supported. Load of media resource http://localhost/uploads/9/v1/Miaow-02-Hidden.ogg failed."` Thoughts? – tim peterson Jun 24 '12 at 17:31
  • @timpeterson I'm somewhat confused, are you wrapping your js in ``? – eivers88 Jun 24 '12 at 17:41
  • yep this is weird, i'm using apache server and same issue whether or not I make any mime-type declarations in my .htaccess – tim peterson Jun 24 '12 at 17:45
  • Ohh yeah that's a whole other issue on its own, my script should work though once you get your mimeTypes properly set, good luck! – eivers88 Jun 24 '12 at 17:52
  • They are properly set to my knowledge, can i ask your server config? – tim peterson Jun 24 '12 at 17:52
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/12969/discussion-between-eivers88-and-tim-peterson) – eivers88 Jun 24 '12 at 17:54
  • oh man! i had simply just misspelled the name of the folder serving these files. Ugh!!! problem solved. It now plays in safari, chrome, firefox. Thanks for all your help! – tim peterson Jun 24 '12 at 17:58
  • Example link has broken, can you give me another working example? – gowri Aug 13 '14 at 07:20
1

For some reason, Safari can't use the <source> tags for swapping between songs but Chrome can. Just changing what gets loaded into the src attribute on the <audio> tag works on both Chrome and Safari but then there is the ogg vs. mp3 issue.

I guess one way to get around this ogg vs. mp3 issue is to use Modernizr does feature detection to load the ogg mime-type in Firefox and the mp3 in Chrome/Safari. Here's a reference on that: Detecting html5 audio support with Modernizr.

Community
  • 1
  • 1
tim peterson
  • 23,653
  • 59
  • 177
  • 299
0

Just a quick addition to the topic (in 2023):

I had a similar problem. The code was working in Safari, but not Chrome. I had Javascript code that swapped the src of the <source> element. That worked fine in Safari, but Chrome refused to recognize the file and showed a disabled player state. What I was missing, and what I learned here, is that you need to call load() as well.

So adding this fixed it for me.

audioPlayer.load();

Safari seems to auto-detect the source change, Chrome did not.

oelna
  • 2,210
  • 3
  • 22
  • 40