Воспроизведение Safari в iOS звучит последовательно после одного касания

Я занимаюсь исследованиями и разработками с воспроизведением звука в сафари для iOS. Я знаю, что существуют ограничения для программного воспроизведения звука в том смысле, что это должно быть сделано из события, инициированного пользователем. Однако мне интересно, можем ли мы инициировать плейлист. Я хочу иметь возможность просматривать массив и воспроизводить звуки один за другим после того, как я начну с начальной кнопки. Мой код выглядит примерно так:

<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 и воспроизводит все 4 звука из учетной записи Vaas, которую я использую. Однако на iPad воспроизводится только первый звук.

Могу ли я в любом случае выполнить рекурсивную функцию и при этом сохранить стек вызовов? Я прохожу в том же контексте, что и начало, но этого, кажется, недостаточно? Любая помощь в этом была бы потрясающей!

Спасибо, Кобби.


person Kobby    schedule 29.05.2015    source источник


Ответы (1)


Лучшее решение здесь — использовать API веб-аудио вместо аудио объектов. API веб-аудио широко доступен и работает даже в iOS 6. Это позволит вам иметь один постоянный AudioContext, на который вы можете накладывать звуки, даже проигрывая несколько одновременно, если хотите.

Один «подводный камень» заключается в том, что iOS Safari реализовал старый API веб-аудио, поэтому он использует AudioBufferSource.prototype.noteOn(ms) и noteOff(ms) вместо start() и stop(); его достаточно просто полифилл.

Если вы хотите продолжать использовать свой метод Audio, знайте, что между ними будет секунда молчания. Кроме того, я бы рекомендовал переназначить атрибут src для одного и того же объекта вместо создания новых, чтобы избежать подобных проблем.

person hapticdata    schedule 29.05.2015
comment
да, это, кажется, сделал это. должен был помнить процесс «включения звука», но веб-аудио API FTW здесь. Спасибо! - person Kobby; 01.06.2015