5

I want to pause the video if the audio device changes. e.g. if the headphones get plugged out. Is there an event for that?

I went through some other questions but they are not for browser

  1. Detect if headphones are plugged in or not via C#
  2. Detecting when head phones are plugged in
  3. Android: Checking if headphones are plugged in
Souradeep Nanda
  • 3,116
  • 2
  • 30
  • 44
  • I assume there has to be an event for it since youtube does this. +1 – Lord Elrond Mar 09 '19 at 02:25
  • https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API should cover what's possible within a modern browser in terms of audio support – ADyson Mar 09 '19 at 02:29

1 Answers1

3

This isn't perfect and it might be a little hacky since it relies on the browser exposing the label attribute of the MediaDevice and then trying to use the string "head"to guess if the user has a headphone device connected, but you could also just watch the number of connected audio devices and pause whenever it changes or something depending on your usecase.

Almost all of the logic was adapted from the MDN page for navigator.mediaDevices.ondevicechange.

NOTE: This code does not work properly when executed from a file:// URL and must be accessed via an http:// or https:// URL for the browser to actually let you access the label property of the MediaDevice. Also, depending on your browser, you may need to use the hack featured in the first iteration of this answer which will ask the user for microphone access and grant you access to the label property.

// let's assume we don't have any headphones connected
let headphonesConnected = false;

const updateDevices = () => {
  navigator.mediaDevices.enumerateDevices()
    .then(function(devices) {
      // check to see if we have any device with "head" in its name connected
      // like "headset" or "headphones"
      headphonesConnected = devices
        .filter(device => /audio\w+/.test(device.kind))
        .find(device => device.label.toLowerCase().includes('head'))
      ;
    })
  ;
};

updateDevices();

// add an ondevicechange event listener so we can tell when
// an input device is connected and disconnected
navigator.mediaDevices.ondevicechange = updateDevices;

NOTE: Testing has been spotty with this new, simpler version, but it eliminates the microphone access requirement. Some browsers also take longer to trigger the ondevicechange handler than others.

Eric Allen
  • 442
  • 3
  • 10
  • In a better world I would be totally outraged that browsers have the unmitigated gall to make this possible, but in this world, it just never seems to stop. I already feel so utterly helpless against the existence of APIs like this and at this point I've no energy left to get outraged. – Boann Mar 09 '19 at 21:48
  • @Boann I don't see the big deal in knowing if the user plugs or unplugs headphones, but maybe I'm not imaginative enough. The immediate usecase I could see would be to pause audio, like many mobile devices do, when the user's headphones are unplugged. I would actually prefer a much cleaner and less hacky implementation where you've just got an `onAudioDestinationChange` or `onAudioDeviceConnected`/`onAudioDeviceDisconnected` event you can listen for. – Eric Allen Mar 10 '19 at 16:46
  • This is hacky, but it's a great solution. Thank you for this. This is useful because theres a bug in chrome, that with spatial audio enabled, echo cancellation doesn't work. So basically you only want to enable spatial audio if headphones are plugged in. See this bug: https://bugs.chromium.org/p/chromium/issues/detail?id=687574 – Oved D Jan 25 '21 at 02:19
  • Does this not work with other languages? – Oved D Jan 25 '21 at 02:23
  • @OvedD It's a very hacky and somewhat naive approach to the problem, so it didn't take other locales into account, but you could probably alter the `device.label.toLowerCase().includes('head')` to be a RegEx test that looks for something like `headset` or `headphone` in the languages you are supporting. It also looks like the functionality this hack attempts to implement is being discussed in [WebAudio API Github Issue #89](https://github.com/WebAudio/web-audio-api-v2/issues/89). – Eric Allen Feb 11 '21 at 17:24
  • How to unsubscribe from "devicechange" ? removeEventListener is not working – J4GD33P 51NGH Mar 24 '23 at 09:32