Skip to content

feat: add advanced call audio controls and level meter (#503) - #512

Open
rohit-khaire wants to merge 1 commit into
muke1908:masterfrom
rohit-khaire:feature/advanced-audio-controls
Open

rohit-khaire wants to merge 1 commit into
muke1908:masterfrom
rohit-khaire:feature/advanced-audio-controls

Conversation

@rohit-khaire

Copy link
Copy Markdown

Overview

This PR adds advanced call audio controls and diagnostic metrics to the SDK, enabling applications to build a fully functional call UI with mute controls, device pickers, and audio level meters.

It also introduces best practices for WebRTC media-track lifecycle management, resource cleanup, optional browser APIs, and graceful degradation.


Changes Implemented

  1. Mute / Unmute Controls:

    • Added mute(), unmute(), and setMuted(boolean) methods.
    • Exposes current state via the muted getter.
    • Uses MediaStreamTrack.enabled = false/true without stopping the active track.
  2. Input Device Switching:

    • Implemented switchInputDevice(deviceId: string) using navigator.mediaDevices.getUserMedia().
    • Uses RTCRtpSender.replaceTrack() without renegotiating the peer connection.
    • Stops old tracks after successful replacement.
    • Preserves the active mute state across device switches.
    • Cleans up newly acquired tracks when replacement fails.
  3. Output Device Selection:

    • Implemented setOutputDevice(deviceId: string) using HTMLMediaElement.setSinkId().
    • Gracefully handles unsupported browsers, unavailable devices, permission failures, and secure-context restrictions without detaching playback.
  4. Audio Level Meter & Diagnostics:

    • Added local RMS audio-level metering using AudioContext, MediaStreamSource, and AnalyserNode.
    • Exposed optional localAudioLevel through getStatsSnapshot().
    • Exposed optional remoteAudioLevel when supported by WebRTC inbound RTP statistics.
    • Fails safely when Web Audio or WebRTC stats APIs are unavailable.
  5. Lifecycle & Cleanup:

    • Stops active media tracks during call termination.
    • Closes and disconnects audio-meter resources.
    • Detaches and removes remote audio elements.
    • Clears peer event handlers to prevent dangling references.
    • Makes cleanup idempotent.

Acceptance Criteria Checklist

  • Active calls expose mute/unmute/setMuted APIs.
  • Active calls expose current mute state via muted.
  • Active calls can switch input microphone devices.
  • Input switching uses replaceTrack() where possible.
  • Old input tracks are stopped after switching.
  • Active calls can select output devices where browser support exists through setSinkId.
  • Audio levels are available through getStatsSnapshot().
  • Tests cover mute, unmute, input switching, output switching, level metering, failure paths, and cleanup.
  • Documentation explains media-track lifecycle and browser support caveats.

Testing Details

  • Verified mute, unmute, and idempotent setMuted() behavior.
  • Tested microphone switching, mute preservation, replacement success, and failure cleanup.
  • Tested setSinkId() support, unsupported-browser handling, and permission failures.
  • Verified local RMS and optional remote audio-level metrics.
  • Verified call termination stops tracks, closes audio contexts, removes audio elements, and clears handlers.
  • Full test suite passed: 16 suites, 178 tests.
  • Service production build passed.

Resolves #503

@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
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.

Advanced Audio Controls

1 participant