However, when handling page disposal (e.g., navigating to a new tab or returning to the previous tab that does not use the microphone), I attempt to stop the audio track using the code below. Despite this, the audio track does not seem to be disposed of, and the microphone icon remains visible on the browser tab bar:
We used the same approach for testing, and it worked as expected—the microphone icon turns off after calling the stop method.
Could you help verify whether the getUserMedia method is called elsewhere in the code? For instance, if the localAudioInputTrack.testMicrophone method is used without being destroyed after testing, it could cause this behavior.
Thanks for your help @vic.yang ,
The getUserMedia method is used in multiple places throughout our code. One of those usages includes the testMicrophone method, but I destroyed it after use. However, the microphone icon still appears.
Suppose there are many other places that use getUserMedia and in our client code we also use them, how can we ensure that all instances are properly disposed of to release the microphone completely?
After calling the stop method, the microphone will be released.
For other parts of the code, it is recommended to obtain the stream instance returned by getUserMedia. Once it is no longer needed, iterate through the tracks and stop them to ensure proper resource cleanup.
Thanks for your help @vic.yang ,
I noticed that calling stop, destroy, and setting the object to undefined doesn’t fully release the microphone. When I remove testMicrophone and other parts that use getUserMedia, the microphone is completely released, and the icon disappears from the tab bar. However, if I keep testMicrophone, the microphone icon still appears on the tab bar, even after using the methods mentioned above. Could you please check this again? How can I fully release the microphone after using testMicrophone?
If microphoneTesterRef.current retains a previous instance of testMicrophone without clearing it (by calling the stop and destroy methods) before invoking testMicrophone again, the previous instance will continue to occupy the microphone. The following code will fix the issue:
if (!isPlayingRecording && !isRecordingVoice) {
// stop and destroy the previous instance
if (microphoneTesterRef.current && microphoneTesterRef.current?.stop) {
microphoneTesterRef.current?.stop();
microphoneTesterRef.current?.destroy();
}
microphoneTesterRef.current = localAudio.testMicrophone({
microphoneId: activeMicrophone,
speakerId: activeSpeaker,
recordAndPlay: true,
onAnalyseFrequency: (value) => {
setInputLevel(Math.min(100, value));
},
...
});
}
@vic.yang Thankyou for your help!
I tried destroying the previous microphoneTesterRef instance and stopping the localAudioInputTrack before starting. However, on the first attempt, it takes approximately 30 seconds to release instead of releasing immediately. But subsequent attempts release the resources right away. It would be great if this issue is resolved in the next release, rather than relying on workarounds like this.