Search code examples
javascriptwebrtcpeerjsmediastreammediastreamtrack

WebRTC: Peers Receive MediaStreamTrack with enabled Property as True Despite Being Set to False Locally and Confirmed


I'm developing a WebRTC application using JavaScript, where I programmatically disable video and audio tracks (MediaStreamTrack.enabled = false) before sending them to peers. Despite setting the enabled property of tracks to false locally and confirming the state post-replacement, the receiving peers always get the track with enabled set to true. I'm using the replaceTrack method to update tracks in an ongoing RTCPeerConnection. Here's a simplified version of my code:

const replacePartyAvStreamTracks = (
newStream: MediaStream,
currentPartyAvCalls: Map<string, MediaConnection>,
 ) => {
   currentPartyAvCalls.forEach((call) => {
     const peerConnection = call.peerConnection;
  const audioTrack = newStream.getAudioTracks()[0] || null;
  const videoTrack = newStream.getVideoTracks()[0] || null;
  if (!peerConnection.getSenders()) return;
  peerConnection.getSenders().forEach((sender) => {
    if (!sender.track) return;

    let newTrack: MediaStreamTrack | null = null;
    if (sender.track.kind === 'audio') {
      newTrack = audioTrack;
      newTrack.enabled = false;
    } else if (sender.track.kind === 'video') {
      newTrack = videoTrack;
      newTrack.enabled = false;
    }

    if (newTrack !== null) {
      sender
        .replaceTrack(newTrack)
        .then(() => {
          console.log('Track replaced and disabled', newTrack!.enabled);
        })
        .catch((err) => {
          console.error(`Error replacing ${sender.track!.kind} track:`, err);
        });
    } else {
      console.log(`No new ${sender.track.kind} track available to replace.`);
    }
  });
});

};

Despite the console log confirming the track is disabled (false) after replacement, the receiving peers always interpret the track as enabled (true).

Questions:

  • Is there any known issue or limitation with the enabled property of MediaStreamTrack when using replaceTrack in WebRTC that could cause this behavior?
  • How can the disabled state of a track be reliably transmitted to the receiving peers in a WebRTC connection?
  • Are there any additional steps or workarounds to ensure the enabled state of a track is correctly synchronized between sending and receiving peers?

Additional Context:

  • The issue occurs across multiple browsers.

  • The enabled property is confirmed to be false immediately after the replaceTrack operation, as indicated by the console log.

  • Other aspects of the signaling and track replacement process work as expected, only the synchronization of the enabled state poses an issue.

  • I am using the PeerJS package as a dependancy, in case this is a known issue of the package. Looking through their documentation, discussions, and git issues, I have not yet identified the package to be the problem.

I'm looking for insights or suggestions on how to ensure the enabled state of tracks is correctly handled and transmitted in WebRTC peer connections. Thank you for any help!


Solution

  • This is expected, there is nothing in the underyling RTP/RTCP protocols that transmits this "enabled" or synchronized its state. You will need to send a "I enabled/disabled this track" notification either over the signaling channel or a datachannel (same for the initial state).

    If you look at the specification this is also expected: https://www.w3.org/TR/mediacapture-streams/#life-cycle setting enabled to false sends blackness or silence but does send something.