39

Am able to play sound with javascript through the following,

    var snd = new Audio('sound.wav');
    snd.play();

This plays the required sound but sometimes it loads slowly or might not even load at all so i encoded the sound in base 64 and tried to play it this way.

      var splash = {
prefix: "data:audio/wav;base64,",
sound: [ "*base64 string here*" ] };

    var snd = new Audio(splash); 
    snd.play();

but the sound does not play, is there a way around it ?

Udo
  • 1,129
  • 3
  • 15
  • 30
  • You did what now? Why would you encode the audio as base64 ! – adeneo Jul 20 '13 at 13:31
  • so that it would play faster, i saw it done in a plugin, google fart scroll – Udo Jul 20 '13 at 13:33
  • 1
    In 2018, it seems that Chrome doesn't support playing WAVs this way. If you `snd.play().catch(err=>console.log(err))` you will see: "NotSupportedError: The element has no supported sources." The solution for me was to use mp3s instead of wavs. The link provided by @Fong-Kah-Chun to generate the string to pass to `new Audio` works great btw. – imjosh Dec 27 '18 at 22:06

2 Answers2

75

That doesn't look like the correct way to use the Audio constructor for HTMLAudioElement / <audio>.

Slight adjustment

var snd = new Audio("data:audio/wav;base64," + base64string);
snd.play();

If it works in console but not in script, it may be getting garbage collected, in which case scope it so it will stay

var Sound = (function () {
    var df = document.createDocumentFragment();
    return function Sound(src) {
        var snd = new Audio(src);
        df.appendChild(snd); // keep in fragment until finished playing
        snd.addEventListener('ended', function () {df.removeChild(snd);});
        snd.play();
        return snd;
    }
}());
// then do it
var snd = Sound("data:audio/wav;base64," + base64string);
Paul S.
  • 64,864
  • 9
  • 122
  • 138
  • 1
    thanks a million @paul s., but which do u think is loads faster, base64 or sound file ? – Udo Jul 20 '13 at 13:38
  • 4
    @UDcreate it depends what you mean "loads faster". The _**base64**_ means the page takes longer to load, depending on your server's _ping_ and sound file size **may be even longer than page+file** for **initial load** because base64 takes up more space, but once the page is loaded, the sound will be available instantly. Alternatively, if you use a _**file**_, the **page loads much faster**, but there **may be a delay** when the sound is fetched from the server when you want to play it. – Paul S. Jul 20 '13 at 13:49
  • @UDcreate It depends. When gzipped, base64 is quite fast. Raw sound file has binary format, so it is more squished at the beginning. Anyway, wav format is very large. Nothing will tell you the truth but performance tests. – Frizi Jul 20 '13 at 13:50
  • @UDcreate also, if an answer is helpful, please up vote it. If an answer solved your problem, please choose it as the solution so others know the question is resolved. – Paul S. Jul 20 '13 at 13:52
  • Thanks @paulS for this... very useful. – Paul T. Oct 17 '15 at 23:15
  • I'm getting this error, when I try..Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first. – Vasanth Nov 09 '18 at 06:26
  • 2
    @Vasanth In 2018, it seems that Chrome doesn't support playing WAVs this way. If you snd.play().catch(err=>console.log(err)) you will see: "NotSupportedError: The element has no supported sources." The solution for me was to use mp3s instead of wavs. – imjosh Dec 27 '18 at 22:08
14
var snd = new Audio("data:audio/x-wav;base64, <URI data>");
snd.play();

There is no need to declare splash as an object variable.

Base64 conversion can be done easily from: https://dopiaza.org/tools/datauri/index.php

Fong Kah Chun
  • 789
  • 6
  • 6