Mobile audio playback compatible scheme

Now many mobile terminals require that audio play must be triggered by the user's event, otherwise it will be hijacked. In practical applications, JS network requests often decide what audio to play through the returned results, which is not allowed in the mobile end.

When the mobile needs to play the audio through the network request callback, it needs to do some preparatory work. The specific code is as follows:

Load preparation processing

/**
 * Cycle processing
 * @param {Object} data
 * @param {Function} callback
 * @returns {undefined}
 */
function each(data, callback) {
    if (typeof data === 'object') {
        if (data.length) {
            for (var key = 0; key < data.length; key++) {
                if (callback(key, data[key]) === false) {
                    break;
                }
            }
        } else {
            for (var key in data) {
                if (callback(key, data[key]) === false) {
                    break;
                }
            }
        }
    }
}

/**
 * Play audio
 * @param {String} name
 * @returns {undefined}
 */
function audioPaly(name) {
    each(name.split(/\s+/), function (_, name) {
        if (audioPaly.lists[name]) {
            audioPaly.lists[name].play();
        }
    });
}
audioPaly.lists = {};

/**
 * Ready audio processing
 * @returns {undefined}
 */
function audioReady() {
    var audio;
    while ((audio = audioReady.lists.pop())) {
        audio.play();
        audio.pause(); //Pause directly and play again quickly
    }
}
audioReady.lists = [];

/**
 * Loading audio
 * @param {String} path
 * @param {Function} callback
 * @returns {undefined}
 */
function loadAudio(path, callback) {
    var audio = create('audio', {preload: 'load'});
    each({'ogg': 'ogg', 'mp3': 'mpeg', 'wav': 'wav'}, function (name, type) {
        audio.appendChild(create('source', {src: '/audio/' + path + '.' + name, type: 'audio/' + type}));
    });
    addEvent(audio, 'loadedmetadata', function () {
        audioPaly.lists[path] = {
            play: function () {//play
                    audio.currentTime = 0; //This is not very useful, compatible processing
                                if (!audio.ended) {
                                     audio.load(); //Reload, compatible processing, but also can quickly start playing
                                }
                audio.play();
            }
        };
        audioReady.lists.push(audio);
        callback && callback();
    });
    loadAudio.frame.appendChild(audio);
}
/**
 * Create elements
 * @param {String} elem
 * @param {Object} addAttr
 * @returns {Element}
 */
function create(elem, addAttr){
    var Elem = document.createElement(elem);
    for(var key in addAttr){
        Elem.setAttribute(key, addAttr[key]);
    }
    return Elem;
}

//Loading audio
loadAudio('test');

User event trigger processing

//Bind user triggered element click event
element.addEventListener('click', function(){
    audioReady();//Audio trigger ready processing for callback playback
    //Network request code
    ....
        //Network callback
        function (){
            audioPaly('test');//Playback processing
        }
    ....
});

Prepared audio files (why not prepare more than one, see the specific terminal supporting audio format)

/audio/test.mp3

/audio/test.ogg

/audio/test.wav

This code is not complicated, but uses a little license in the mobile terminal restrictions. When it is played in the user trigger event, it can be played again in the subsequent operations.

As long as we play the audio after the user triggers and pause or mute it in time, we can not hear the audio. Then we can play it again in the network request callback, dynamic play.

Original link

https://blog.51cto.com/php2012web/2066930

Service recommendation

Tags: network Mobile

Posted on Sun, 01 Dec 2019 20:00:30 -0800 by richie1975