1

So in my audio player (ka-musicplayer.glitch.me) i saw a flaw that when i played audio by typing the path to an MP3 it returned that. If i predefine the MP3s, it works. Feel free to see the code here.

   var input = document.getElementById("input");
      var inputVal = "";
      if (input) {
        inputVal = input.value;
      }

      var player = new Audio(inputVal);
      player.crossOrigin = "anonymous";
  var s2 = document.createElement("button");
      s2.innerText = "Play";
      s2.addEventListener("click", function() {
        player.src = inputVal;
        player.play();
      });
      document.body.appendChild(s2);
<!DOCTYPE html>
<head></head>
<body>


<input id="input" />
Check JS Console in current browser for error
Karim AlAhmed
  • 23
  • 1
  • 5
  • This is a cool idea--however, simply entering the path/URL of an MP3 in an `input` and retrieving it as a string with `.value` won't do much for you, especially since you're trying to access files from other domains. You might want to try `Fetch` the specified URL/resource and set the `Audio.src` with the returned Promise. See here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch – Hello World Oct 22 '20 at 02:59
  • can you give me an example code snippet? you can use this for the sound: https://cdn.glitch.com/ad51e798-dd80-42d5-a0d3-6e61db915f66%2Fshakedown.mp3 @HelloWorld – Karim AlAhmed Oct 22 '20 at 15:06
  • I tweaked around with your code and got a working solution! See the below answer. @KarimAlAhmed – Hello World Oct 22 '20 at 21:13

2 Answers2

0

After investigating the Audio() constructor, I've revised your code.

Firstly, you could write the button element in your HTML and add an event listener rather than generating it dynamically.

<!DOCTYPE html>
<head></head>
<html>
<body>
    <input id="input" type="text">
    <button id="play">Play</button>
</body>
</html>

Also, at least in the snippet you provided, you're grabbing the value of the input right away. I'd grab the value when you click the play button:

const input = document.getElementById("input");
const playButton = document.getElementById("play");


playButton.addEventListener("click", function() {
    if (input.value.length) {
        let inputVal = input.value;
        var player = new Audio(inputVal);
        player.crossOrigin = "anonymous";
        player.addEventListener("canplaythrough", function() {
            player.play();
        })
    }
})

Notice the "canplaythrough" listener on the player--this delays playing the audio until the audio element and file itself have been completely loaded. You also didn't need to assign a src to the element; the URL passed into the Audio() constructor is automatically assigned to the source.

Hello World
  • 361
  • 1
  • 9
0

I also had trouble when dynamically added songs ended with "Uncaught (In promise): (DOMException) The element has no supported sources" . Where initially loaded songs on page refresh, worked just OK, but newly added NOT even thought its same code. I tried to discard old songs with "song.srcObj = null;" to help garbage collector, then I tried to always generate unique song url if some troubles happening when loading same song (element.song = new Audio("https://domain.cz" + element.file + "?" + new Date().getTime());)

What really helped was :

song.load();

More preciselly, since play is promise, so catching when this error breaks promise and then call load. (loading song just after it was created had no impact strangely, only when attempting to play), here is code I use :

                    var playPromise = songToPlay.song.play();
                    // In browsers that don’t yet support this functionality,
                    // playPromise won’t be defined.
                    if (playPromise !== undefined) {
                        playPromise.then(function() {
                            // Automatic playback started!
                        }).catch(function(error) {
                            console.log(error);
                            console.log("try to reload");
                            songToPlay.song.load();
                            songToPlay.song.play();
                        });
                    }

Part of code is taken from "how to catch play error" - JavaScript audio.play() error

And of course user have to click on page at least once (I have click to show player area, so chrome wont disable audio playing straight ahead)

Jiro Matchonson
  • 875
  • 1
  • 17
  • 24