5.4 RTCRtpTransceiver Interface

The RTCRtpTransceiver interface represents a combination of an RTCRtpSender and an RTCRtpReceiver that share a common media stream “identification-tag”. As defined in [RFC8829] (section 3.4.1.), an RTCRtpTransceiver is said to be associated with a media description if its “mid” property is non-null and matches a media stream “identification-tag” in the media description; otherwise it is said to be disassociated with that media description.

Note

A RTCRtpTransceiver may become associated with a new pending description in RFC8829 while still being disassociated with the current description. This may happen in check if negotiation is needed.

The transceiver kind of an RTCRtpTransceiver is defined by the kind of the associated RTCRtpReceiver‘s MediaStreamTrack object.

To create an RTCRtpTransceiver with an RTCRtpReceiver object, receiver, RTCRtpSender object, sender, and an RTCRtpTransceiverDirection value, direction, run the following steps:

  1. Let transceiver be a new RTCRtpTransceiver object.

  2. Let transceiver have a [[Sender]] internal slot, initialized to sender.

  3. Let transceiver have a [[Receiver]] internal slot, initialized to receiver.

  4. Let transceiver have a [[Stopping]] internal slot, initialized to false.

  5. Let transceiver have a [[Stopped]] internal slot, initialized to false.

  6. Let transceiver have a [[Direction]] internal slot, initialized to direction.

  7. Let transceiver have a [[Receptive]] internal slot, initialized to false.

  8. Let transceiver have a [[CurrentDirection]] internal slot, initialized to null.

  9. Let transceiver have a [[FiredDirection]] internal slot, initialized to null.

  10. Let transceiver have a [[PreferredCodecs]] internal slot, initialized to an empty list.

  11. Let transceiver have a [[JsepMid]] internal slot, initialized to null. This is the “RtpTransceiver mid property” defined in [RFC8829] (section 5.2.1. and section 5.3.1.), and is only modified there.

  12. Let transceiver have a [[Mid]] internal slot, initialized to null.

  13. Return transceiver.

Note

Creating a transceiver does not create the underlying RTCDtlsTransport and RTCIceTransport objects. This will only occur as part of the process of setting a session description.

  1. WebIDL[Exposed=Window]
  2. interface RTCRtpTransceiver {
  3. readonly attribute DOMString? mid;
  4. [SameObject] readonly attribute RTCRtpSender sender;
  5. [SameObject] readonly attribute RTCRtpReceiver receiver;
  6. attribute RTCRtpTransceiverDirection direction;
  7. readonly attribute RTCRtpTransceiverDirection? currentDirection;
  8. undefined stop();
  9. undefined setCodecPreferences(sequence<RTCRtpCodecCapability> codecs);
  10. };

Attributes

mid of type DOMString, readonly, nullable

The mid attribute is the media stream “identification-tag” negotiated and present in the local and remote descriptions. On getting, the attribute MUST return the value of the [[Mid]] slot.

sender of type RTCRtpSender, readonly

The sender attribute exposes the RTCRtpSender corresponding to the RTP media that may be sent with mid = [[Mid]]. On getting, the attribute MUST return the value of the [[Sender]] slot.

receiver of type RTCRtpReceiver, readonly

The receiver attribute is the RTCRtpReceiver corresponding to the RTP media that may be received with mid = [[Mid]]. On getting the attribute MUST return the value of the [[Receiver]] slot.

direction of type RTCRtpTransceiverDirection

As defined in [RFC8829] (section 4.2.4.), the direction attribute indicates the preferred direction of this transceiver, which will be used in calls to createOffer and createAnswer. An update of directionality does not take effect immediately. Instead, future calls to createOffer and createAnswer mark the corresponding media description as sendrecv, sendonly, recvonly or inactive as defined in [RFC8829] (section 5.2.2. and section 5.3.2.)

On getting, the user agent MUST run the following steps:

  1. Let transceiver be the RTCRtpTransceiver object on which the getter is invoked.

  2. If transceiver.[[Stopping]] is true, return “stopped“.

  3. Otherwise, return the value of the [[Direction]] slot.

On setting, the user agent MUST run the following steps:

  1. Let transceiver be the RTCRtpTransceiver object on which the setter is invoked.

  2. Let connection be the RTCPeerConnection object associated with transceiver.

  3. If transceiver.[[Stopping]] is true, throw an InvalidStateError.

  4. Let newDirection be the argument to the setter.

  5. If newDirection is equal to transceiver.[[Direction]], abort these steps.

  6. If newDirection is equal to “stopped“, throw a TypeError.

  7. Set transceiver.[[Direction]] to newDirection.

  8. Update the negotiation-needed flag for connection.

currentDirection of type RTCRtpTransceiverDirection, readonly, nullable

As defined in [RFC8829] (section 4.2.5.), the currentDirection attribute indicates the current direction negotiated for this transceiver. The value of currentDirection is independent of the value of RTCRtpEncodingParameters.active since one cannot be deduced from the other. If this transceiver has never been represented in an offer/answer exchange, the value is null. If the transceiver is stopped, the value is “stopped“.

On getting, the user agent MUST run the following steps:

  1. Let transceiver be the RTCRtpTransceiver object on which the getter is invoked.

  2. If transceiver.[[Stopped]] is true, return “stopped“.

  3. Otherwise, return the value of the [[CurrentDirection]] slot.

Methods

stop

Irreversibly marks the transceiver as stopping, unless it is already stopped. This will immediately cause the transceiver’s sender to no longer send, and its receiver to no longer receive. Calling stop() also updates the negotiation-needed flag for the RTCRtpTransceiver‘s associated RTCPeerConnection.

A stopping transceiver will cause future calls to createOffer to generate a zero port in the media description for the corresponding transceiver, as defined in [RFC8829] (section 4.2.1.) (The user agent MUST treat a stopping transceiver as stopped for the purposes of RFC8829 only in this case). However, to avoid problems with [RFC8843], a transceiver that is stopping, but not stopped, will not affect createAnswer.

A stopped transceiver will cause future calls to createOffer or createAnswer to generate a zero port in the media description for the corresponding transceiver, as defined in [RFC8829] (section 4.2.1.).

The transceiver will remain in the stopping state, unless it becomes stopped by setRemoteDescription processing a rejected m-line in a remote offer or answer.

Note

A transceiver that is stopping but not stopped will always need negotiation. In practice, this means that calling stop() on a transceiver will cause the transceiver to become stopped eventually, provided negotiation is allowed to complete on both ends.

When the stop method is invoked, the user agent MUST run the following steps:

  1. Let transceiver be the RTCRtpTransceiver object on which the method is invoked.

  2. Let connection be the RTCPeerConnection object associated with transceiver.

  3. If connection.[[IsClosed]] is true, throw an InvalidStateError.

  4. If transceiver.[[Stopping]] is true, abort these steps.

  5. Stop sending and receiving with transceiver.

  6. Update the negotiation-needed flag for connection.

The stop sending and receiving algorithm given a transceiver and, optionally, a disappear boolean defaulting to false, is as follows:

  1. Let sender be transceiver.[[Sender]].

  2. Let receiver be transceiver.[[Receiver]].

  3. Stop sending media with sender.

  4. Send an RTCP BYE for each RTP stream that was being sent by sender, as specified in [RFC3550].

  5. Stop receiving media with receiver.

  6. If disappear is false, execute the steps for receiver.[[ReceiverTrack]] to be ended. This fires an event.

  7. Set transceiver.[[Direction]] to “inactive“.

  8. Set transceiver.[[Stopping]] to true.

The stop the RTCRtpTransceiver algorithm given a transceiver and, optionally, a disappear boolean defaulting to false, is as follows:

  1. If transceiver.[[Stopping]] is false, stop sending and receiving with transceiver and disappear.

  2. Set transceiver.[[Stopped]] to true.

  3. Set transceiver.[[Receptive]] to false.

  4. Set transceiver.[[CurrentDirection]] to null.

setCodecPreferences

The setCodecPreferences method overrides the default codec preferences used by the user agent. When generating a session description using either createOffer or createAnswer, the user agent MUST use the indicated codecs, in the order specified in the codecs argument, for the media section corresponding to this RTCRtpTransceiver.

This method allows applications to disable the negotiation of specific codecs (including RTX/RED/FEC). It also allows an application to cause a remote peer to prefer the codec that appears first in the list for sending.

Codec preferences remain in effect for all calls to createOffer and createAnswer that include this RTCRtpTransceiver until this method is called again. Setting codecs to an empty sequence resets codec preferences to any default value.

Note

Codecs have their payload types listed under each m= section in the SDP, defining the mapping between payload types and codecs. These payload types are referenced by the m=video or m=audio lines in the order of preference, and codecs that are not negotiated do not appear in this list as defined in section 5.2.1 of [RFC8829]. A previously negotiated codec that is subsequently removed disappears from the m=video or m=audio line, and while its codec payload type is not to be reused in future offers or answers, its payload type may also be removed from the mapping of payload types in the SDP.

The codecs sequence passed into setCodecPreferences can only contain codecs that are returned by RTCRtpSender.getCapabilities(kind) or RTCRtpReceiver.getCapabilities(kind), where kind is the kind of the RTCRtpTransceiver on which the method is called. Additionally, the RTCRtpCodecCapability dictionary members cannot be modified. If codecs does not fulfill these requirements, the user agent MUST throw an InvalidModificationError.

Note

Due to a recommendation in [SDP], calls to createAnswer SHOULD use only the common subset of the codec preferences and the codecs that appear in the offer. For example, if codec preferences are “C, B, A”, but only codecs “A, B” were offered, the answer should only contain codecs “B, A”. However, [RFC8829] (section 5.3.1.) allows adding codecs that were not in the offer, so implementations can behave differently.

When setCodecPreferences() in invoked, the user agent MUST run the following steps:

  1. Let transceiver be the RTCRtpTransceiver object this method was invoked on.

  2. Let codecs be the first argument.

  3. If codecs is an empty list, set transceiver.[[PreferredCodecs]] to codecs and abort these steps.

  4. Remove any duplicate values in codecs. Start at the back of the list such that the priority of the codecs is maintained; the index of the first occurrence of a codec within the list is the same before and after this step.

  5. Let kind be the transceiver’s transceiver kind.

  6. If the intersection between codecs and RTCRtpSender.getCapabilities(kind).codecs or the intersection between codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX, RED or FEC codecs or is an empty set, throw InvalidModificationError. This ensures that we always have something to offer, regardless of transceiver.direction.

  7. Let codecCapabilities be the union of RTCRtpSender.getCapabilities(kind).codecs and RTCRtpReceiver.getCapabilities(kind).codecs.

  8. For each codec in codecs,

    1. If codec is not in codecCapabilities, throw InvalidModificationError.
  9. Set transceiver.[[PreferredCodecs]] to codecs.

Note

If set, the offerer’s codec preferences will decide the order of the codecs in the offer. If the answerer does not have any codec preferences then the same order will be used in the answer. However, if the answerer also has codec preferences, these preferences override the order in the answer. In this case, the offerer’s preferences would affect which codecs were on offer but not the final order.

5.4.1 Simulcast functionality

Simulcast functionality is provided via the addTransceiver method of the RTCPeerConnection object and the setParameters method of the RTCRtpSender object.

The addTransceiver method establishes the simulcast envelope which includes the maximum number of simulcast streams that can be sent, as well as the ordering of the encodings. While characteristics of individual simulcast streams can be modified using the setParameters method, the simulcast envelope cannot be changed. One of the implications of this model is that the addTrack() method cannot provide simulcast functionality since it does not take sendEncodings as an argument, and therefore cannot configure an RTCRtpTransceiver to send simulcast.

Another implication is that the answerer cannot set the simulcast envelope directly. Upon calling the setRemoteDescription method of the RTCPeerConnection object, the simulcast envelope is configured on the RTCRtpTransceiver to contain the layers described by the specified session description. Once the envelope is determined, layers cannot be removed. They can be marked as inactive by setting the active member to false effectively disabling the layer.

While setParameters cannot modify the simulcast envelope, it is still possible to control the number of streams that are sent and the characteristics of those streams. Using setParameters, simulcast streams can be made inactive by setting the active member to false, or can be reactivated by setting the active member to true. Using setParameters, stream characteristics can be changed by modifying attributes such as maxBitrate.

Note

Simulcast is frequently used to send multiple encodings to an SFU, which will then forward one of the simulcast streams to the end user. The user agent is therefore expected to allocate bandwidth between encodings in such a way that all simulcast streams are usable on their own; for instance, if two simulcast streams have the same maxBitrate, one would expect to see a similar bitrate on both streams. If bandwidth does not permit all simulcast streams to be sent in an usable form, the user agent is expected to stop sending some of the simulcast streams.

As defined in [RFC8829] (section 3.7.), an offer from a user-agent will only contain a “send” description and no “recv” description on the a=simulcast line. Alternatives and restrictions (described in [RFC8853]) are not supported.

This specification does not define how to configure reception of multiple RTP encodings using createOffer, createAnswer or addTransceiver. However when setRemoteDescription is called with a corresponding remote description that is able to send multiple RTP encodings as defined in [RFC8829], and the browser supports receiving multiple RTP encodings, the RTCRtpReceiver may receive multiple RTP encodings and the parameters retrieved via the transceiver’s receiver.getParameters() will reflect the encodings negotiated.

Note

An RTCRtpReceiver can receive multiple RTP streams in a scenario where a Selective Forwarding Unit (SFU) switches between simulcast streams it receives from user agents. If the SFU does not rewrite RTP headers so as to arrange the switched streams into a single RTP stream prior to forwarding, the RTCRtpReceiver will receive packets from distinct RTP streams, each with their own SSRC and sequence number space. While the SFU may only forward a single RTP stream at any given time, packets from multiple RTP streams can become intermingled at the receiver due to reordering. An RTCRtpReceiver equipped to receive multiple RTP streams will therefore need to be able to correctly order the received packets, recognize potential loss events and react to them. Correct operation in this scenario is non-trivial and therefore is optional for implementations of this specification.

5.4.1.1 Encoding Parameter Examples

This section is non-normative.

Examples of simulcast scenarios implemented with encoding parameters:

Example 3

  1. // Example of 3-layer spatial simulcast with all but the lowest resolution layer disabled
  2. var encodings = [
  3. {rid: 'q', active: true, scaleResolutionDownBy: 4.0}
  4. {rid: 'h', active: false, scaleResolutionDownBy: 2.0},
  5. {rid: 'f', active: false},
  6. ];

5.4.2 “Hold” functionality

This section is non-normative.

Together, the direction attribute and the replaceTrack method enable developers to implement “hold” scenarios.

To send music to a peer and cease rendering received audio (music-on-hold):

Example 4

  1. async function playMusicOnHold() {
  2. try {
  3. // Assume we have an audio transceiver and a music track named musicTrack
  4. await audio.sender.replaceTrack(musicTrack);
  5. // Mute received audio
  6. audio.receiver.track.enabled = false;
  7. // Set the direction to send-only (requires negotiation)
  8. audio.direction = 'sendonly';
  9. } catch (err) {
  10. console.error(err);
  11. }
  12. }

To respond to a remote peer’s “sendonly” offer:

Example 5

  1. async function handleSendonlyOffer() {
  2. try {
  3. // Apply the sendonly offer first,
  4. // to ensure the receiver is ready for ICE candidates.
  5. await pc.setRemoteDescription(sendonlyOffer);
  6. // Stop sending audio
  7. await audio.sender.replaceTrack(null);
  8. // Align our direction to avoid further negotiation
  9. audio.direction = 'recvonly';
  10. // Call createAnswer and send a recvonly answer
  11. await doAnswer();
  12. } catch (err) {
  13. // handle signaling error
  14. }
  15. }

To stop sending music and send audio captured from a microphone, as well to render received audio:

Example 6

  1. async function stopOnHoldMusic() {
  2. // Assume we have an audio transceiver and a microphone track named micTrack
  3. await audio.sender.replaceTrack(micTrack);
  4. // Unmute received audio
  5. audio.receiver.track.enabled = true;
  6. // Set the direction to sendrecv (requires negotiation)
  7. audio.direction = 'sendrecv';
  8. }

To respond to being taken off hold by a remote peer:

Example 7

  1. async function onOffHold() {
  2. try {
  3. // Apply the sendrecv offer first, to ensure receiver is ready for ICE candidates.
  4. await pc.setRemoteDescription(sendrecvOffer);
  5. // Start sending audio
  6. await audio.sender.replaceTrack(micTrack);
  7. // Set the direction sendrecv (just in time for the answer)
  8. audio.direction = 'sendrecv';
  9. // Call createAnswer and send a sendrecv answer
  10. await doAnswer();
  11. } catch (err) {
  12. // handle signaling error
  13. }
  14. }