iOS Safari在一次触摸后按顺序播放声音

时间:2015-05-29 19:11:31

标签: javascript ios audio safari playlist

我正在为iOS上的safari播放音频做一些R& D。我知道在必须通过用户发起的事件完成时,以编程方式播放音频存在限制。我想知道的是,如果我们可以发起一个播放列表。我希望能够通过一个数组并在我从初始按钮开始后逐个播放声音。我的代码看起来像这样:

<button id="play-btn">Play sounds</button><br/>
    <input class="text-input" type="text" placeholder="text for a sound here" value="hello world"><br/>
    <input class="text-input" type="text" placeholder="text for a sound here" value="typing a sound"><br/>
    <input class="text-input" type="text" placeholder="text for a sound here" value="my name is kobby"><br/>
    <input class="text-input" type="text" placeholder="text for a sound here" value="whatup allisha"><br/>

我的js看起来像这样:

(函数(){

function createAudioFile(text){
    console.log('audio file create', this);
    var audioSrc = "http://vaas.acapela-group.com/Services/Streamer?req_voice=sharon22k&req_text="
        + text.split(' ').join('+') + "&cl_login=EVAL_VAAS&cl_app=EVAL_7285884&cl_pwd=h1j1endv";

    var audioFile = new Audio();
    audioFile.src = audioSrc;

    if(audioFile.canPlayType('audio/mp3')) console.log('can play mp3');
    if(audioFile.canPlayType('audio/ogg')) console.log('can play ogg');

    console.log(audioFile);

    return audioFile;
}

var btn = document.querySelector('#play-btn');
var inputs = Array.prototype.slice.call(document.querySelectorAll('.text-input'));

btn.addEventListener('click', function(){

    //keep this context obj through all new callbacks or function calls
    var ctx = this;
    console.log('initial click', this);

    var values = inputs.map(function(el, i){
        return el.value;
    });

    console.log(values);
    var currentAudioIndex = 0;
    function playAudio(){
        console.log('playing audio', this);
        var audioFile = createAudioFile.call(ctx,values[currentAudioIndex]);

        var events = ['loadstart', 'stalled', 'suspend', 'waiting', 'progress', 'error', 'abort'];
        for( var i = 0, len = events.length; i<len; i++ ){
            audioFile.addEventListener(events[i], function(evt){{
                console.log(events[i] + ' just fired');
            }}.bind(ctx));
        }

        audioFile.addEventListener('ended', function(){
            console.log('audio end',this);
            currentAudioIndex ++;
            audioFile = null;//for ram purposes
            if(currentAudioIndex < values.length) playAudio.call(ctx);

        }.bind(ctx), false);

        audioFile.load();
        audioFile.play();

    }

    playAudio.call(ctx);


}, false);

})();

这适用于Chrome,它可以播放我正在使用的Vaas帐户中的所有4种声音。但它只能在iPad上播放第一个声音。

无论如何我可以做递归函数并仍然保持调用堆栈吗?我在开始时传递的是同一个环境,但这似乎还不够?任何有关这方面的帮助都会很棒!

由于 Kobby

1 个答案:

答案 0 :(得分:0)

这里最好的解决方案是使用Web Audio API而不是Audio对象。 Web Audio API可以广泛使用,甚至可以在iOS 6中使用。这将允许您拥有一个可以将声音叠加在一起的常量AudioContext,如果您愿意,甚至可以同时播放多个。

一个&#34;陷阱&#34;是iOS Safari实现了较旧的Web Audio API,因此它使用AudioBufferSource.prototype.noteOn(ms)noteOff(ms)而不是start()stop();它足够简单到polyfill。

如果您想继续使用Audio方法,请注意中间会有一秒钟的沉默。另外,我建议在同一个对象上重新分配src属性,而不是创建新的属性,以避免这样的问题。