Skip to content

fix: re-acquire mic track when effects require specific audio constraints#99

Open
antsukanova wants to merge 4 commits intomainfrom
antsukan/agc-fix
Open

fix: re-acquire mic track when effects require specific audio constraints#99
antsukanova wants to merge 4 commits intomainfrom
antsukan/agc-fix

Conversation

@antsukanova
Copy link
Copy Markdown
Contributor

Summary

Adds a handleConstraintsRequired handler in LocalStream.addEffect() that listens for ConstraintsRequired events from effects (e.g. web-media-effects noise reduction). When an effect needs specific audio processing properties on the microphone track, the handler re-acquires the track via getUserMedia() since applyConstraints() is silently ignored by Chrome for audio constraints. Original track settings are saved and restored when the effect emits empty constraints on disable/dispose.

What's changed

  • Constraint-driven track re-acquisition — Listens for constraints-required events on effects. Non-empty constraints trigger getUserMedia with the requested values merged over current settings. Empty constraints ({}) restore the saved originals.
  • Save/restore mechanism — Before applying effect constraints, the current values of affected properties are saved. On restore, saved values are applied and cleared. Duplicate restores and already-satisfied constraints are skipped.
  • Track replacement ordering — Track event handlers are removed before oldTrack.stop() to prevent spurious ended events. The old track is stopped before getUserMedia to force Chrome to create a fresh audio pipeline (required for independent AEC/AGC/NS control).
  • Constraint merginggetUserMedia is called with { ...oldSettings, ...constraintsToApply, deviceId: { exact } } to preserve the current device and non-affected settings while applying the requested constraints.
  • Cleanup on dispose — The constraints-required listener is unregistered when the effect is disposed.

Testing

  • Enable OFMV on a meeting/stream — verify autoGainControl: false, noiseSuppression: false, echoCancellation: true in logs after re-acquisition
  • Disable OFMV — verify saved constraints restored (AGC/NS back to original values)
  • Toggle OFMV multiple times — no duplicate listeners, no stale track references
  • BNR enable/disable — no constraint re-acquisition triggered

@antsukanova antsukanova changed the title fix: add handleConstraintsRequired fix: re-acquire mic track when effects require specific audio constraints Apr 3, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e903658ce5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 54f77fd9d6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0769169e4f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +369 to +372
newTrack.enabled = wasEnabled;
this.inputStream.removeTrack(oldTrack);
this.inputStream.addTrack(newTrack);
this.addTrackHandlers(newTrack);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Ignore stale re-acquire results before swapping tracks

handleConstraintsRequired is async and can be invoked again before a previous getUserMedia call finishes, but this block always applies whichever request resolves last without checking whether a newer constraints event already superseded it. In practice, quick enable/disable or model-switch emissions can leave the stream on outdated constraints because an older in-flight request still replaces inputTrack and re-wires effects after a newer request was processed. Add request sequencing (or a mutex) and discard late completions before mutating stream/effect state.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

@bbaldino bbaldino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple comments. Some impressive catches by codex as well 👀

* emits empty constraints (disable / dispose / model switch to one with no
* special requirements).
*/
let savedConstraints: Record<string, MediaTrackConstraints[keyof MediaTrackConstraints]> = {};
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have the possibility of multiple "layers" of saving constraints? Or currently can there only ever be one? I.e.: we have some constraints, a single thing can change them, and then the only other possible transition would be going back to those original constraints?

Comment on lines +285 to +286
* Empty constraints ({}): restore the previously saved values so the track
* returns to the user's original settings.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity: did you consider emitting different events for when new constraints are required and when they're no longer required (as opposed to overloading the value of the constraints parameter here)? It seems like it would simplify the logic below a decent amount.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants