Disable iOS Safari lock screen scrubber for media

Viewed 2753

Safari on iOS puts a scrubber on its lock screen for simple HTMLAudioElements. For example:

const a = new Audio();
a.src = 'https://example.com/audio.m4a'
a.play();

JSFiddle: https://jsfiddle.net/0seckLfd/

The lock screen will allow me to choose a position in the currently playing audio file.

How can I disable the ability for the user to scrub the file on the lock screen? The metadata showing is fine, and being able to pause/play is also acceptable, but I'm also fine with disabling it all if I need to.

iOS Lock Screen

4 Answers

DISABLE Player on lock screen completely

if you want to completely remove the lock screen player you could do something like

const a = new Audio();
document.querySelector('button').addEventListener('click', (e) => {
  a.src = 'http://sprott.physics.wisc.edu/wop/sounds/Bicycle%20Race-Full.m4a' 
  a.play();
});

document.addEventListener('visibilitychange', () => {
  if (document.hidden) a.src = undefined
})

https://jsfiddle.net/5s8c9eL0/3/

that is stoping the player when changing tab or locking screen (code to be cleaned improved depending on your needs)

From my understanding you can't block/hide the scrubbing commands unless you can tag the audio as a live stream. That being said, you can use js to refuse scrubbing server-side. Reference the answer here. Although that answer speaks of video, it also works with audio.

The lock screen / control center scrubber can also be avoided by using Web Audio API.

This is an example of preloading a sound and playing it, with commentary and error handling:


try {
    // <audio> element is simpler for sound effects,
    // but in iOS/iPad it shows up in the Control Center, as if it's music you'd want to play/pause/etc.
    // Also, on subsequent plays, it only plays part of the sound.
    // And Web Audio API is better for playing sound effects anyway because it can play a sound overlapping with itself, without maintaining a pool of <audio> elements.
    window.audioContext = window.audioContext || new AudioContext(); // Interoperate with other things using Web Audio API, assuming they use the same global & pattern.
    const audio_buffer_promise =
        fetch("audio/sound.wav")
            .then(response => response.arrayBuffer())
            .then(array_buffer => audioContext.decodeAudioData(array_buffer))
    var play_sound = async function () {
        audioContext.resume(); // in case it was not allowed to start until a user interaction
        // Note that this should be before waiting for the audio buffer,
        // so that it works the first time (it would no longer be "within a user gesture")
        // This only works if play_sound is called during a user gesture (at least once), otherwise audioContext.resume(); needs to be called externally.

        const audio_buffer = await audio_buffer_promise; // Promises can be awaited any number of times. This waits for the fetch the first time, and is instant the next time.
        // Note that if the fetch failed, it will not retry. One could instead rely on HTTP caching and just fetch() each time, but that would be a little less efficient as it would need to decode the audio file each time, so the best option might be custom caching with request error handling.
        const source = audioContext.createBufferSource();
        source.buffer = audio_buffer;
        source.connect(audioContext.destination);
        source.start();
    };
} catch (error) {
    console.log("AudioContext not supported", error);
    play_sound = function() {
        // no-op
        // console.log("SFX disabled because AudioContext setup failed.");
    };
}

I did a search, in search of a way to help you, but I did not find an effective way to disable the commands, however, I found a way to customize them, it may help you, follow the apple tutorial link

I think what's left to do now is wait, see if ios 13 will bring some option that will do what you want.

Related