Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Applying constraints to an audio track from getUserMedia

Is it possible to apply constraints to a running live audio track? It doesn't seem to work for me, at least on Chrome v80.

Suppose I have a stream:

const stream = await navigator.mediaDevices.getUserMedia({
  audio: {
    autoGainControl: true
    channelCount: 2
    echoCancellation: true
    noiseSuppression: true
  },
  video: false
});

Now, later on I want to change some of those parameters:

for (const track of stream.getAudioTracks()) {
  track.applyConstraints({
    autoGainControl: false,
    echoCancellation: false,
    noiseSuppression: false
  });
}

This has no effect. If I call track.getConstraints(), I see my new constraints but audibly they have no effect until I reload the page and apply them from the beginning. Additionally, when I call track.getSettings(), I see that my new constraints haven't been applied.

I have also tried calling track.enabled = false before applying the constraints, with track.enabled = true afterwards, with no luck.

Any advice on how to get this to work without making a fresh call to getUserMedia()?

like image 900
Brad Avatar asked Mar 02 '23 15:03

Brad


1 Answers

SO user jib, which works on Firefox and adapter.js projects wrote a blog post in 2017 about this exact feature.

Here is how they did apply the constraints to the track:

async function apply(c) {
  await track.applyConstraints(Object.assign(track.getSettings(), c));
  update();
}

c is an object with the particular constraints to add.

They do it this way because all the properties that are omitted when passing the MediaTrackConstraints dictionary will get reset to their defaults when applied.

Now, your solution should have worked too for the properties you did set.


So using this fiddle I did try the few UAs I have on my macOS machine:

Chrome

As you reported, settings are not applied.

Here is the issue tracking the upcoming implementation.

From this issue's comments you can also find a workaround which implies requesting a new MediaStream from the same deviceId as the one you got, and applying the desired constraints.

Here is a fork of jib's fiddle with such a workaround. Note that the deviceId is gotten from track.getSettings()

async function apply(c) {
  track.stop(); // required
  const new_constraints = Object.assign(track.getSettings(), c, );
  const new_stream = await gUM({ audio: new_constraints });

  updateSpectrum( audio.srcObject = new_stream );
  track = new_stream.getAudioTracks()[0];
  update();
}

Firefox

Works seamlessly.

Safari

Badly crashes. On my machine, running the original fiddle, with only the tweak of the spectrum will completely crash the gUM of the whole browser. - The current stream is stopped - Any attempt to get a new stream fails - until reboot of the whole app.

The forked fiddle we made for Chrome at least doesn't crash, but it doesn't seem to produce any audible change either...

like image 128
Kaiido Avatar answered Mar 05 '23 17:03

Kaiido