70

I have multiple audio files that I want to stream based on the user selects. How do I do that? This is what I have so far and it doesn't seem to work.

*UPDATE: Made a few changes and now its claiming that audio.load(); is not a function. Can anyone tell me why that is? The Code is updated to reflect the changes.

JavaScript:

function updateSource(){ 
    var audio = document.getElementById('oggSource');
    audio.src = 
        'audio/ogg/' + 
        document.getElementById('song1').getAttribute('data-value');
    audio.load();
}

HTML:

<audio id="audio" controls="controls">
    <source id="oggSource" src="" type="audio/ogg"></source>
    <source id="mp3Source" type="audio/mp3"></source>
        Your browser does not support the audio format.
</audio>

<ul style="list-style: none">
    <li>Sunday May 27, 2012
        <ul style="display: none">
            <li id="song1" data-value="song1.ogg">
                <button onclick="updateSource();">Item1</button>
            </li>
            <li>Item2</li>
            <li>Item3</li>
        </ul>
    </li>
</ul>

Item2 and Item3 I will want to play a different audio file when they are clicked on.

4
  • 1
    You have to play it after you load the media. audio.play. Commented May 29, 2012 at 3:14
  • @Derek That did it! I can't believe I didn't think of that. Now is there a way to make the media player show up? It stays hidden for some reason. Commented May 29, 2012 at 3:21
  • Take a look at my comment below. Commented May 29, 2012 at 3:24
  • 1
    i tried doing <audio src="dropbox/link/ahc.mp3"> and it does work...any idea why? Commented Aug 23, 2012 at 2:13

8 Answers 8

130

Try this snippet

list.onclick = function(e) {
  e.preventDefault();

  var elm = e.target;
  var audio = document.getElementById('audio');

  var source = document.getElementById('audioSource');
  source.src = elm.getAttribute('data-value');

  audio.load(); //call this to just preload the audio without playing
  audio.play(); //call this to play the song right away
};
<ul style="list-style: none">
  <li>Audio Files
    <ul id="list">
      <li><a href="#" data-value="http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.oga">Death_Becomes_Fur.oga</a></li>
      <li><a href="#" data-value="http://media.w3.org/2010/07/bunny/04-Death_Becomes_Fur.mp4">Death_Becomes_Fur.mp4</a></li>
      <li><a href="#" data-value="http://media.w3.org/2010/11/rrs006.oga">rrs006.oga</a></li>
      <li><a href="#" data-value="http://media.w3.org/2010/05/sound/sound_90.mp3">sound_90.mp3</a></li>
    </ul>
  </li>
</ul>

<audio id="audio" controls="controls">
  <source id="audioSource" src=""></source>
  Your browser does not support the audio format.
</audio>

JSFiddle http://jsfiddle.net/jm6ky/2/

Sign up to request clarification or add additional context in comments.

7 Comments

Now it complains that source is null. So it doesn't even get to the audio.load()
Nevermind, source was null because I mispelled the id in one place. But now it doesn't do anything. Firebug doesn't show any errors but it still isn't working. Not sure why.
Yeah I am using your example. I just had to add audio.play() after I loaded the file. Now it plays the music, but I'd like the media player to show up, for some reason it stays hidden.
The player UI is different for each browser, in safari I can see a little black player. I'm not sure if firefox add a UI to the audio tag, but You can do the player UI yourself, and add buttons to player.play() player.pause() etc... including sliders and time stamp
I realize it's different for each browser. It just seems odd that it only shows up in FF once the song ends, but shows up fine from the beginning in other browsers. I've never made a player UI myself, but it might be something I try to do.
|
5

Found this spec note for those trying to change the src of a source element. Especially useful for libs like React where audio.load() causes render loop.

..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, just use the src attribute on the media element directly

<audio>
    <source src='./first-src'/>
</audio>

To change the src

<audio src='./second-src'/>
    <source src='./first-src'/>
</audio>

Comments

4

with jQuery:

 $("#playerSource").attr("src", "new_src");

    var audio = $("#player");      

    audio[0].pause();
    audio[0].load();//suspends and restores all audio element

    if (isAutoplay) 
        audio[0].play();

Comments

3

If you are storing metadata in a tag use data attributes eg.

<li id="song1" data-value="song1.ogg"><button onclick="updateSource()">Item1</button></li>

Now use the attribute to get the name of the song

var audio = document.getElementById('audio');
audio.src='audio/ogg/' + document.getElementById('song1').getAttribute('data-value');
audio.load();

2 Comments

FF and Chrome are now saying that audio.load() is not a function. Do you know why that is?
@Fourthmeal70 Post your updated code so we can see what the problem is.
2

Here is how I did it using React and CJSX (Coffee JSX) based on Vitim.us solution. Using componentWillReceiveProps I was able to detect every property changes. Then I just check whether the url has changed between the future props and the current one. And voilà.

@propTypes =
    element: React.PropTypes.shape({
         version: React.PropTypes.number
         params:
             React.PropTypes.shape(
                 url: React.PropTypes.string.isRequired
                 filename: React.PropTypes.string.isRequired
                 title: React.PropTypes.string.isRequired
                 ext: React.PropTypes.string.isRequired
             ).isRequired
     }).isRequired

componentWillReceiveProps: (nextProps) ->
    element = ReactDOM.findDOMNode(this)
    audio = element.querySelector('audio')
    source = audio.querySelector('source')

    # When the url changes, we refresh the component manually so it reloads the loaded file
    if nextProps.element.params?.filename? and
    nextProps.element.params.url isnt @props.element.params.url
        source.src = nextProps.element.params.url
        audio.load()

I had to do it this way, because even a change of state or a force redraw didn't work.

Comments

1

Try this:

Replace:

audio.load();

with:

audio.play();

8 Comments

I had to do both. Its working now but how to I make it so the media player show up?
Adding src="" there makes it stop working. Firebug says its getting an invalid URI. But when src="" is not there it plays the song fine.
No no no, that src is just an example! You don't need to follow it. All I mean is that controls.
Oh! That was the only difference between what I already had and your example. I have controls there and it still does not show up.
|
0

The error occurs because you need to wait for the new media to load before starting the audio. To do this, use the loadeddata event as below:

Vue 3

<script setup>
    import { ref } from 'vue';

    const srcaudio = ref("");
    
    const playMusic = (url) => {
        srcaudio.value = url
        const audioplay = document.getElementById("audioplay"); // audio element
    
        audioplay.load(); //preload
        audioplay.addEventListener("loadeddata", () => {
             audioplay.play(); //playing
        });
    };
</script>
<template>
        <audio id="audioplay" :src="srcaudio"></audio>
        <button @click.prevent="playMusic('/music-url.mp3')">Play</button>
</template>

HTML/JavaScript

<body>
        <audio id="audioplay"></audio>
        <button id="playbutton">Play</button>
        <script>
             const playbutton = document.getElementById("playbutton"); // button element
             const audioplay = document.getElementById("audioplay"); // audio element

             playbutton.addEventListener("click", (e) => {
                 audioplay.src = '/music-url.mp3'; //new url
                 audioplay.load(); //preload
                 audioplay.addEventListener("loadeddata", () => {
                     audioplay.play(); //playing
                 });
             });
        </script>
</body>

Comments

-2

change this

audio.src='audio/ogg/' + document.getElementById(song1.ogg);

to

audio.src='audio/ogg/' + document.getElementById('song1');

1 Comment

It still doesn't seem to work. Firebug is saying its getting a 500 because it looks like its passing %5Bobject%20HTMLLIElement%5D that in when it runs the document.getElementById('song1'); I'm not sure what that means.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.