firefoxweb-audio-apigetusermedianavigatormediadevices

Web Audio Api : navigator.mediaDevices.getUserMedia ---> Error:NotReadableError: Concurrent mic process limit


I am developing a 3D environment that connects two microphones with a specific geometry in my scene , runs locally. I want to be able to switch between which microphone is being used ( when I press key A use mic1 and when I press key B use mic 2 ). The error I get is : Firefox ----> Error:NotReadableError: Concurrent mic process limit. Chrome -> no Error, it just doesn't switch devices

How can I fix that ? I tried to stop the stream but maybe I am not doing it right , any suggestions ?

async function openMic(nodein){ 

 // inputDevices is an array with the deviceIds
 await  navigator.mediaDevices.getUserMedia ({audio: { deviceId: {exact: 
                         inputDevices[nodein]}}, video: false}) 
 
    .then(function(stream) {
    console.log('THE DEVICE IS: '+ thisdev);    

    //soundNodesArray has objects that represent different sources
    soundNodesArray[nodein].source=context.createMediaStreamSource(stream);

    //making our source a stream connect source with Gain node
    soundNodesArray[nodein].source.connect(soundNodesArray[nodein].volume);
                
    //connect Gain node with Panner node                     
    soundNodesArray[nodein].volume.connect(soundNodesArray[nodein].panner);
                
    //connect the Panner Node with the Destination node                  
    soundNodesArray[nodein].panner.connect(context.destination);
 })
.catch(function(e){
    alert('Error:'+e);
    });
        
}       

For stopping the track I call this function first :

    async function closeMic(nodeout) {
await   navigator.mediaDevices.getUserMedia({audio: true, video: false})
    .then(function(mediaStream) {
        const tracks = mediaStream.getTracks();
          
        tracks.forEach(function(track) {
        track.stop();
        console.log('STOPPED STREAM ?????????');
        });
    })
  
    soundNodesArray[nodeout].source = null;
  }
enter code here

Solution

  • await ... .then() is not correct.

    To open up your stream, do something like this.

    let stream  // keep the stream so you can stop it later.
    async function openMic(nodein){ 
      try {
        // inputDevices is an array with the deviceIds
       stream = await navigator.mediaDevices.getUserMedia (
                     {audio: { deviceId: {exact: inputDevices[nodein]}},
                      video: false}) 
     
       //soundNodesArray has objects that represent different sources
       soundNodesArray[nodein].source=context.createMediaStreamSource(stream)
    
       ...
      } catch (e) {
        alert('Error:' + e)
        console.error(e)
      }
    }
    

    Later, to stop the stream stop all its tracks and forget it exists. Don't use .getUserMedia() to try to get another stream to stop. Instead stop the one you already have.

    const tracks = stream.getTracks()
    tracks.forEach(track => {track.stop()})
    stream = undefined
    

    I'm not familiar with the AudioContext stuff; you may have to stop that stuff too before starting a new stream.

    It's best to stop one stream before using getUserMedia() to start another. Some browsers allow you to start one stream before stopping another. Others don't.