navigator.enumerateDevices returning different Device IDs Intermittently

1k views Asked by At

I am in the process of converting a chrome extension to manifest v3 and ran into an issue that may or may not be related to this. I am using the navigator.mediaDevices.enumerateDevices to get a list of the connected microphones. I am having issues with the saved microphone not being selected when opening new tabs and after some debugging, I've found the the deviceID is different when reloading from different tabs. The code to get the list is pretty straighforward;

function getBrowserMics() {
    //This is just building the mic list
    var stream;

    navigator.mediaDevices
        .getUserMedia({ audio: true })
        .then(s => (stream = s), e => console.log(e.message))
        .then(() => navigator.mediaDevices.enumerateDevices())
        .then(devices => {
            $.each(devices, function(index, dv) {
                if (dv.kind == "audioinput") {
                    if (
                        typeof storedBrowserMicList[dv.deviceId] == "undefined"
                    ) {
                        browserMicList.push(dv);
                        // console.log(`browserMicList array ${browserMicList}`);
                        storedBrowserMicList[dv.deviceId] = dv;
                        console.log(`Stored Browser Mic list object is: ${JSON.stringify(dv)}`);
                    }
                }
            });
        })
        .catch(e => console.log(e));
}

For testing, I used a single device that I jsut kept connected to the computer. If I run this on one tab, I get the following;

content.js:118 Stored Browser Mic list object is: {"deviceId":"436f6e823d2ce9846735e8091cb20fe3bb3fbdb28c33c353d657b34fafbb383d","kind":"audioinput","label":"Microphone 1 (0555:1002)","groupId":"23d7627f4f062c3d9f28596532e5e467e4662f3b142ff583909dab5a8f3d413f"}

This remains the same if I refresh the tab. If I go to another tab, I get the following;

Stored Browser Mic list object is: {"deviceId":"6c07bd2b34257d25afd5bc59613e470a019994273d5bfa4546318ade36336fe9","kind":"audioinput","label":"Microphone 1 (0555:1002)","groupId":"e617ed598de785b4d655ed017586dc954cdc8e1abbbecdd78288a1109848ddba"}

I thought maybe it was a domain issue but I tried using the same domain as the other tab but it was different. Now to throw another wrench in it, While testing, I found that sometimes I would get a previous deviceID used with that device in another tab. It seems like it is inconsistent. One thing that is different is I am also connecting to this device through webHID API. I did some testing after connecting the device through the webHID but that didn't seem to affect the device ID whether it was connected or not. My main test machine is macOS running chrome 99.0.4844.74.

I found a post from last year from someone who had the same issue but there was no resolution added to it; Why navigator.mediaDevices.enumerateDevices() returns different values?.

Does anyone have any suggestions as to why this is happening and how I can prevent the device IDs from changing between tabs?

1

There are 1 answers

0
nondebug On

Maybe it's this behavior described in the spec?

However, as long as no local device has been attached to a live MediaStreamTrack in a page from this origin, and no stored permission to access local devices has been granted to this origin, then the User Agent MAY clear this identifier once the last browsing session from this origin has been closed. If the User Agent chooses not to clear the identifier in this condition, then it MUST provide for the user to visibly inspect and delete the identifier, like a cookie.

https://www.w3.org/TR/mediacapture-streams/#dom-mediadeviceinfo-deviceid

It's a tricky balance between enabling device identification and mitigating fingerprinting. A page might enumerate devices it doesn't intend to use just to access those unique device IDs. The browser protects the user's privacy by keeping separate IDs for each origin and creating new IDs for origins that don't actually need device access.