RTCPeerConnection.addTrack()

The RTCPeerConnection method addTrack() adds a new media track to the set of tracks which will be transmitted to the other peer.

Note: Adding a track to a connection triggers renegotiation by firing an negotiationneeded event.

Syntax

rtpSender = RTCPeerConnection.addTrack(track, stream...);

Parameters

track
A MediaStreamTrack object representing the media track to add to the peer connection.
stream...
One or more MediaStream objects in which the specified track are to be contained.

The specified track doesn't necessarily have to already be part of any of the specified streams. Instead, the streams are simply a way to group tracks together on the receiving end of the connection, making sure they are synchronized.

Return value

The RTCRtpSender object which will be used to transmit the media data.

Note: Every RTCRtpSender is paired with an RTCRtpReceiver to make up an RTCRtpTransceiver. The associated receiver is muted (indicating that it is not able to deliver packets) until and unless one or more streams are added to the receiver by the remote peer.

Reused senders

This method may return either a new RTCRtpSender or, under very specific circumstances, an existing compatible sender which has not yet been used to transmit data. Compatible reusable RTCRtpSender instances meet these criteria:

  • There is no track already associated with the sender.
  • The RTCRtpTransceiver associated with the sender has a RTCRtpReceiver whose track property specifies a MediaStreamTrack whose kind is the same as the kind of the track parameter specified when calling RTCPeerConnection.addTrack(). This ensures that a transceiver only handles audio or video and never both.
  • The RTCRtpTransceiver's stopped property is false.
  • The RTCRtpSender being considered has never been used to send data. If the transceiver's currentDirection has ever been "sendrecv" or "sendonly", the sender can't be reused.

If all of those criteria are met, the sender gets reused, which results in these changes occurring to the existing RTCRtpSender and its RTCRtpTransceiver:

  • The RTCRtpSender's track is set to the specified track.
  • The sender's set of associated streams is set to the list of streams passed into this method, stream....
  • The associated RTCRtpTransceiver has its currentDirection updated to include sending; if its current value is "recvonly", it becomes "sendrecv", and if its current value is "inactive", it becomes "sendonly".

New senders

If no existing sender exists that can be reused, a new one is created. This also results in the creation of the associated objects that must exist. The process of creating a new sender results in these changes:

  • The new RTCRtpSender is created with the specified track and set of stream(s).
  • A new RTCRtpReceiver is created with a new MediaStreamTrack as its track property (not the track specified as a parameter when calling addTrack()). This track's kind is set to match the kind of the track provided as an input parameter.
  • A new RTCRtpTransceiver is created and associated with the new sender and receiver.
  • The new transceiver's direction is set to "sendrecv".
  • The new transceiver is added to the RTCPeerConnection's set of transceivers.

Exceptions

InvalidAccessError
The specified track (or all of its underlying streams) is already part of the RTCPeerConnection.
InvalidStateError
The RTCPeerConnection is closed.

Example

This example is drawn from the code presented in the article Signaling and video calling and its corresponding sample code. It comes from the handleVideoOfferMsg() method there, which is called when an offer message is received from the remote peer.

var mediaConstraints = {
  audio: true,            // We want an audio track
  video: true             // ...and we want a video track
};

var desc = new RTCSessionDescription(sdp);

pc.setRemoteDescription(desc).then(function () {
  return navigator.mediaDevices.getUserMedia(mediaConstraints);
})
.then(function(stream) {
  previewElement.srcObject = stream;

  stream.getTracks().forEach(track => pc.addTrack(track, stream));
})

This code takes SDP which has been received from the remote peer and constructs a new RTCSessionDescription to pass into setRemoteDescription(). Once that succeeds, it uses MediaDevices.getUserMedia() to obtain access to the local webcam and microphone.

If that succeeds, the resulting stream is assigned as the source for a <video> element which is referenced by the variable previewElement.

The final step is to begin sending the local video across the peer connection to the caller. This is done by adding each track in the stream by iterating over the list returned by MediaStream.getTracks() and passing them to addTrack() along with the stream which they're a component of.

Specifications

Specification Status Comment
WebRTC 1.0: Real-time Communication Between Browsers
The definition of 'RTCPeerConnection.addTrack()' in that specification.
Candidate Recommendation Initial specification.

Browser compatibility

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support No support 45 (45) [1][2] ? ? ?
Feature Android Webview Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support No support No support 45 (45)[2] ? ? ?

[1] Prior to Firefox 49, the specified track was required to be component of all passed MediaStreams. Starting in Firefox 49, this is no longer the case. See bug 1271669 for specifics.

[2] Firefox did not support or implement RTCRtpTransceiver or the RTCPeerConnection.addTransceiver() method until Firefox 59. Before that, there was no direct association between senders and receivers.

See also

Document Tags and Contributors

 Contributors to this page: Sheppy, jpmedley, Jib
 Last updated by: Sheppy,