title: In WebRTC, how do I label a local MediaStream so that a remote peer can identify it?
body: <p>I am building a WebRTC application in which users can share their camera and their screen.
  When a client receives a stream/track, it needs to know whether it is a camera stream or a screen recording stream.
  This distinction is obvious at the sending end,
  but the distinction is lost by the time the tracks reach the receiving peer.</p>
  <p>Here's some sample code from my application:</p>
  <pre class="lang-js prettyprint-override"><code>// Note the distinction between streams is obvious at the sending end.
  const localWebcamStream = await navigator.mediaDevices.getUserMedia({ ... });
  const screenCaptureStream = await navigator.mediaDevices.getDisplayMedia({ ... });
  
  // This is called by signalling logic
  function addLocalTracksToPeerConn(peerConn) {
    // Our approach here loses information because our two distinct streams 
    // are added to the PeerConnection's homogeneous bag of streams
  
    for (const track of screenCaptureStream.getTracks()) {
      peerConn.addTrack(track, screenCaptureStream);
    }
  
    for (const track of localWebcamStream.getTracks()) {
      peerConn.addTrack(track, localWebcamStream);
    }
  }
  
  // This is called by signalling logic
  function handleRemoteTracksFromPeerConn(peerConn) {
      peerConn.ontrack = ev =&gt; {
        const stream = ev.streams[0];
        if (stream is a camera stream) {  // FIXME how to distinguish reliably?
          remoteWebcamVideoEl.srcObject = stream;
        }
        else if (stream is a screen capture) {  // FIXME how to distinguish reliably?
          remoteScreenCaptureVideoEl.srcObject = stream;
        }
    };
  }
  </code></pre>
  <p>My ideal imaginary API would allow adding a <code>.label</code> to a track or stream, like this:</p>
  <pre class="lang-js prettyprint-override"><code>// On sending end, add arbitrary metadata
  track.label = &quot;screenCapture&quot;;
  peerConn.addTrack(track, screenCaptureStream);
  
  // On receiving end, retrieve arbitrary metadata
  peerConn.ontrack = ev =&gt; {
        const trackType = ev.track.label;  // get the label when receiving the track
  }
  </code></pre>
  <p>But this API does not really exist.
  There is <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/label" rel="nofollow noreferrer">a <code>MediaStreamTrack.label</code> property</a>,
  but it's read-only, and not preserved in transmission.
  By experimentation,
  the .label property at the sending end is informative (e.g. <code>label: &quot;FaceTime HD Camera (Built-in) (05ac:8514)&quot;</code>).
  But at the receiving end, the <code>.label</code> for the same track is is not preserved.
  (It appears to be replaced with the <code>.id</code> of the track - in Chrome, at least.)</p>
  <p><a href="https://www.kevinmoreland.com/articles/03-22-20-webrtc-mediastream-tracks" rel="nofollow noreferrer">This article by Kevin Moreland</a>
  describes the same problem,
  and recommends a mildly terrifying solution:
  munge the SDP on the sending end,
  and then grep the SDP on the receiving end.
  But this solution feels very fragile and low-level.</p>
  <p>I know there is a <code>MediaStreamTrack.id</code> property.
  There is also a <code>MediaStream.id</code> property.
  Both of these appear to be preserved in transmission.
  This means I could send the metadata in a side-channel,
  such as the signalling channel or a <code>DataChannel</code>.
  From the sending end, I would send <code>{ &quot;myStreams&quot;: { &quot;screen&quot;: &quot;&lt;some stream id&gt;&quot;, &quot;camera&quot;: &quot;&lt;another stream id&gt;&quot; } }</code>.
  The receiving end would wait until it has both the metadata and the stream before displaying anything.
  However, this approach introduces a side-channel (and inevitable concurrency challenges associated with that),
  where a side-channel feels unnecessary.</p>
  <p>I'm looking for an idiomatic, robust solution.
  How do I label/identify MediaStreams at the sending end,
  so that the receiving end knows which stream is which?</p>