3

When playing a live audio stream, like web radio, through <audio> or Audio(), the pause event can fire in (at least) three ways:

  1. user clicks on the pause button (with <audio controls>)
  2. user clicks the browsers global audio controls
    • iOS: Control Center
    • Android: browser's notification drawer (at least Chrome, Opera, Firefox)
    • Desktop: Media Session API controls, but uninitialized, without explicit setActionHandler (might be hidden behind a flag as of now)
  3. a buffer underrun caused by various network conditions

Is it possible to distinguish between 1/2 and 3?

  • Ideally, there would be an event property like isTrusted, which I am missing
  • I have tried to guess, looking esp. at readyState and networkState, but both are very inconclusive, especially across browsers (e.g. the interpretation/semantics of HAVE_FUTURE_DATA vs HAVE_ENOUGH_DATA)
  • I have shied away from making a "decaying state machine", juggling other events. A buffer underrun is often preceded by stalled events, and sometimes followed by ended events. A cross-browser implementation seems crazy complex and the danger of false positives very high.

Am I out of luck until Media Session lands everywhere?

Note: this question looks like a solution, but unfortunately isn't -- browsers handle live streams' "ends" differently and inconsistently.

kubi
  • 477
  • 1
  • 9
  • 23

2 Answers2

0

The waiting event should fit your needs.

You can try this demo while you simulate bad network with the dropdown in Chrome's Network tab (e.g: Slow 3G)

const video = document.getElementById('mwe_player_0');
video.onwaiting = function() { console.log('onwaiting'); };
<video id="mwe_player_0" controls="" preload="none" style="width:800px;height:450px"><source src="https://upload.wikimedia.org/wikipedia/commons/2/22/Volcano_Lava_Sample.webm" type="video/webm; codecs=&quot;vp8, vorbis&quot;"></video>

Note that this demo works with HTMLAudioElement as well (because it inherits HTMLMediaElement). The video demo is just easier to test.

Guerric P
  • 20,579
  • 2
  • 28
  • 66
  • Thanks, but again, I'd have to set some flag, like `was_waiting`, to then reason that the `pause` was *maybe* a network event (how much time has to pass so it isn't?). If it wasn't clear enough: I have to deal with the `pause`, not find an alternative. I've had some success in my narrower use case with the similar `ended` event: for a live stream that is expected to be playing (again, a flag), a `pause` event that precedes `ended`, becomes moot - and I can deduce, that any other `pause` *must* be user interaction... until a new control scheme comes along ;) – kubi Feb 17 '20 at 17:45
  • ...tl;dr: I had looked at this & other events, still frustratingly implicit guess-work, at best. – kubi Feb 17 '20 at 17:48
  • Why do you have to deal with the `pause` event while it doesn't fire on lack of data? – Guerric P Feb 17 '20 at 18:09
  • `pause` events *do* happen for finite resources, they become moot for **live streams only** – kubi Feb 24 '20 at 12:45
0

If you want to start an event when the user pauses the audio then this snippet will do the job. I didn't test it on mobile in the notification drawer but I think it'll work.

const video = document.querySelector('video');

video.addEventListener('pause', (event) => {
  console.log('The Boolean paused property is now true. Either the ' + 
  'pause() method was called or the autoplay attribute was toggled.');
});

resource: audio element events

resource: pause event

I also found a helpful answer to what you are trying to do 2 (at least from what I understand) and why it's a bad technique. Link to question

3 Events: stalled / waiting check the events resource

Youssef AbouEgla
  • 732
  • 5
  • 18
  • Nope, sorry. This just listens for the event, but does not discern its origin. Also, I am not trying to do any UA/mobile-sniffing in the classic sense. – kubi Feb 24 '20 at 12:43