Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically Created Audio Object not playing in Android Chrome browser

I'm trying to write a RIA which can be used on both Mobile as well as desktop browsers. One main objective of this app is to play sounds. There could be X many (as of now, there are 150+)

On a certain user action I want to create a new audio object, load a certain clip, and play it. Ideally, I'd create a new 'Audio' object, set the src wait for load then play. This works on various desktop browsers, however seems to fail on Android 4.2, Chrome and stock browsers.

I've tried 4 different ways of including audio:

  1. Including (in html) just an audio block, have it load at runtime and calling .play(); This works however It means I must create 150+ audio blocks. (this works everywhere)
  2. Create a new instance of 'Audio' and dynamically setting the .src attribute, then on loadcomplete calling .play() (this seems to works only on desktop browsers, NOT on my mobile)
  3. Use jQuery to Create new audio tag, add to dom, wait for load then play (this seems to works only on desktop browsers, NOT on my mobile)
  4. Add Audio tags in html with telling it to not load, wait for user interaction, then load it, wait for it to get ready, then play (this works everywhere).

So, the big question is, any idea why this isn't working?

** Edit ** I know that only 1 file can be played at a time, and that is what I'm trying to do here. Project is (functionally) similar to a phone service, where you have 1 person record the numbers 0 - 9 , then it 'speaks' a phone number so '5'.'5'.'5'.'0'.'1'..... etc. So 1 audio stream out at a time is perfectly acceptable... It's just getting it to play which is the issue.

As of right now, I have the following code, which can also be found here

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>test</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script>
    var $a1, $a2, $a3, $a4;
    $(document).ready( function(){
        _setupVars();
        _addListeners();
    })

    function _setupVars(){
        $a1 = $( "#audio1");
        $a2 = $( "#audio2");
        $a3 = $( "#audio3");
        $a4 = $( "#audio4");
    }

    function _addListeners(){
        $a1.click( _handleAudio1 );
        $a2.click( _handleAudio2 );
        $a3.click( _handleAudio3 );
        $a4.click( _handleAudio4 );
    }

    function _handleAudio1 (){
        $("#america")[0].play();
    }

    function _handleAudio2 (){
        var a = new Audio();

        $(a).on("canplay", function(){
            a.play();
        })

        if(a.canPlayType("audio/mp3"))
            a.src = "audio/test2.mp3";
        else if(a.canPlayType("audio/ogg"))
            a.src = "audio/test2.ogg";
    }

    function _handleAudio3 (){
        var $x = $('<audio id="says">'+
                '<source src="audio/test3.mp3">'+
                '<source src="audio/test3.ogg">'+
                '</audio>');
        $x.on("canplay", function(){
            $x[0].play();
        })
        $("#audioCont").append($x);
    }

    function _handleAudio4(){
        var $x =$("#cat");
        $x.on("canplay", function(){
            $x[0].play();
        })
        $x[0].load();
    }

</script>
</head>
<body>
    <input type="button" id="audio1" value="play Audio Tag"/><br />
    <input type="button" id="audio2" value="play audio object"/><br />
    <input type="button" id="audio3" value="play dynamic Audio Tag"/><br />
    <input type="button" id="audio4" value="play load Audio Tag, then play"/><br />
    <audio id="america">
        <source src="audio/test1.mp3">
        <source src="audio/test1.ogg">
    </audio>
    <audio id="cat">
        <source src="audio/test4.mp3">
        <source src="audio/test4.ogg">
    </audio>

</body>
</html>
like image 901
whomba Avatar asked Jun 09 '13 00:06

whomba


2 Answers

Right now Chrome on Android there is an explicit need for the user to "invoke" playback via a gesture to play audio. There were concerns of overloading the mobile devices bandwidth or creating annoying popups that just play audio - which is one of the reasons why it is disabled by default.

We are looking at changing this, and if you are on Beta of Chrome on Android you can go to this link chrome://flags/#disable-gesture-requirement-for-media-playback and it will let you toggle this behavior. We are working on the issue and you can follow it on Bug 160536

like image 59
Kinlan Avatar answered Sep 21 '22 02:09

Kinlan


Methods 1, 2 & 3 will not work on iOS. Unfortunately most mobile devices limit HTML5 audio to a single source playing at a time. iOS requires user interaction to initiate any media playback (onload doesn't count).

like image 28
idbehold Avatar answered Sep 21 '22 02:09

idbehold