WebRTC: 브라우저에서의 실시간 통신

W3C 권고안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2025/REC-webrtc-20250313/
최신 공개 버전:
https://www.w3.org/TR/webrtc/
최신 편집자 초안:
https://w3c.github.io/webrtc-pc/
이력:
https://www.w3.org/standards/history/webrtc/
커밋 이력
테스트 스위트:
https://github.com/web-platform-tests/wpt/tree/master/webrtc/
구현 보고서:
https://w3c.github.io/webrtc-interop-reports/webrtc-pc-report.html
편집자:
Cullen Jennings (Cisco)
Florent Castelli (Google)
Henrik Boström (Google)
Jan-Ivar Bruaroey (Mozilla)
이전 편집자:
Adam Bergkvist (Ericsson) - 까지
Daniel C. Burnett (초빙 전문가) - 까지
Anant Narayanan (Mozilla) - 까지
Bernard Aboba (Microsoft Corporation) - 까지
Taylor Brandstetter (Google) - 까지
피드백:
GitHub w3c/webrtc-pc (풀 리퀘스트, 새 이슈, 미해결 이슈)
public-webrtc@w3.org 제목 줄에 [webrtc] … 메시지 주제 … 사용 (보관함)
참여
메일링 리스트

다음도 참조하십시오: 번역.


초록

이 문서는 미디어 및 일반 애플리케이션 데이터를 적절한 실시간 프로토콜 집합을 구현하는 다른 브라우저 또는 장치로 보내고 받을 수 있도록 WebIDL로 작성된 ECMAScript API 집합을 정의한다. 이 명세는 IETF RTCWEB 그룹에서 개발한 프로토콜 명세 및 로컬 미디어 장치에 접근하기 위한 API 명세와 함께 개발되고 있다.

이 문서의 상태

이 절에서는 이 문서가 발행된 시점의 상태를 설명한다. 현재 W3C 간행물 목록과 이 기술 보고서의 최신 개정판은 https://www.w3.org/TR/의 W3C 기술 보고서 색인에서 확인할 수 있다.

이 문서에는 후보 수정안이 포함되어 있다.

이 문서의 관련 테스트 스위트는 API가 권고안으로 처음 발행될 당시의 구현 보고서를 작성하는 데 사용되었다. 그 이후 식별된 제안 수정안과 후보 수정안을 통합하도록 이 테스트 스위트가 업데이트되었으며, 이러한 수정안의 구현 상태에 중점을 둔 업데이트된 구현 보고서는 두 개의 구현이 있는 기능을 제안 수정안으로 선택하는 데 사용되었고, 이제 이 권고안 버전에 완전히 통합되었다.

이 문서는 웹 실시간 통신 워킹 그룹에서 권고안 트랙을 사용하여 권고안으로 발행했다. 이 문서에는 이전 권고안 이후의 실질적인 변경 사항과 새로운 기능을 도입하는 후보 수정안이 포함되어 있다.

W3C는 이 명세를 웹의 표준으로 널리 배포할 것을 권고한다.

W3C 권고안은 광범위한 합의 형성 후 W3C와 그 회원들이 승인하고, 워킹 그룹 회원들이 구현에 대한 로열티 없는 라이선스를 약속한 명세이다. 이 권고안의 향후 업데이트에는 새로운 기능이 포함될 수 있다.

후보 추가 사항은 문서에 표시되어 있다.

후보 수정 사항은 문서에 표시되어 있다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했다. W3C는 이 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지한다. 해당 페이지에는 특허 공개 지침도 포함되어 있다. 자신이 실제로 알고 있는 특허에 필수 청구항이 포함되어 있다고 믿는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 한다.

이 문서는 2023년 11월 3일 W3C 프로세스 문서의 적용을 받는다.

1. 소개

이 절은 비규범적이다.

이 명세에서는 HTML의 피어 투 피어 통신 및 화상 회의와 관련된 다음과 같은 여러 측면을 다룬다.

이 문서는 이러한 기능에 사용되는 API를 정의한다. 이 명세는 IETF RTCWEB 그룹에서 개발한 프로토콜 명세 및 WebRTC 워킹 그룹에서 개발한 로컬 미디어 장치에 접근하기 위한 API 명세 [GETUSERMEDIA]와 함께 개발되고 있다. 시스템에 대한 개요는 [RFC8825] 및 [RFC8826]에서 확인할 수 있다.

2. 적합성

비규범적이라고 표시된 절뿐만 아니라 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적이다. 이 명세의 그 밖의 모든 내용은 규범적이다.

이 문서에서 할 수 있다, 해야 한다, 해서는 안 된다하는 것이 좋다라는 핵심어는 여기에 표시된 것처럼 모두 대문자로 나타나는 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 한다.

이 명세는 하나의 제품, 즉 이 명세에 포함된 인터페이스를 구현하는 사용자 에이전트에 적용되는 적합성 기준을 정의한다.

알고리즘이나 특정 단계로 표현된 적합성 요구 사항은 최종 결과가 동등하다면 어떤 방식으로든 구현할 수 있다. (특히 이 명세에서 정의하는 알고리즘은 쉽게 따라갈 수 있도록 작성되었으며, 성능 향상을 목적으로 하지 않는다.)

ECMAScript를 사용하여 이 명세에서 정의한 API를 구현하는 구현은 Web IDL 명세 [WEBIDL]에서 정의한 ECMAScript 바인딩과 일관된 방식으로 이를 구현해야 한다. 이 명세에서는 해당 명세와 용어를 사용하기 때문이다.

3. 용어

이벤트 처리기에 사용되는 콜백을 나타내는 EventHandler 인터페이스는 [HTML]에서 정의한다.

작업을 큐에 넣기네트워킹 작업 소스 개념은 [HTML]에서 정의한다.

이벤트 발생시키기 개념은 [DOM]에서 정의한다.

이벤트, 이벤트 처리기이벤트 처리기 이벤트 타입이라는 용어는 [HTML]에서 정의한다.

Performance.timeOriginPerformance.now()는 [hr-time]에서 정의한다.

직렬화 가능한 객체, 직렬화 단계역직렬화 단계라는 용어는 [HTML]에서 정의한다.

MediaStream, MediaStreamTrackMediaStreamConstraints라는 용어는 [GETUSERMEDIA]에서 정의한다. 이 문서에서 MediaStream9.2 MediaStream에서 확장되고, MediaStreamTrack은 이 문서의 9.3 MediaStreamTrack에서 확장된다는 점에 유의한다.

Blob이라는 용어는 [FILEAPI]에서 정의한다.

미디어 설명이라는 용어는 [RFC4566]에서 정의한다.

미디어 전송이라는 용어는 [RFC7656]에서 정의한다.

세대라는 용어는 [RFC8838] 제2절에서 정의한다.

통계 객체모니터링되는 객체라는 용어는 [WEBRTC-STATS]에서 정의한다.

예외를 참조할 때 사용하는 던지기생성됨이라는 용어는 [WEBIDL]에서 정의한다.

VoidFunction 콜백은 [WEBIDL]에서 정의한다.

“예외를 던진다”라는 용어는 [INFRA]에 명시된 대로 사용한다. 즉, 현재 처리 단계를 종료한다.

Promise의 문맥에서 사용하는 이행됨, 거부됨, 결정됨확정됨이라는 용어는 [ECMASCRIPT-6.0]에서 정의한다.

AlgorithmIdentifier는 [WebCryptoAPI]에서 정의한다.

참고

완료될 때까지 실행 원칙과 [API-DESIGN-PRINCIPLES]에서 정의한 데이터 경합 없음 원칙을 포함하여 JavaScript API의 일반 원칙이 적용된다. 즉, 작업이 실행되는 동안 외부 이벤트는 JavaScript 애플리케이션에 표시되는 내용에 영향을 주지 않는다. 예를 들어 JavaScript가 실행되는 동안 “send” 호출로 인해 데이터 채널에 버퍼링된 데이터의 양은 증가하며, 패킷 전송으로 인한 감소는 작업 체크포인트 이후 표시된다.
애플리케이션에 제공되는 값의 집합이 일관되도록 보장하는 것은 사용자 에이전트의 책임이다. 예를 들어 getContributingSources()는 동기식이며, 동일한 시점에 측정된 모든 소스의 값을 반환해야 한다.

4. 피어 투 피어 연결

4.1 소개

이 절은 비규범적이다.

RTCPeerConnection 인스턴스를 사용하면 애플리케이션이 다른 브라우저에 있는 또 다른 RTCPeerConnection 인스턴스 또는 필수 프로토콜을 구현하는 다른 엔드포인트와 피어 투 피어 통신을 설정할 수 있다. 통신은 지정되지 않은 방식으로 제공되지만 일반적으로 서버를 경유하는 페이지의 스크립트에서 제공하는 시그널링 채널을 통해 제어 메시지 (시그널링 프로토콜이라고 함)를 교환하여 조정된다. 예를 들어 WebSocket 또는 XMLHttpRequest를 사용한다.

4.2 구성

4.2.1 RTCConfiguration 딕셔너리

RTCConfigurationRTCPeerConnection을 통해 설정되는 피어 투 피어 통신을 설정하거나 다시 설정하는 방법을 구성하는 매개변수 집합을 정의한다.

WebIDLdictionary RTCConfiguration {
  sequence<RTCIceServer> iceServers = [];
  RTCIceTransportPolicy iceTransportPolicy = "all";
  RTCBundlePolicy bundlePolicy = "balanced";
  RTCRtcpMuxPolicy rtcpMuxPolicy = "require";
  sequence<RTCCertificate> certificates = [];
  [EnforceRange] octet iceCandidatePoolSize = 0;
};
딕셔너리 RTCConfiguration 멤버
iceServers의 타입은 sequence<RTCIceServer>이며, 기본값은 []이다.

STUN 및 TURN 서버와 같이 ICE에서 사용할 수 있는 서버를 설명하는 객체 배열이다. ICE 서버 수가 구현에서 정의한 제한을 초과하면 임계값을 넘는 ICE 서버를 무시한다. 구현에서 정의한 이 제한은 최소 32여야 한다.

iceTransportPolicy의 타입은 RTCIceTransportPolicy이며, 기본값은 "all"이다.

ICE 에이전트가 사용할 수 있는 후보를 나타낸다.

bundlePolicy의 타입은 RTCBundlePolicy이며, 기본값은 "balanced"이다.

ICE 후보를 수집할 때 사용할 미디어 번들링 정책을 나타낸다.

rtcpMuxPolicy의 타입은 RTCRtcpMuxPolicy이며, 기본값은 "require"이다.

ICE 후보를 수집할 때 사용할 rtcp-mux 정책을 나타낸다.

certificates의 타입은 sequence<RTCCertificate>이며, 기본값은 []이다.

RTCPeerConnection이 인증에 사용하는 인증서 집합이다.

이 매개변수에 유효한 값은 generateCertificate() 함수를 호출하여 생성한다.

주어진 DTLS 연결은 하나의 인증서만 사용하지만 이 속성을 사용하면 호출자가 서로 다른 알고리즘을 지원하는 여러 인증서를 제공할 수 있다. 최종 인증서는 허용되는 인증서를 설정하는 DTLS 핸드셰이크를 기반으로 선택한다. RTCPeerConnection 구현은 주어진 연결에 사용할 인증서를 선택한다. 인증서 선택 방법은 이 명세의 범위를 벗어난다.

참고

기존 구현은 제공된 첫 번째 인증서만 사용하며 나머지는 무시한다.

이 값이 없으면 각 RTCPeerConnection 인스턴스에 대해 기본 인증서 집합을 생성한다.

이 옵션을 사용하면 애플리케이션이 키 연속성을 설정할 수 있다. RTCCertificate는 [INDEXEDDB]에 영구 저장하고 재사용할 수 있다. 영구 저장과 재사용은 키 생성 비용도 방지한다.

이 구성 옵션의 값은 처음 선택된 후에는 변경할 수 없다.

iceCandidatePoolSize의 타입은 octet이며, 기본값은 0이다.

[RFC9429] (제 3.5.4절제 4.1.1절)에서 정의한 미리 가져온 ICE 풀의 크기이다.

4.2.2 RTCIceServer 딕셔너리

RTCIceServer 딕셔너리는 ICE 에이전트가 피어와 연결을 설정하는 데 사용할 수 있는 STUN 및 TURN 서버를 설명하는 데 사용된다.

WebIDLdictionary RTCIceServer {
  required (DOMString or sequence<DOMString>) urls;
  DOMString username;
  DOMString credential;
};
딕셔너리 RTCIceServer 멤버
urls의 타입은 (DOMString or sequence<DOMString>)이며, 필수이다.

[RFC7064] 및 [RFC7065]에서 정의한 STUN 또는 TURN URI나 기타 URI 타입이다.

username의 타입은 DOMString이다.

RTCIceServer 객체가 TURN 서버를 나타내는 경우 이 속성은 해당 TURN 서버에 사용할 사용자 이름을 지정한다.

credential의 타입은 DOMString이다.

RTCIceServer 객체가 TURN 서버를 나타내는 경우 이 속성은 해당 TURN 서버에 사용할 자격 증명을 지정한다.

credential은 [RFC5389] 제10.2절에 설명된 장기 인증 비밀번호를 나타낸다.

RTCIceServer 객체 배열의 예는 다음과 같다.

[
  {urls: 'stun:stun1.example.net'},
  {urls: ['turns:turn.example.org', 'turn:turn.example.net'],
    username: 'user',
    credential: 'myPassword',
];

4.2.3 RTCIceTransportPolicy 열거형

[RFC9429] (제4.1.1절)에 설명된 대로 iceTransportPolicy 멤버가 RTCConfiguration에 지정되면 브라우저가 허용된 후보를 애플리케이션에 노출하는 데 사용하는 ICE 후보 정책 [RFC9429] (제3.5.3절)을 정의한다. 연결성 검사에는 이러한 후보만 사용된다.

WebIDLenum RTCIceTransportPolicy {
  "relay",
  "all"
};
RTCIceTransportPolicy 열거형 설명
열거형 값 설명
relay

ICE 에이전트는 TURN 서버를 통과하는 후보와 같은 미디어 릴레이 후보만 사용한다.

참고
특정 사용 사례에서 필요할 수 있는 사용자 IP 주소를 원격 엔드포인트가 알아내지 못하도록 하는 데 사용할 수 있다. 예를 들어 “통화” 기반 애플리케이션에서는 수신자가 어떤 방식으로든 동의할 때까지 알 수 없는 발신자가 수신자의 IP 주소를 알아내지 못하도록 할 수 있다.
all

이 값을 지정하면 ICE 에이전트가 모든 타입의 후보를 사용할 수 있다.

참고
구현은 RTCIceCandidate.address의 설명에 언급된 것처럼 애플리케이션에 노출되는 IP 주소를 제한하기 위해 자체 후보 필터링 정책을 계속 사용할 수 있다.

4.2.4 RTCBundlePolicy 열거형

[RFC9429] (제4.1.1절)에 설명된 대로 원격 엔드포인트가 번들을 인식하지 못하는 경우 번들 정책은 협상되는 미디어 트랙과 수집되는 ICE 후보에 영향을 준다. 원격 엔드포인트가 번들을 인식하면 모든 미디어 트랙과 데이터 채널을 동일한 전송에 번들로 묶는다.

WebIDLenum RTCBundlePolicy {
  "balanced",
  "max-compat",
  "max-bundle"
};
RTCBundlePolicy 열거형 설명
열거형 값 설명
balanced 사용 중인 각 미디어 타입(오디오, 비디오 및 데이터)에 대해 ICE 후보를 수집한다. 원격 엔드포인트가 번들을 인식하지 못하면 별도의 전송에서 오디오 트랙 하나와 비디오 트랙 하나만 협상한다.
max-compat 각 트랙에 대해 ICE 후보를 수집한다. 원격 엔드포인트가 번들을 인식하지 못하면 별도의 전송에서 모든 미디어 트랙을 협상한다.
max-bundle 하나의 트랙에 대해서만 ICE 후보를 수집한다. 원격 엔드포인트가 번들을 인식하지 못하면 미디어 트랙 하나만 협상한다.

4.2.5 RTCRtcpMuxPolicy 열거형

[RFC9429] (제4.1.1절)에 설명된 대로 RTCRtcpMuxPolicy는 다중화되지 않은 RTCP를 지원하기 위해 수집되는 ICE 후보에 영향을 준다. 이 명세에서 정의하는 유일한 값은 "require"이다.

WebIDLenum RTCRtcpMuxPolicy {
  "require"
};
RTCRtcpMuxPolicy 열거형 설명
열거형 값 설명
require RTP에 대해서만 ICE 후보를 수집하고 RTP 후보에서 RTCP를 다중화한다. 원격 엔드포인트가 rtcp-mux를 지원하지 않으면 세션 협상이 실패한다.

4.2.6 제안/응답 옵션

이 딕셔너리들은 제안/응답 생성 프로세스를 제어하는 데 사용할 수 있는 옵션을 설명한다.

WebIDLdictionary RTCOfferAnswerOptions {};
딕셔너리 RTCOfferAnswerOptions 멤버
WebIDLdictionary RTCOfferOptions : RTCOfferAnswerOptions {
  boolean iceRestart = false;
};
딕셔너리 RTCOfferOptions 멤버
iceRestart의 타입은 boolean이며, 기본값은 false이다.

이 딕셔너리 멤버의 값이 true이거나 관련 RTCPeerConnection 객체의 [[LocalIceCredentialsToReplace]] 슬롯이 비어 있지 않으면 생성된 설명에는 현재 자격 증명 (currentLocalDescription 속성의 SDP에 표시됨)과 다른 ICE 자격 증명이 포함된다. 생성된 설명을 적용하면 [RFC5245] 제9.1.1.1절에 설명된 대로 ICE가 다시 시작된다.

이 딕셔너리 멤버의 값이 false이고 관련 RTCPeerConnection 객체의 [[LocalIceCredentialsToReplace]] 슬롯이 비어 있으며 currentLocalDescription 속성에 유효한 ICE 자격 증명이 있으면 생성된 설명에는 currentLocalDescription 속성의 현재 값과 동일한 ICE 자격 증명이 포함된다.

참고

iceConnectionState가 "failed"로 전이될 때 ICE를 다시 시작하는 것이 좋다. 애플리케이션은 추가로 iceConnectionState가 "disconnected"로 전이되는 것을 수신 대기한 다음 다른 정보 소스(예: getStats를 사용하여 다음 몇 초 동안 송수신된 바이트 수가 증가하는지 측정)를 이용해 ICE를 다시 시작하는 것이 적절한지 판단할 수 있다.

RTCAnswerOptions 딕셔너리는 "answer" 타입의 세션 설명에 특정된 옵션을 설명한다 (이 명세 버전에는 없음).

WebIDLdictionary RTCAnswerOptions : RTCOfferAnswerOptions {};

4.3 상태 정의

4.3.1 RTCSignalingState 열거형

WebIDLenum RTCSignalingState {
  "stable",
  "have-local-offer",
  "have-remote-offer",
  "have-local-pranswer",
  "have-remote-pranswer",
  "closed"
};
RTCSignalingState 열거형 설명
열거형 값 설명
stable 진행 중인 제안/응답 교환이 없다. 이는 로컬 및 원격 설명이 비어 있는 초기 상태이기도 하다.
have-local-offer "offer" 타입의 로컬 설명이 성공적으로 적용되었다.
have-remote-offer "offer" 타입의 원격 설명이 성공적으로 적용되었다.
have-local-pranswer "offer" 타입의 원격 설명이 성공적으로 적용되었으며 "pranswer" 타입의 로컬 설명이 성공적으로 적용되었다.
have-remote-pranswer "offer" 타입의 로컬 설명이 성공적으로 적용되었으며 "pranswer" 타입의 원격 설명이 성공적으로 적용되었다.
closed RTCPeerConnection이 닫혔으며 그 [[IsClosed]] 슬롯은 true이다.
시그널링 상태 전이 다이어그램
그림 1 비규범적 시그널링 상태 전이 다이어그램. 메서드 호출은 축약되어 있다.

전이 집합의 예는 다음과 같다.

호출자 전이:
수신자 전이:

4.3.2 RTCIceGatheringState 열거형

WebIDLenum RTCIceGatheringState {
  "new",
  "gathering",
  "complete"
};
RTCIceGatheringState 열거형 설명
열거형 값 설명
new RTCIceTransport 중 하나가 "new" 수집 상태이고 어떤 전송도 "gathering" 상태가 아니거나 전송이 없다.
gathering RTCIceTransport 중 하나가 "gathering" 상태이다.
complete 하나 이상의 RTCIceTransport가 존재하며 모든 RTCIceTransport가 "complete" 수집 상태이다.

고려되는 전송 집합은 현재 RTCPeerConnection트랜시버 집합에서 참조하는 전송과 RTCPeerConnection[[SctpTransport]] 내부 슬롯이 null이 아닌 경우 그 슬롯에서 참조하는 전송이다.

4.3.3 RTCPeerConnectionState 열거형

WebIDLenum RTCPeerConnectionState {
  "closed",
  "failed",
  "disconnected",
  "new",
  "connecting",
  "connected"
};
RTCPeerConnectionState 열거형 설명
열거형 값 설명
closed [[IceConnectionState]]가 "closed"이다.
failed 이전 상태가 적용되지 않으며 [[IceConnectionState]]가 "failed"이거나 RTCDtlsTransport 중 하나가 "failed" 상태이다.
disconnected 이전 상태 중 어느 것도 적용되지 않으며 [[IceConnectionState]]가 "disconnected"이다.
new 이전 상태 중 어느 것도 적용되지 않고 [[IceConnectionState]]가 "new"이며 모든 RTCDtlsTransport가 "new" 또는 "closed" 상태이거나 전송이 없다.
connected 이전 상태 중 어느 것도 적용되지 않고 [[IceConnectionState]]가 "connected"이며 모든 RTCDtlsTransport가 "connected" 또는 "closed" 상태이다.
connecting 이전 상태 중 어느 것도 적용되지 않는다.
참고

"connecting" 상태에서는 하나 이상의 RTCIceTransport가 "new" 또는 "checking" 상태이거나 하나 이상의 RTCDtlsTransport가 "new" 또는 "connecting" 상태이다.

고려되는 전송 집합은 현재 RTCPeerConnection트랜시버 집합에서 참조하는 전송과 RTCPeerConnection[[SctpTransport]] 내부 슬롯이 null이 아닌 경우 그 슬롯에서 참조하는 전송이다.

4.3.4 RTCIceConnectionState 열거형

WebIDLenum RTCIceConnectionState {
  "closed",
  "failed",
  "disconnected",
  "new",
  "checking",
  "completed",
  "connected"
};
RTCIceConnectionState 열거형 설명
열거형 값 설명
closed RTCPeerConnection 객체의 [[IsClosed]] 슬롯이 true이다.
failed 이전 상태가 적용되지 않고 RTCIceTransport 중 하나가 "failed" 상태이다.
disconnected 이전 상태 중 어느 것도 적용되지 않고 RTCIceTransport 중 하나가 "disconnected" 상태이다.
new 이전 상태 중 어느 것도 적용되지 않고 모든 RTCIceTransport가 "new" 또는 "closed" 상태이거나 전송이 없다.
checking 이전 상태 중 어느 것도 적용되지 않고 RTCIceTransport 중 하나가 "new" 또는 "checking" 상태이다.
completed 이전 상태 중 어느 것도 적용되지 않고 모든 RTCIceTransport가 "completed" 또는 "closed" 상태이다.
connected 이전 상태 중 어느 것도 적용되지 않고 모든 RTCIceTransport가 "connected", "completed" 또는 "closed" 상태이다.

고려되는 전송 집합은 현재 RTCPeerConnection트랜시버 집합에서 참조하는 전송과 RTCPeerConnection[[SctpTransport]] 내부 슬롯이 null이 아닌 경우 그 슬롯에서 참조하는 전송이다.

시그널링의 결과(예: RTCP 다중화 또는 번들링)로 RTCIceTransport가 폐기되거나 시그널링의 결과(예: 새 미디어 설명 추가)로 생성되면 상태가 한 상태에서 다른 상태로 직접 진행될 수 있다는 점에 유의한다.

4.4 RTCPeerConnection 인터페이스

[RFC9429] 명세는 전체적으로 RTCPeerConnection의 작동 방식에 관한 세부 사항을 설명한다. [RFC9429]의 특정 하위 절에 대한 참조는 적절한 곳에 제공된다.

4.4.1 동작

다음을 호출하면 new RTCPeerConnection(configuration) RTCPeerConnection 객체가 생성된다.

configuration.iceServers에는 ICE에서 사용하는 서버를 찾고 접근하는 데 쓰이는 정보가 포함된다. 애플리케이션은 각 유형의 서버를 여러 개 제공할 수 있으며, 모든 TURN 서버를 서버 반사 후보를 수집하기 위한 STUN 서버로도 사용할 수 있다.

RTCPeerConnection 객체에는 [[SignalingState]]와 집계된 상태인 [[ConnectionState]], [[IceGatheringState]], 그리고 [[IceConnectionState]]가 있다. 이러한 상태는 객체가 생성될 때 초기화된다.

RTCPeerConnection의 ICE 프로토콜 구현은 ICE 에이전트로 표현된다 [RFC5245]. 일부 RTCPeerConnection 메서드는 ICE 에이전트와 상호 작용하며, 해당 메서드는 addIceCandidate, setConfiguration, setLocalDescription, setRemoteDescriptionclose이다. 이러한 상호 작용은 이 문서의 관련 절과 [RFC9429]에 설명되어 있다. 또한 ICE 에이전트RTCIceTransport의 내부 표현 상태가 변경될 때 사용자 에이전트에 알림을 제공한다. 이는 5.6 RTCIceTransport 인터페이스에 설명되어 있다.

이 절에 나열된 태스크의 태스크 소스는 네트워킹 태스크 소스이다.

참고

SDP 협상의 상태는 내부 변수 [[SignalingState]], [[CurrentLocalDescription]], [[CurrentRemoteDescription]], [[PendingLocalDescription]][[PendingRemoteDescription]]로 표현된다. 이들은 setLocalDescriptionsetRemoteDescription 작업 내부에서만 설정되며, addIceCandidate 작업과 후보를 노출하는 절차에 의해 수정된다. 각각의 경우 다섯 변수 모두에 대한 모든 수정은 해당 절차가 이벤트를 발생시키거나 콜백을 호출하기 전에 완료되므로, 수정 사항은 단일 시점에 표시된다.

문서 언로드 정리 단계 중 하나로 다음 단계를 실행한다:

  1. windowdocument관련 전역 객체로 둔다.

  2. 관련 전역 객체window인 각 RTCPeerConnection 객체 connection에 대해, connection 및 값 true를 사용하여 연결을 닫는다.

4.4.1.1 생성자

RTCPeerConnection.constructor()가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. 아래에 열거된 단계 중 하나라도 여기에 명시되지 않은 이유로 실패하면, 적절한 설명으로 message 속성이 설정된 UnknownError던진다.

  2. connection을 새로 생성된 RTCPeerConnection 객체로 둔다.

  3. connection[[DocumentOrigin]] 내부 슬롯을 두고, 관련 설정 객체출처로 초기화한다.

  4. configuration을 메서드의 첫 번째 인수로 둔다.
  5. configurationcertificates 값이 비어 있지 않으면 certificates의 각 certificate에 대해 다음 단계를 실행한다:

    1. certificate.expires 값이 현재 시간보다 작으면 InvalidAccessError던진다.

    2. certificate.[[Origin]]connection.[[DocumentOrigin]]동일 출처가 아니면 InvalidAccessError던진다.

    3. certificate를 저장한다.

  6. 그렇지 않으면 이 RTCPeerConnection 인스턴스로 하나 이상의 새 RTCCertificate 인스턴스를 생성하여 저장한다. 이는 비동기적으로 수행될 수 있으며, 이후 단계에서 certificates의 값은 undefined로 유지된다. [RFC8826]의 4.3.2.3절에 언급된 것처럼 WebRTC는 공개 키 기반 구조(PKI) 인증서가 아닌 자체 서명 인증서를 사용한다. 따라서 만료 검사는 키가 무기한 사용되지 않도록 하기 위한 것이며 추가 인증서 검사는 필요하지 않다.

  7. connectionICE 에이전트를 초기화한다.

  8. connection[[Configuration]] 내부 슬롯을 두고 null로 초기화한다. configuration으로 지정된 구성을 설정한다.

  9. connection[[IsClosed]] 내부 슬롯을 두고 false로 초기화한다.

  10. connection[[NegotiationNeeded]] 내부 슬롯을 두고 false로 초기화한다.

  11. connection[[SctpTransport]] 내부 슬롯을 두고 null로 초기화한다.

  12. connection[[DataChannels]] 내부 슬롯을 두고 빈 순서 있는 집합으로 초기화한다.

  13. connection[[Operations]] 내부 슬롯을 둔다. 이 슬롯은 작업 체인을 나타내며 빈 목록으로 초기화한다.

  14. connection[[UpdateNegotiationNeededFlagOnEmptyChain]] 내부 슬롯을 두고 false로 초기화한다.

  15. connection[[LastCreatedOffer]] 내부 슬롯을 두고 ""로 초기화한다.

  16. connection[[LastCreatedAnswer]] 내부 슬롯을 두고 ""로 초기화한다.

  17. connection[[EarlyCandidates]] 내부 슬롯을 두고 빈 목록으로 초기화한다.

  18. connection[[SignalingState]] 내부 슬롯을 두고 "stable"로 초기화한다.

  19. connection[[IceConnectionState]] 내부 슬롯을 두고 "new"로 초기화한다.

  20. connection[[IceGatheringState]] 내부 슬롯을 두고 "new"로 초기화한다.

  21. connection[[ConnectionState]] 내부 슬롯을 두고 "new"로 초기화한다.

  22. connection[[PendingLocalDescription]] 내부 슬롯을 두고 null로 초기화한다.

  23. connection[[CurrentLocalDescription]] 내부 슬롯을 두고 null로 초기화한다.

  24. connection[[PendingRemoteDescription]] 내부 슬롯을 두고 null로 초기화한다.

  25. connection[[CurrentRemoteDescription]] 내부 슬롯을 두고 null로 초기화한다.

  26. connection[[LocalIceCredentialsToReplace]] 내부 슬롯을 두고 빈 집합으로 초기화한다.

  27. connection을 반환한다.

4.4.1.2 비동기 작업 연결

RTCPeerConnection 객체에는 작업 체인[[Operations]]이 있으며, 이는 체인에서 하나의 비동기 작업만 동시에 실행되도록 한다. 이전 호출이 반환한 프로미스가 아직 결정되지 않은 동안 후속 호출이 이루어지면 해당 호출은 체인에 추가되고, 모든 이전 호출의 실행이 완료되고 그 프로미스가 결정된 후 실행된다.

RTCPeerConnection 객체의 작업 체인에 작업을 연결하려면 다음 단계를 실행한다:

  1. connection을 해당 RTCPeerConnection 객체로 둔다.

  2. connection.[[IsClosed]]true이면, 새로 생성된 InvalidStateError거부된 프로미스를 반환한다.

  3. operation을 연결할 작업으로 둔다.

  4. p를 새 프로미스로 둔다.

  5. operation[[Operations]]에 추가한다.

  6. [[Operations]]의 길이가 정확히 1이면 operation을 실행한다.

  7. operation이 반환한 프로미스가 이행되거나 거부되면 다음 단계를 실행한다:

    1. connection.[[IsClosed]]true이면 이 단계를 중단한다.

    2. operation이 반환한 프로미스가 어떤 값으로 이행되었으면, 해당 값으로 p이행한다.

    3. operation이 반환한 프로미스가 어떤 값으로 거부되었으면, 해당 값으로 p거부한다.

    4. p이행되거나 거부되면 다음 단계를 실행한다:

      1. connection.[[IsClosed]]true이면 이 단계를 중단한다.

      2. [[Operations]]의 첫 번째 요소를 제거한다.

      3. [[Operations]]가 비어 있지 않으면 [[Operations]]의 첫 번째 요소가 나타내는 작업을 실행하고 이 단계를 중단한다.

      4. connection.[[UpdateNegotiationNeededFlagOnEmptyChain]]false이면 이 단계를 중단한다.

      5. connection.[[UpdateNegotiationNeededFlagOnEmptyChain]]false로 설정한다.

      6. connection에 대해 협상 필요 플래그를 업데이트한다.

  8. p를 반환한다.

4.4.1.3 연결 상태 업데이트

RTCPeerConnection 객체에는 집계된 [[ConnectionState]]가 있다. RTCDtlsTransport의 상태가 변경될 때마다 사용자 에이전트는 다음 단계를 실행하는 태스크를 반드시 큐에 넣어야 한다:

  1. connection을 상태가 변경된 RTCDtlsTransport 객체와 연결된 이 RTCPeerConnection 객체로 둔다.

  2. connection.[[IsClosed]]true이면 이 단계를 중단한다.

  3. newStateRTCPeerConnectionState 열거형에 설명된 방식으로 새 상태 값을 도출한 결과로 둔다.

  4. connection.[[ConnectionState]]newState와 같으면 이 단계를 중단한다.

  5. connection.[[ConnectionState]]newState로 설정한다.

  6. connection에서 connectionstatechange라는 이름의 이벤트를 발생시킨다.

4.4.1.4 세션 설명 설정

RTCPeerConnection 객체 connectiondescription 로컬 세션 설명으로 설정하려면, 추가 값 false를 사용하여 connectiondescription세션 설명으로 설정한다.

RTCPeerConnection 객체 connectiondescription 원격 세션 설명으로 설정하려면, 추가 값 true를 사용하여 connectiondescription세션 설명으로 설정한다.

불리언 remote가 주어진 경우, RTCPeerConnection 객체 connectiondescription세션 설명으로 설정하려면 다음 단계를 실행한다:

  1. p를 새 프로미스로 둔다.

  2. description.type이 "rollback"이고 connection.[[SignalingState]]이 "stable", "have-local-pranswer", 또는 "have-remote-pranswer" 중 하나이면, 새로 생성된 InvalidStateErrorp거부하고 이 단계를 중단한다.

  3. jsepSetOfTransceiversconnection트랜시버 집합의 얕은 복사본으로 둔다.

  4. [RFC9429] (5.5절5.6절)에 설명된 대로 description을 적용하는 프로세스를 병렬로 시작하되, 다음 추가 제한 사항을 적용한다:

    1. 어떤 "RtpTransceivers"가 존재하는지를 판단하는 기준 정보로 jsepSetOfTransceivers를 사용하고, 해당 트랜시버의 [[JsepMid]] 내부 슬롯을 해당 트랜시버의 "mid 속성"으로 사용한다.

    2. 후보 수정 5:관리상 금지된 후보에 대한 ICE 수집 및 연결성 검사를 금지한다 (PR #2708)

      remotefalse이고 이로 인해 [RFC9429] (5.9절)의 ICE 후보 수집 프로세스가 시작되면, ICE 에이전트관리상 금지되는 후보를 수집해서는 안 된다.

    3. 후보 수정 5:관리상 금지된 후보에 대한 ICE 수집 및 연결성 검사를 금지한다 (PR #2708)

      remotetrue이고 이로 인해 [RFC9429] (5.10절)의 ICE 연결성 검사가 시작되면, ICE 에이전트관리상 금지된 후보에 연결을 시도해서는 안 된다.

    4. remotetrue이면, 연속된 제안 사이에 응답이 적용된 것처럼, 후속 제안에 대한 검사를 안정 상태에서 수행하는 것처럼 실행하여 연속된 제안을 검증한다.

    5. description을 적용하여 트랜시버 transceiver가 수정되고, transceiver.[[Sender]].[[SendEncodings]]가 비어 있지 않으며 description 처리의 결과로 생성될 인코딩과 같지 않으면, description 적용 프로세스가 실패한다. 이 명세는 원격에서 시작된 RID 재협상을 허용하지 않는다.

       
    6. 어떤 이유로든 description 적용 프로세스가 실패하면 사용자 에이전트는 다음 단계를 실행하는 태스크를 반드시 큐에 넣어야 한다:

      1. connection.[[IsClosed]]true이면 이 단계를 중단한다.

      2. description.type [RFC9429] (5.5절5.6절)에 설명된 현재 connection.[[SignalingState]]에 유효하지 않으면, 새로 생성된 InvalidStateErrorp거부하고 이 단계를 중단한다.

      3. description의 내용이 유효한 SDP 구문이 아니면 pRTCError거부한다( errorDetail을 "sdp-syntax-error"로 설정하고, sdpLineNumber 속성을 구문 오류가 감지된 SDP의 줄 번호로 설정한다). 그런 다음 이 단계를 중단한다.

      4. remotetrue이고, connectionRTCRtcpMuxPolicyrequire이며 설명에서 RTCP mux를 사용하지 않으면, 새로 생성된 InvalidAccessErrorp거부하고 이 단계를 중단한다.

      5. 위에서 설명한 대로 설명에서 RID 재협상을 시도했으면, 새로 생성된 InvalidAccessErrorp거부하고 이 단계를 중단한다.

      6. description의 내용이 유효하지 않으면, 새로 생성된 InvalidAccessErrorp거부하고 이 단계를 중단한다.

      7. 다른 모든 오류의 경우 새로 생성된 OperationErrorp거부한다.

    7. description이 성공적으로 적용되면 사용자 에이전트는 다음 단계를 실행하는 태스크를 반드시 큐에 넣어야 한다:

      1. connection.[[IsClosed]]true이면 이 단계를 중단한다.

      2. remotetrue이고 description이 "offer" 유형이며, description을 적용하는 프로세스 중 connectionaddTrack() 메서드 중 하나라도 성공한 경우, 이 단계를 중단하고 해당 메서드가 이전에 성공한 것처럼 프로세스를 다시 시작하여 추가 트랜시버를 프로세스에 포함한다.

      3. connection과 연결된 RTCRtpSendersetParameters 메서드에서 반환된 프로미스 중 하나라도 결정되지 않았으면, 이 단계를 중단하고 프로세스를 다시 시작한다.

      4. description이 "offer" 유형이고 connection.[[SignalingState]]이 "stable"이면, connection트랜시버 집합에 있는 각 transceiver에 대해 다음 단계를 실행한다:

        1. transceiver.[[Sender]].[[LastStableStateSenderTransport]]transceiver.[[Sender]].[[SenderTransport]]로 설정한다.

        2. 후보 수정 13:롤백은 sRD(simulcastOffer)로 대체된 rid 없는 인코딩을 복원한다. (PR #2797)

          transceiver.[[Sender]].[[SendEncodings]].length가 1이고 유일한 인코딩에 rid 멤버가 포함되어 있지 않으면, transceiver.[[Sender]].[[LastStableRidlessSendEncodings]]transceiver.[[Sender]].[[SendEncodings]]로 설정한다. 그렇지 않으면, transceiver.[[Sender]].[[LastStableRidlessSendEncodings]]null로 설정한다.

        3. transceiver.[[Receiver]].[[LastStableStateReceiverTransport]]transceiver.[[Receiver]].[[ReceiverTransport]]로 설정한다.

        4. transceiver.[[Receiver]].[[LastStableStateAssociatedRemoteMediaStreams]]transceiver.[[Receiver]].[[AssociatedRemoteMediaStreams]]로 설정한다.

        5. transceiver.[[Receiver]].[[LastStableStateReceiveCodecs]]transceiver.[[Receiver]].[[ReceiveCodecs]]로 설정한다.

      5. remotefalse이면 다음 단계 중 하나를 실행한다:

        1. description이 "offer" 유형이면, connection.[[PendingLocalDescription]]description으로 생성한 새 RTCSessionDescription 객체로 설정하고, connection.[[SignalingState]]을 "have-local-offer"로 설정한 다음 초기 후보를 해제한다.

        2. description이 "answer" 유형이면 제안-응답 협상이 완료된다. connection.[[CurrentLocalDescription]]description으로 생성한 새 RTCSessionDescription 객체로 설정하고, connection.[[CurrentRemoteDescription]]connection.[[PendingRemoteDescription]]으로 설정한다. connection.[[PendingRemoteDescription]]connection.[[PendingLocalDescription]]을 모두 null로 설정한다. connection.[[LastCreatedOffer]]connection.[[LastCreatedAnswer]]를 모두 ""로 설정하고, connection.[[SignalingState]]을 "stable"로 설정한 다음 초기 후보를 해제한다. 마지막으로, connection.[[LocalIceCredentialsToReplace]]의 ICE 자격 증명 중 어느 것도 description에 없으면, connection.[[LocalIceCredentialsToReplace]]을 빈 집합으로 설정한다.

        3. description이 "pranswer" 유형이면, connection.[[PendingLocalDescription]]description으로 생성한 새 RTCSessionDescription 객체로 설정하고, connection.[[SignalingState]]을 "have-local-pranswer"로 설정한 다음 초기 후보를 해제한다.

      6. 그렇지 않으면(remotetrue이면) 다음 단계 중 하나를 실행한다:

        1. description이 "offer" 유형이면, connection.[[PendingRemoteDescription]] 속성을 description으로 생성한 새 RTCSessionDescription 객체로 설정하고, connection.[[SignalingState]]을 "have-remote-offer"로 설정한다.

        2. description이 "answer" 유형이면 제안-응답 협상이 완료된다. connection.[[CurrentRemoteDescription]]description으로 생성한 새 RTCSessionDescription 객체로 설정하고, connection.[[CurrentLocalDescription]]connection.[[PendingLocalDescription]]으로 설정한다. connection.[[PendingRemoteDescription]]connection.[[PendingLocalDescription]]을 모두 null로 설정한다. connection.[[LastCreatedOffer]]connection.[[LastCreatedAnswer]]를 모두 ""로 설정하고, connection.[[SignalingState]]을 "stable"로 설정한다. 마지막으로, 새로 설정된 connection.[[CurrentLocalDescription]]connection.[[LocalIceCredentialsToReplace]]의 ICE 자격 증명이 하나도 없으면, connection.[[LocalIceCredentialsToReplace]]을 빈 집합으로 설정한다.

        3. description이 "pranswer" 유형이면, connection.[[PendingRemoteDescription]]description으로 생성한 새 RTCSessionDescription 객체로 설정하고 connection.[[SignalingState]]을 "have-remote-pranswer"로 설정한다.

      7. description이 "answer" 유형이고 [RFC8841]의 10.3절 및 10.4절에 정의된 대로 기존 SCTP 연결의 종료를 시작하면, connection.[[SctpTransport]]의 값을 null로 설정한다.

      8. trackEventInits, muteTracks, addList, removeListerrorList를 빈 목록으로 둔다.

      9. description이 "answer" 또는 "pranswer" 유형이면 다음 단계를 실행한다:

        1. description이 [RFC8841]의 10.3절 및 10.4절에 정의된 대로 새 SCTP 연결 설정을 시작하면, 초기 상태가 "connecting"인 RTCSctpTransport를 생성하고, 그 결과를 [[SctpTransport]] 슬롯에 할당한다. 그렇지 않고 SCTP 연결이 설정되어 있지만 max-message-size SDP 속성이 업데이트되면, connection.[[SctpTransport]]데이터 최대 메시지 크기를 업데이트한다.

        2. description이 SCTP 전송의 DTLS 역할을 협상하면, null id를 가진 각 RTCDataChannel channel에 대해 다음 단계를 실행한다:

          1. [RFC8832]에 따라 생성한 새 ID를 channel에 부여한다. 사용 가능한 ID를 생성할 수 없으면 channel.[[ReadyState]]를 "closed"로 설정하고 channnelerrorList에 추가한다.
      10. description이 "rollback" 유형이 아니면 다음 단계를 실행한다:

        1. remotefalse이면 description의 각 미디어 설명에 대해 다음 단계를 실행한다:

          후보 수정 26:createAnswer()의 인코딩과 sLD(answer)의 SendEncodings를 정리한다. (PR #2801)
          1. 미디어 설명이 아직 RTCRtpTransceiver 객체와 연결되지 않았으면 다음 단계를 실행한다:

            1. transceiver미디어 설명을 생성하는 데 사용된 RTCRtpTransceiver로 둔다.

            2. transceiver.[[Mid]]transceiver.[[JsepMid]]로 설정한다.

            3. transceiver.[[Stopped]]true이면 이 하위 단계를 중단한다.

            4. [RFC8843]에 따라 미디어 설명에서 기존 미디어 미디어 전송을 사용하는 것으로 표시하면, transport를 해당 전송의 RTP/RTCP 구성 요소를 나타내는 RTCDtlsTransport 객체로 둔다.

            5. 그렇지 않으면 transport를 새로운 기반 RTCIceTransport를 가진, 새로 생성된 RTCDtlsTransport 객체로 둔다.

            6. transceiver.[[Sender]].[[SenderTransport]]transport로 설정한다.

            7. transceiver.[[Receiver]].[[ReceiverTransport]]transport로 설정한다.

          2. transceiver미디어 설명연결된 RTCRtpTransceiver로 둔다.

          3. transceiver.[[Stopped]]true이면 이 하위 단계를 중단한다.

          4. direction미디어 미디어 설명의 방향을 나타내는 RTCRtpTransceiverDirection 값으로 둔다.

          5. direction이 "sendrecv" 또는 "recvonly"이면, transceiver.[[Receptive]]true로 설정하고, 그렇지 않으면 false로 설정한다.

          6. transceiver.[[Receiver]].[[ReceiveCodecs]]description에서 수신용으로 협상하고 사용자 에이전트가 현재 수신할 준비가 된 코덱으로 설정한다.

            참고

            direction이 "sendonly" 또는 "inactive"이면, 수신기는 어떤 것도 수신할 준비가 되어 있지 않으므로 목록은 비어 있게 된다.

          7. description이 "answer" 또는 "pranswer" 유형이면 다음 단계를 실행한다:

            1. transceiver. [[Sender]].[[SendEncodings]] .length가 1보다 크면 다음 단계를 실행한다:

              1. description에 이전에 협상한 모든 계층이 없으면, transceiver.[[Sender]].[[SendEncodings]]에서 첫 번째 사전을 제외한 모든 사전을 제거하고 다음 단계를 건너뛴다.

              2. description에 이전에 협상한 계층 중 하나라도 없으면, 누락된 계층에 대응하는 사전을 transceiver.[[Sender]].[[SendEncodings]]에서 제거한다.

            2. transceiver.[[Sender]].[[SendCodecs]]description에서 송신용으로 협상하고 사용자 에이전트가 현재 송신할 수 있는 코덱으로 설정하고, transceiver.[[Sender]].[[LastReturnedParameters]]null로 설정한다.

            3. direction이 "sendonly" 또는 "inactive"이고, transceiver.[[FiredDirection]]이 "sendrecv" 또는 "recvonly" 중 하나이면 다음 단계를 실행한다:

              1. transceiver.[[Receiver]], 빈 목록, 또 다른 빈 목록 및 removeList가 주어졌을 때 연결된 원격 스트림을 설정한다.

              2. transceivermuteTracks가 주어졌을 때 미디어 설명에 대해 원격 원격 트랙 제거를 처리한다.

            4. transceiver.[[CurrentDirection]]transceiver.[[FiredDirection]]direction으로 설정한다.

        2. 그렇지 않으면(remotetrue이면) description의 각 미디어 설명에 대해 다음 단계를 실행한다:

          후보 수정 12:encoding.active와 simulcast ~rid 사이의 상호 작용을 제거한다 (PR #2754)
          후보 수정 14:RTCTransceiver.direction이 제안과 응답에서 로컬 기본 설정을 반영하도록 한다 (PR #2759)
          후보 수정 22:클라이언트 응답을 통해 원격 제안의 rid 인코딩 정리를 허용한다. (PR #2758)
          후보 수정 37:rid 불일치로 인해 sRD(offer)를 실패시키지 않고 유니캐스트로만 응답한다. (PR #2794)
          후보 수정 25:proposedSendEncodings에서 중복 rid를 제거한다. (PR #2800)
          후보 수정 27:쉼표로 구분된 rid 대안을 무시한다. (PR #2813)
          1. description이 "offer" 유형이고 미디어 설명동시 송출 수신 요청이 포함되어 있으면, simulcast 속성에 지정된 rid 값의 순서를 사용하여 각 동시 송출 계층에 대한 RTCRtpEncodingParameters 사전을 생성하고, 대응하는 rid 값에 따라(쉼표로 구분된 대안이 있으면 첫 번째 값만 사용하여) rid 멤버를 채운 다음, sendEncodingsproposedSendEncodings를 생성된 사전을 포함하는 목록으로 목록으로 둔다. 그렇지 않으면 sendEncodingsproposedSendEncodings 목록으로 목록으로 둔다.

          2. proposedSendEncodings의 각 인코딩 encoding에 대해 역순으로, encodingridproposedSendEncodings에 있는 다른 인코딩의 값과 일치하면 encodingproposedSendEncodings에서 제거한다.

          3. supportedEncodings를 구현이 지원할 수 있는 최대 인코딩 수로 둔다. sendEncodingsproposedSendEncodings의 길이가 supportedEncodings보다 크면, 길이가 supportedEncodings가 되도록 sendEncodingsproposedSendEncodings를 자른다.
          4. sendEncodingsproposedSendEncodings가 비어 있지 않으면,인코딩의 scaleResolutionDownBy2^(length of sendEncodingsproposedSendEncodings - encoding index - 1)로 설정한다.
          5. [RFC8829RFC9429] (5.10절)에 설명된 대로, 미디어 설명을 나타낼 기존 RTCRtpTransceiver 객체 transceiver를 찾으려고 시도한다.

          6. 적합한 트랜시버를 찾았고 (transceiver가 설정됨), sendEncodingsproposedSendEncodings가 비어 있지 않으면, transceiver.[[Sender]].[[SendEncodings]] sendEncodings로 설정하고, transceiver.[[Sender]].[[LastReturnedParameters]]null로 설정한다.다음 단계를 실행한다:

            1. transceiver.[[Sender]].[[SendEncodings]]의 길이가 1이고 유일한 인코딩에 rid 멤버가 포함되어 있지 않으면, transceiver.[[Sender]].[[SendEncodings]]proposedSendEncodings로 설정하고, transceiver.[[Sender]].[[LastReturnedParameters]]null로 설정한다.

          7. 적합한 트랜시버를 찾지 못한 경우 (transceiver가 설정되지 않은 경우), 다음 단계를 실행한다:

            1. RTCRtpSender를 생성하여, sender로 하고, 미디어 미디어 설명에서 sendEncodingsproposedSendEncodings을 사용한다.

            2. RTCRtpReceiver를 생성하여, receiver로 하고, 미디어 미디어 설명을 사용한다.

            3. RTCRtpTransceiver 생성sender, receiverRTCRtpTransceiverDirection 값 "recvonly"를 사용하고, 그 결과를 transceiver로 한다.

            4. transceiverconnection트랜시버 집합에 집합에 추가한다.

          8. description의 유형이 "answer" 또는 "pranswer"이고, 또한 transceiver. [[Sender]].[[SendEncodings]] .length가 1보다 크면, 다음 단계를 실행한다:

            1. description이 동시 송출을 지원하지 않거나 원하지 않음을 나타내거나, 또는 description에 이전에 협상된 모든 계층이 누락된 경우, transceiver.[[Sender]].[[SendEncodings]]에서 첫 번째 사전을 제외한 모든 사전을 제거하고 이 하위 단계들을 중단한다.

            2. description거부한 누락한 제안된 이전에 협상된 계층이 하나라도 있으면, 그런 다음 그런 다음 transceiver.[[Sender]].[[SendEncodings]]에서 거부된 누락된 계층에 대응하는 해당 해당 사전을 제거한다.

            3. 각 동시 송출 계층의 일시 중지 상태를 [RFC8853]에 명시된 대로 갱신한다. 이를 위해 transceiver.[[Sender]].[[SendEncodings]]의 대응하는 사전에 있는 active 멤버를 일시 중지되지 않은 경우 true로, 일시 중지된 경우 false로 설정한다.

          9. transceiver.[[Mid]]transceiver.[[JsepMid]]로 설정한다.

          10. direction미디어 미디어 설명의 방향을 나타내되, 송신 및 수신 방향을 반대로 하여 이 피어의 관점에서 나타내는 RTCRtpTransceiverDirection 값으로 한다. 미디어 설명이 거부된 경우, direction을 "inactive"로 설정한다.

          11. direction이 "sendrecv" 또는 "recvonly"인 경우, msids를 미디어 설명이 transceiver.[[Receiver]].[[ReceiverTrack]]과 연결되어야 한다고 나타내는 MSID의 목록으로 한다. 그렇지 않으면 msids를 빈 목록으로 한다.

            참고
            미디어 설명이 거부되면 여기서 msids는 빈 목록이 된다.
          12. 원격 트랙 처리transceiver, direction, msids, addList, removeListtrackEventInits를 사용한다.

          13. transceiver.[[Receiver]].[[ReceiveCodecs]]description이 수신용으로 협상하고 사용자 에이전트가 현재 수신할 준비가 된 코덱으로 설정한다.

          14. description의 유형이 "answer" 또는 "pranswer"이면, 다음 단계를 실행한다:

            1. transceiver.[[Sender]].[[SendCodecs]]description이 송신용으로 협상하고 사용자 에이전트가 현재 송신할 수 있는 코덱으로 설정한다.

            2. transceiver.[[CurrentDirection]] transceiver.[[Direction]]direction으로 설정한다.

            3. transporttransceiver연결된 미디어 설명이 사용하는 미디어 미디어 전송의 RTP/RTCP 구성요소를 나타내는 RTCDtlsTransport 객체로 하며, 이는 [RFC8843]을 따른다.

            4. transceiver.[[Sender]].[[SenderTransport]]transport로 설정한다.

            5. transceiver.[[Receiver]].[[ReceiverTransport]]transport로 설정한다.

            6. transport[[IceRole]]을 [RFC8445]의 규칙에 따라 설정한다.

              참고
              여기에 적용되는 [RFC8445]의 규칙은 다음과 같다: 이렇게 하면 첫 번째 제안이 처리된 후 [[IceRole]]이 항상 값을 갖게 된다.
          15. 미디어 설명이 거부되었고, transceiver.[[Stopped]]false이면, transceiver RTCRtpTransceiver를 중지 중지 한다.

      11. 그렇지 않으면(description의 유형이 "rollback"인 경우) 다음 단계를 실행한다:

        1. pendingDescriptionconnection.[[PendingLocalDescription]] 또는 connection.[[PendingRemoteDescription]]null이 아닌 것으로 한다.

        2. connection트랜시버 집합에 있는 각 transceiver에 대해 다음 단계를 실행한다:

          1. pendingDescription이 설정되기 전에 transceiver미디어 설명연결되어 있지 않았다면 연결을 해제하고, transceiver.[[JsepMid]]transceiver.[[Mid]]를 모두 null로 설정한다.

          2. transceiver.[[Sender]].[[SenderTransport]]transceiver.[[Sender]].[[LastStableStateSenderTransport]]로 설정한다.

          3. 후보 수정 13:롤백은 sRD(simulcastOffer)가 덮어쓴 rid 없는 인코딩을 복원한다. (PR #2797)

            transceiver.[[Sender]].[[LastStableRidlessSendEncodings]]null이 아니고, transceiver.[[Sender]].[[SendEncodings]]의 인코딩 중 하나라도 rid 멤버를 포함하면, transceiver.[[Sender]].[[SendEncodings]]transceiver.[[Sender]].[[LastStableRidlessSendEncodings]]로 설정한다.

          4. transceiver.[[Receiver]].[[ReceiverTransport]]transceiver.[[Receiver]].[[LastStableStateReceiverTransport]]로 설정한다.

          5. transceiver.[[Receiver]].[[ReceiveCodecs]]transceiver.[[Receiver]].[[LastStableStateReceiveCodecs]]로 설정한다.

          6. connection.[[SignalingState]]이 "have-remote-offer"이면, 다음 하위 단계를 실행한다:

            1. msidstransceiver.[[Receiver]].[[LastStableStateAssociatedRemoteMediaStreams]]에 있는 모든 MediaStream 객체의 id 목록으로 하며, 객체가 없으면 빈 목록으로 한다.

            2. 원격 트랙 처리transceiver, transceiver.[[CurrentDirection]], msids, addList, removeListtrackEventInits를 사용한다.

          7. pendingDescription이 설정될 때 transceiver가 생성되었고, addTrack()을 통해 트랙이 연결된 적이 없다면, transceiver RTCRtpTransceiver를 중지하고, connection트랜시버 집합에서 제거한다.

        3. connection.[[PendingLocalDescription]]connection.[[PendingRemoteDescription]]null로 설정하고, connection.[[SignalingState]]을 "stable"로 설정한다.

      12. description의 유형이 "answer"이면, 다음 단계를 실행한다:

        1. connection트랜시버 집합에 있는 각 transceiver에 대해 다음 단계를 실행한다:

          1. transceiverstopped이고, m= 섹션과 연결되어 있으며, 연결된 m= 섹션이 connection.[[CurrentLocalDescription]] 또는 connection.[[CurrentRemoteDescription]]에서 거부되었다면, transceiverconnection트랜시버 집합에서 제거한다.

      13. 이제 connection.[[SignalingState]]이 "stable"이면, 다음 단계를 실행한다:

        1. 앞 단계에서 트랜시버 집합에서 제거된 각 transceiver에 대해, 해당 전송 중 하나라도 (transceiver.[[Sender]].[[SenderTransport]] 또는 transceiver.[[Receiver]].[[ReceiverTransport]])이 아직 닫히지 않았고, 더 이상 중지되지 않은 트랜시버가 참조하지 않는다면, 해당 RTCDtlsTransport와 연결된 RTCIceTransport를 닫는다. 그 결과 대기열에 추가된 태스크에서 이 객체들에 이벤트가 발생한다.

        2. 후보 추가 49: RTCRtpEncodingParameters에 코덱 추가 (PR #2985)

          connection트랜시버 집합에 있는 각 transceiver에 대해:

          1. codecstransceiver.[[Sender]].[[SendCodecs]]로 한다.

          2. codecs가 빈 목록이 아니면:

            1. transceiver.[[Sender]].[[SendEncodings]]의 각 encoding에 대해, encoding.codecignoreLevelstrue로 설정한 코덱 사전 일치 알고리즘을 사용해 codecs의 어떤 항목과도 일치하지 않으면, encoding.codec제거한다.

        3. 협상 필요 플래그를 지우고, 협상 필요 플래그를 갱신한다.

      14. 위에서 connection.[[SignalingState]]이 변경되었다면, connection에서 signalingstatechange라는 이름의 이벤트를 발생시킨다.

      15. errorList의 각 channel에 대해, RTCErrorEvent 인터페이스를 사용하고 errorDetail 속성을 "data-channel-failure"로 설정하여, channel에서 error라는 이름의 이벤트를 발생시킨다.

      16. muteTracks의 각 track에 대해, track음소거 상태를 true로 설정한다.

      17. removeList의 각 streamtrack 쌍에 대해, stream에서 track제거한다.

      18. addList의 각 streamtrack 쌍에 대해, streamtrack추가 한다.

      19. trackEventInits의 각 항목 entry에 대해, 이벤트를 발생시킨다. 이벤트의 이름은 track이며, RTCTrackEvent 인터페이스를 사용하고, 그 receiver 속성은 entry.receiver로 초기화하고, 그 track 속성은 entry.track으로 초기화하고, 그 streams 속성은 entry.streams로 초기화하며, 또한 그 transceiver 속성은 entry.transceiver로 초기화하여 connection 객체에서 발생시킨다.

      20. pundefined이행한다.

  5. p를 반환한다.

4.4.1.5 구성 설정

구성을 설정하기 위해 configuration을 사용하여 다음 단계를 실행한다:

  1. connection을 대상 RTCPeerConnection 객체로 한다.

  2. oldConfigconnection.[[Configuration]]으로 한다.

  3. oldConfignull이 아니면 다음 단계를 실행하고, 그중 하나라도 실패하면 다음 예외를 던진다: InvalidModificationError:

    1. configuration.certificates의 길이가 oldConfig.certificates의 길이와 다르면 실패한다.

    2. index를 0으로 한다.

    3. indexconfiguration.certificates의 길이보다 작은 동안 다음 단계를 실행한다:

      1. configuration.certificatesindex 위치에 있는 값이 나타내는 ECMAScript 객체가 oldConfig.certificatesindex 위치에 있는 값이 나타내는 ECMAScript 객체와 같지 않으면 실패한다.

      2. index를 1만큼 증가시킨다.

    4. configuration.bundlePolicy의 값이 oldConfig.bundlePolicy와 다르면 실패한다.

    5. configuration.rtcpMuxPolicy의 값이 oldConfig.rtcpMuxPolicy와 다르면 실패한다.

    6. configuration.iceCandidatePoolSize의 값이 oldConfig.iceCandidatePoolSize와 다르고, setLocalDescription이 이미 호출되었다면 실패한다.

  4. iceServersconfiguration.iceServers로 한다.

  5. iceServers를 지원되는 최대 요소 수로 잘라낸다.

  6. iceServers의 각 server에 대해 다음 단계를 실행한다:

    1. urlsserver.urls로 한다.

    2. urls가 문자열이면, urls를 해당 문자열 하나로만 구성된 목록으로 설정한다.

    3. urls가 비어 있으면 다음 예외를 던진다: "SyntaxError" DOMException.

    4. urls의 각 url에 대해, urlICE 서버 URL 검증 알고리즘을 실행한다.

  7. ICE 에이전트ICE 전송 설정configuration.iceTransportPolicy의 값으로 설정한다. [RFC9429] (4.1.18절 )에 정의된 대로, 새 ICE 전송 설정이 기존 설정을 변경하는 경우 다음 수집 단계까지 아무 작업도 수행되지 않는다. 스크립트가 이를 즉시 적용하려면 ICE 재시작을 수행해야 한다.

  8. [RFC9429] (3.5.4절4.1.1절 )에 정의된 대로 ICE 에이전트의 미리 가져온 ICE 후보 풀 크기configuration.iceCandidatePoolSize의 값으로 설정한다. 새 ICE 후보 풀 크기가 기존 설정을 변경하면, [RFC9429] (4.1.18절 )에 정의된 대로 새 풀 후보가 즉시 수집되거나 기존 풀 후보가 폐기될 수 있다.

  9. ICE 에이전트ICE 서버 목록iceServers로 설정한다.

    [RFC9429] (4.1.18절 )에 정의된 대로, 새 서버 목록이 ICE 에이전트의 기존 ICE 서버 목록을 교체하면 다음 수집 단계까지 아무 작업도 수행되지 않는다. 스크립트가 이를 즉시 적용하려면 ICE 재시작을 수행해야 한다. 그러나 ICE 후보 풀의 크기가 0이 아니면 기존 풀 후보는 모두 폐기되고 새 후보가 새 서버에서 수집된다.

  10. configuration[[Configuration]] 내부 슬롯에 저장한다.

url에 대해 ICE 서버 URL을 검증하려면 다음 단계를 실행한다:

후보 수정 33:ICE 서버 URL을 구문 분석할 때 URL 명세 사용 (PR #2853, PR #2996, PR #2998)
  1. [RFC3986]에 정의된 일반 URI 구문을 사용하여 url을 구문 분석하고 scheme name을 얻는다. [RFC3986]에 정의된 구문에 따른 구문 분석이 실패하면 다음 예외를 던진다: SyntaxError. scheme name이 브라우저에서 구현되지 않은 경우 다음 예외를 던진다: NotSupportedError. scheme nameturn 또는 turns이고, [RFC7065]에 정의된 구문으로 url을 구문 분석하는 데 실패하면 다음 예외를 던진다: SyntaxError. scheme namestun 또는 stuns이고, [RFC7064]에 정의된 구문으로 url을 구문 분석하는 데 실패하면 다음 예외를 던진다: SyntaxError.

  2. parsedURLurl구문 분석한 결과로 한다.

  3. 다음 조건 중 하나라도 적용되면 다음 예외를 던진다: "SyntaxError" DOMException:

    • parsedURL이 실패이다
    • parsedURL스킴"stun", "stuns", "turn", "turns" 중 어느 것도 아니다
    • parsedURL불투명 경로가 없다
    • parsedURL불투명 경로에 하나 이상의 "/" 또는 "@"가 포함되어 있다
    • parsedURL프래그먼트가 null이 아니다
    • parsedURL스킴"stun" 또는 "stuns"이고, parsedURL쿼리가 null이 아니다
  4. parsedURL스킴이 사용자 에이전트에서 구현되지 않았다면 다음 예외를 던진다: NotSupportedError.

  5. hostAndPortURL"https://"parsedURL경로를 연결한 문자열을 구문 분석한 결과로 한다.

  6. hostAndPortURL이 실패이면 다음 예외를 던진다: "SyntaxError" DOMException.

    hostAndPortURL경로, 사용자 이름 또는 비밀번호가 null이 아니면 다음 예외를 던진다: "SyntaxError" DOMException.

    참고

    "stun" 및 "stuns" 스킴의 경우, 이 단계는 [RFC7064] 3.1절을 검증한다.
    "turn" 및 "turns" 스킴의 경우, 이 단계와 아래 단계들은 [RFC7065] 3.1절을 검증한다.

  7. parsedURL쿼리가 null이 아니고 parsedURL쿼리"transport=udp" 또는 "transport=tcp" 중 어느 것과도 다르면 다음 예외를 던진다: "SyntaxError" DOMException.

  8. scheme nameparsedURL's' 스킴turn"turn" 또는 turns또는 "turns"이고, server.username 또는 server.credential 중 하나가 생략되어 있으면 존재하지 않으면, 다음 예외를 던진다: InvalidAccessError.

  9. scheme nameturn 또는 turns이고, server.credentialType이 "password"이고, server.credentialDOMString이 아니면 다음 예외를 던진다: InvalidAccessError.

4.4.2 인터페이스 정의

이 절에서 제시하는 RTCPeerConnection 인터페이스는 이 명세 전반의 여러 부분 인터페이스에 의해 확장된다. 특히 RTP 미디어 API 절은 MediaStreamTrack 객체를 송수신하는 API를 추가한다.

WebIDL[Exposed=Window]
interface RTCPeerConnection : EventTarget  {
  constructor(optional RTCConfiguration configuration = {});
  Promise<RTCSessionDescriptionInit> createOffer(optional RTCOfferOptions options = {});
  Promise<RTCSessionDescriptionInit> createAnswer(optional RTCAnswerOptions options = {});
  Promise<undefined> setLocalDescription(optional RTCLocalSessionDescriptionInit description = {});
  readonly attribute RTCSessionDescription? localDescription;
  readonly attribute RTCSessionDescription? currentLocalDescription;
  readonly attribute RTCSessionDescription? pendingLocalDescription;
  Promise<undefined> setRemoteDescription(RTCSessionDescriptionInit description);
  readonly attribute RTCSessionDescription? remoteDescription;
  readonly attribute RTCSessionDescription? currentRemoteDescription;
  readonly attribute RTCSessionDescription? pendingRemoteDescription;
  Promise<undefined> addIceCandidate(optional RTCIceCandidateInit candidate = {});
  readonly attribute RTCSignalingState signalingState;
  readonly attribute RTCIceGatheringState iceGatheringState;
  readonly attribute RTCIceConnectionState iceConnectionState;
  readonly attribute RTCPeerConnectionState connectionState;
  readonly attribute boolean? canTrickleIceCandidates;
  undefined restartIce();
  RTCConfiguration getConfiguration();
  undefined setConfiguration(optional RTCConfiguration configuration = {});
  undefined close();
  attribute EventHandler onnegotiationneeded;
  attribute EventHandler onicecandidate;
  attribute EventHandler onicecandidateerror;
  attribute EventHandler onsignalingstatechange;
  attribute EventHandler oniceconnectionstatechange;
  attribute EventHandler onicegatheringstatechange;
  attribute EventHandler onconnectionstatechange;

  // 레거시 인터페이스 확장
  // 이 절의 메서드 지원은 선택 사항이다.
  // 이러한 메서드를 지원하는 경우
  // "레거시 인터페이스 확장" 절에 정의된 대로
  // 구현해야 한다.
  Promise<undefined> createOffer(RTCSessionDescriptionCallback successCallback,
                            RTCPeerConnectionErrorCallback failureCallback,
                            optional RTCOfferOptions options = {});
  Promise<undefined> setLocalDescription(RTCLocalSessionDescriptionInit description,
                                    VoidFunction successCallback,
                                    RTCPeerConnectionErrorCallback failureCallback);
  Promise<undefined> createAnswer(RTCSessionDescriptionCallback successCallback,
                             RTCPeerConnectionErrorCallback failureCallback);
  Promise<undefined> setRemoteDescription(RTCSessionDescriptionInit description,
                                     VoidFunction successCallback,
                                     RTCPeerConnectionErrorCallback failureCallback);
  Promise<undefined> addIceCandidate(RTCIceCandidateInit candidate,
                                VoidFunction successCallback,
                                RTCPeerConnectionErrorCallback failureCallback);
};
속성
localDescription 유형: RTCSessionDescription, 읽기 전용, null 허용

localDescription 속성은 [[PendingLocalDescription]]null이 아니면 이를 반드시 반환하고, 그렇지 않으면 [[CurrentLocalDescription]]반드시 반환해야 한다.

[[CurrentLocalDescription]].sdp[[PendingLocalDescription]].sdp는 대응하는 setLocalDescription 호출에 전달된 sdp 값과 문자열 단위로 동일하지 않을 수 있음에 유의한다 (즉, SDP가 구문 분석되고 다시 형식화되며 ICE 후보가 추가될 수 있다).

currentLocalDescription 유형: RTCSessionDescription, 읽기 전용, null 허용

currentLocalDescription 속성은 [[CurrentLocalDescription]]반드시 반환해야 한다.

이는 RTCPeerConnection이 마지막으로 stable 상태로 전환되었을 때 성공적으로 협상된 로컬 설명과, 제안 또는 응답이 생성된 이후 ICE 에이전트가 생성한 모든 로컬 후보를 나타낸다.

pendingLocalDescription 유형: RTCSessionDescription, 읽기 전용, null 허용

pendingLocalDescription 속성은 [[PendingLocalDescription]]반드시 반환해야 한다.

이는 현재 협상 중인 로컬 설명과, 제안 또는 응답이 생성된 이후 ICE 에이전트가 생성한 모든 로컬 후보를 나타낸다. RTCPeerConnection이 stable 상태이면 값은 null이다.

remoteDescription 유형: RTCSessionDescription, 읽기 전용, null 허용

remoteDescription 속성은 [[PendingRemoteDescription]]null이 아니면 이를 반드시 반환하고, 그렇지 않으면 [[CurrentRemoteDescription]]반드시 반환해야 한다.

[[CurrentRemoteDescription]].sdp[[PendingRemoteDescription]].sdp는 대응하는 setRemoteDescription 호출에 전달된 sdp 값과 문자열 단위로 동일하지 않을 수 있음에 유의한다 (즉, SDP가 구문 분석되고 다시 형식화되며 ICE 후보가 추가될 수 있다).

currentRemoteDescription 유형: RTCSessionDescription, 읽기 전용, null 허용

currentRemoteDescription 속성은 [[CurrentRemoteDescription]]반드시 반환해야 한다.

이는 RTCPeerConnection이 마지막으로 stable 상태로 전환되었을 때 성공적으로 협상된 최종 원격 설명과, 제안 또는 응답이 생성된 이후 addIceCandidate()를 통해 제공된 모든 원격 후보를 나타낸다.

pendingRemoteDescription 유형: RTCSessionDescription, 읽기 전용, null 허용

pendingRemoteDescription 속성은 [[PendingRemoteDescription]]반드시 반환해야 한다.

이는 현재 협상 중인 원격 설명과, 제안 또는 응답이 생성된 이후 addIceCandidate()를 통해 제공된 모든 원격 후보를 나타낸다. RTCPeerConnection이 stable 상태이면 값은 null이다.

signalingState의 유형: RTCSignalingState, 읽기 전용

signalingState 속성은 RTCPeerConnection 객체의 [[SignalingState]]반드시 반환해야 한다.

iceGatheringState 유형: RTCIceGatheringState, 읽기 전용

iceGatheringState 속성은 RTCPeerConnection 객체의 [[IceGatheringState]]반드시 반환해야 한다.

iceConnectionState 유형: RTCIceConnectionState, 읽기 전용

iceConnectionState 속성은 RTCPeerConnection 객체의 [[IceConnectionState]]반드시 반환해야 한다.

connectionState 유형: RTCPeerConnectionState, 읽기 전용

connectionState 속성은 RTCPeerConnection 객체의 [[ConnectionState]]반드시 반환해야 한다.

canTrickleIceCandidates의 유형: boolean, 읽기 전용, null 허용

canTrickleIceCandidates 속성은 원격 피어가 Trickle ICE 후보를 수락할 수 있는지를 나타낸다 [RFC8838]. 이 값은 [RFC9429] (4.1.17절 )에 정의된 대로 원격 설명이 Trickle ICE 지원을 나타내는지에 따라 결정된다. setRemoteDescription이 완료되기 전에는 이 값이 null이다.

onnegotiationneeded의 유형: EventHandler
이 이벤트 처리기의 이벤트 유형은 negotiationneeded이다.
onicecandidate의 유형: EventHandler
이 이벤트 처리기의 이벤트 유형은 icecandidate이다.
onicecandidateerror의 유형: EventHandler
이 이벤트 처리기의 이벤트 유형은 icecandidateerror이다.
onsignalingstatechange의 유형: EventHandler
이 이벤트 처리기의 이벤트 유형은 signalingstatechange이다.
oniceconnectionstatechange의 유형: EventHandler
이 이벤트 처리기의 이벤트 유형은 iceconnectionstatechange
onicegatheringstatechange의 유형: EventHandler
이 이벤트 처리기의 이벤트 유형은 icegatheringstatechange이다.
onconnectionstatechange의 유형: EventHandler
이 이벤트 처리기의 이벤트 유형은 connectionstatechange이다.
메서드
createOffer

createOffer 메서드는 이 RTCPeerConnection에 연결된 로컬 MediaStreamTrack의 설명, 이 구현이 지원하는 코덱/RTP/RTCP 기능, ICE 에이전트와 DTLS 연결의 매개변수를 포함하여 세션에 지원되는 구성이 담긴 RFC 3264 제안을 포함하는 SDP 블롭을 생성한다. 생성되는 제안을 추가로 제어하기 위해 options 매개변수를 제공할 수 있다.

시스템의 리소스가 제한된 경우(예: 디코더 수가 유한한 경우), createOffer는 시스템의 현재 상태를 반영하는 제안을 반환해야 한다. 그래야 setLocalDescription이 해당 리소스를 확보하려고 할 때 성공한다. 세션 설명은 반환된 프로미스의 이행 콜백이 끝날 때까지 오류를 발생시키지 않고 setLocalDescription에서 사용할 수 있는 상태를 반드시 유지해야 한다.

SDP 생성은 [RFC9429]에 설명된 적절한 제안 생성 절차를 반드시 따라야 한다. 다만 이 경우 사용자 에이전트는 RFC9429의 목적상 stopping 트랜시버를 stopped반드시 취급해야 한다.

생성된 SDP는 제안이므로 세션에서 지원하거나 선호하는 코덱/RTP/RTCP 기능의 전체 집합을 포함한다 (사용할 특정 협상 하위 집합만 포함하는 응답과는 다르다). 세션이 설정된 후 createOffer가 호출되는 경우, createOffer는 트랙 추가 또는 제거처럼 마지막으로 완료된 제안-응답 교환 이후 세션에 적용된 모든 변경 사항을 통합하여 현재 세션과 호환되는 제안을 생성한다. 변경 사항이 없으면 제안에는 현재 로컬 설명의 기능과 갱신된 제안에서 추가로 협상할 수 있는 기능이 포함된다.

생성된 SDP에는 ICE 에이전트usernameFragment, password 및 ICE 옵션([RFC5245] 14절에 정의됨)이 포함되며, 에이전트가 수집한 모든 로컬 후보도 포함될 수 있다.

RTCPeerConnectionconfiguration에 있는 certificates 값은 애플리케이션이 RTCPeerConnection에 구성한 인증서를 제공한다. 이러한 인증서는 모든 기본 인증서와 함께 인증서 지문 집합을 생성하는 데 사용된다. 이 인증서 지문은 SDP 구성에 사용된다.

SDP 생성 과정은 기반 시스템의 미디어 기능 중 일부를 노출하며, 이는 일반적으로 기기에 관한 지속적인 교차 출처 정보를 제공한다. 따라서 애플리케이션의 핑거프린팅 노출 면적이 증가한다. 개인정보 보호에 민감한 환경에서 브라우저는 공통 기능 하위 집합에만 일치하는 SDP를 생성하는 등의 완화책을 고려할 수 있다. (이는 핑거프린팅 벡터이다.)

이 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. connection을 메서드가 호출된 RTCPeerConnection 객체로 한다.

  2. connection.[[IsClosed]]true이면, 새로 생성된 InvalidStateError거부된 프로미스를 반환한다.

  3. connection으로 제안을 생성한 결과를 connection작업 체인연결한 결과를 반환한다.

connection이 주어졌을 때 제안을 생성하려면 다음 단계를 실행한다:

  1. connection.[[SignalingState]]이 "stable"도 아니고 "have-local-offer"도 아니면, 새로 생성된 InvalidStateError거부된 프로미스를 반환한다.

  2. p를 새 프로미스로 한다.

  3. 병렬로, connectionp가 주어졌을 때의 제안을 생성하는 병렬 단계를 시작한다.

  4. p를 반환한다.

connection과 프로미스 p가 주어졌을 때의 제안을 생성하는 병렬 단계는 다음과 같다:

  1. connection이 인증서 집합을 사용하여 생성되지 않았고 아직 인증서가 생성되지 않았다면, 인증서가 생성될 때까지 기다린다.

  2. [RFC9429] (4.1.8절 )에 설명된 대로, 제안을 생성하는 데 필요한 현재 사용 가능한 리소스를 확인하기 위해 제안자의 시스템 상태를 검사한다.

  3. 이 검사가 어떤 이유로든 실패하면 새로 생성된 OperationErrorp거부하고 이 단계들을 중단한다.

  4. connectionp가 주어졌을 때의 제안 생성의 최종 단계를 실행하는 태스크를 대기열에 추가한다.

connection과 프로미스 p가 주어졌을 때의 제안 생성의 최종 단계는 다음과 같다:

  1. connection.[[IsClosed]]true이면 이 단계들을 중단한다.

  2. connection제안자의 시스템 상태를 추가로 검사해야 하는 방식으로 수정되었다면, 병렬로 connectionp가 주어진 제안을 생성하는 병렬 단계를 다시 시작하고 이 단계들을 중단한다.

    참고
    예를 들어 오디오 RTCRtpTransceiverconnection에 추가된 상태에서 createOffer가 호출되었지만, 제안을 생성하는 병렬 단계를 수행하는 동안 비디오 RTCRtpTransceiver가 추가되어 비디오 시스템 리소스를 추가로 검사해야 하는 경우가 이에 해당할 수 있다.
  3. 이전 검사에서 얻은 정보와 connection 및 그 RTCRtpTransceiver들의 현재 상태를 바탕으로, [RFC9429] (5.2절 )에 설명된 SDP 제안 sdpString을 생성한다.

    1. [RFC8843] 7절에 설명된 대로 번들링을 사용하는 경우 (RTCBundlePolicy 참조), BUNDLE 그룹을 협상하려면 제안자 태그가 지정된 m= 섹션을 선택해야 한다. 사용자 에이전트는 트랜시버 집합에서 중지되지 않은 첫 번째 트랜시버에 대응하는 m= 섹션을 제안자 태그가 지정된 m= 섹션으로 반드시 선택해야 한다. 이렇게 하면 원격 엔드포인트가 SDP를 구문 분석하지 않고도 어떤 트랜시버가 제안자 태그가 지정된 m= 섹션인지 예측할 수 있다.

    2. filteredCodecstransceiver.[[PreferredCodecs]]에 다음 필터를 적용한 결과로 한다. 필터링은 코덱 선호도의 순서를 변경해서는 안 된다:

      1. kindtransceiver[[Receiver]][[ReceiverTrack]]kind로 한다.

      2. transceiver.direction이 "sendonly" 또는 "sendrecv"이면, ignoreLevelstrue로 설정한 코덱 사전 일치 알고리즘을 사용하여 kind구현된 송신 코덱 목록에 포함되지 않은 코덱을 제외한다.

      3. transceiver.direction이 "recvonly" 또는 "sendrecv"이면, ignoreLevelstrue로 설정한 코덱 사전 일치 알고리즘을 사용하여 kind구현된 수신 코덱 목록에 포함되지 않은 코덱을 제외한다.

      미디어 설명연결된 트랜시버 transceiver코덱 선호도filteredCodecs가 비어 있지 않으면 그 값으로 정의되고, 그렇지 않으면 설정되지 않은 것으로 정의된다.

    3. RTCRtpSender[[SendEncodings]] 슬롯의 길이가 1보다 크면, RTCRtpSender[[SendEncodings]]에 주어진 각 인코딩에 대해 대응하는 미디어 섹션에 a=rid send 줄을 추가하고, encodings 필드에 지정된 것과 같은 순서로 RID를 나열하는 a=simulcast:send 줄을 추가한다. RID 제한은 설정하지 않는다.

      참고

      [RFC8853] 5.2절은 a=simulcast 줄에 있는 RID의 순서가 제안된 선호 순서를 나타낸다고 규정한다. 브라우저가 모든 인코딩을 전송하지 않기로 결정하면 목록의 마지막 인코딩부터 전송을 중지할 것으로 예상해야 한다.

  4. offer를 새로 생성된 RTCSessionDescriptionInit 사전으로 한다. 이 사전의 type 멤버는 문자열 "offer"로 초기화하고, sdp 멤버는 sdpString으로 초기화한다.

  5. [[LastCreatedOffer]] 내부 슬롯을 sdpString으로 설정한다.

  6. poffer이행한다.

createAnswer

createAnswer 메서드는 원격 구성의 매개변수와 호환되는 세션 지원 구성을 포함한 [SDP] 응답을 생성한다. createOffer와 마찬가지로 반환되는 SDP 블롭에는 이 RTCPeerConnection에 연결된 로컬 MediaStreamTrack의 설명, 이 세션에 대해 협상된 코덱/RTP/RTCP 옵션, ICE 에이전트가 수집한 모든 후보가 포함된다. 생성되는 응답을 추가로 제어하기 위해 options 매개변수를 제공할 수 있다.

createOffer와 마찬가지로 반환되는 설명은 시스템의 현재 상태를 반영하는 것이 좋다. 세션 설명은 반환된 프로미스의 이행 콜백이 끝날 때까지 오류를 발생시키지 않고 setLocalDescription에서 사용할 수 있는 상태를 반드시 유지해야 한다.

생성된 SDP는 응답이므로, 대응하는 제안과 함께 미디어 평면을 설정하는 방법을 지정하는 특정 코덱/RTP/RTCP 구성을 포함한다. SDP 생성은 [RFC9429]에 설명된 적절한 응답 생성 절차를 반드시 따라야 한다.

생성된 SDP에는 ICE 에이전트usernameFragment, password 및 ICE 옵션([RFC5245] 14절에 정의됨)이 포함되며, 에이전트가 수집한 모든 로컬 후보도 포함될 수 있다.

RTCPeerConnectionconfiguration에 있는 certificates 값은 애플리케이션이 RTCPeerConnection에 구성한 인증서를 제공한다. 이러한 인증서는 모든 기본 인증서와 함께 인증서 지문 집합을 생성하는 데 사용된다. 이 인증서 지문은 SDP 구성에 사용된다.

응답은 [RFC9429] (4.1.10.1절 )에 설명된 대로 type을 "pranswer"로 설정하여 임시 응답으로 표시할 수 있다.

이 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. connection을 메서드가 호출된 RTCPeerConnection 객체로 한다.

  2. connection.[[IsClosed]]true이면, 새로 생성된 InvalidStateError거부된 프로미스를 반환한다.

  3. connection으로 응답을 생성한 결과를 connection작업 체인연결한 결과를 반환한다.

connection이 주어졌을 때 응답을 생성하려면 다음 단계를 실행한다:

  1. connection.[[SignalingState]]이 "have-remote-offer"도 아니고 "have-local-pranswer"도 아니면, 새로 생성된 InvalidStateError거부된 프로미스를 반환한다.

  2. p를 새 프로미스로 한다.

  3. 병렬로, connectionp가 주어졌을 때의 응답을 생성하는 병렬 단계를 시작한다.

  4. p를 반환한다.

connection과 프로미스 p가 주어졌을 때의 응답을 생성하는 병렬 단계는 다음과 같다:

  1. connection이 인증서 집합을 사용하여 생성되지 않았고 아직 인증서가 생성되지 않았다면, 인증서가 생성될 때까지 기다린다.

  2. [RFC9429] (4.1.9절 )에 설명된 대로, 응답을 생성하는 데 필요한 현재 사용 가능한 리소스를 확인하기 위해 응답자의 시스템 상태를 검사한다.

  3. 이 검사가 어떤 이유로든 실패하면 새로 생성된 OperationErrorp거부하고 이 단계들을 중단한다.

  4. p가 주어졌을 때의 응답 생성의 최종 단계를 실행하는 태스크를 대기열에 추가한다.

프로미스 p가 주어졌을 때의 응답 생성의 최종 단계는 다음과 같다:

  1. connection.[[IsClosed]]true이면 이 단계들을 중단한다.

  2. connection응답자의 시스템 상태를 추가로 검사해야 하는 방식으로 수정되었다면, 병렬로 connectionp가 주어진 응답을 생성하는 병렬 단계를 다시 시작하고 이 단계들을 중단한다.

    참고
    예를 들어 RTCRtpTransceiver의 방향이 "recvonly"일 때 createAnswer가 호출되었지만, 응답을 생성하는 병렬 단계를 수행하는 동안 방향이 "sendrecv"로 변경되어 비디오 인코딩 리소스를 추가로 검사해야 하는 경우가 이에 해당할 수 있다.
  3. 이전 검사에서 얻은 정보와 connection 및 그 RTCRtpTransceiver들의 현재 상태를 바탕으로, [RFC9429] (5.3절 )에 설명된 SDP 응답 sdpString을 생성한다.

    후보 수정 26:createAnswer()의 encodings와 sLD(answer)의 SendEncodings 가지치기. (PR #2801)
    후보 수정 27:쉼표로 구분된 rid 대안 무시. (PR #2813)
    1. m= 섹션과 연결된 트랜시버의 코덱 선호도는 다음 필터링이 적용된 RTCRtpTransceiver.[[PreferredCodecs]]의 값으로 정의된다([[PreferredCodecs]]가 비어 있으면 설정되지 않은 것으로 정의된다):

      1. direction이 "sendrecv"이면, RTCRtpSender.getCapabilities(kind).codecsRTCRtpReceiver.getCapabilities(kind).codecs의 교집합에 포함되지 않은 코덱을 제외한다.

      2. direction이 "sendonly"이면, RTCRtpSender.getCapabilities(kind).codecs에 포함되지 않은 코덱을 제외한다.

      3. direction이 "recvonly"이면, RTCRtpReceiver.getCapabilities(kind).codecs에 포함되지 않은 코덱을 제외한다.

      필터링은 코덱 선호도의 순서를 변경해서는 안 된다.

    2. RTCRtpSender[[SendEncodings]] 슬롯의 길이가 1보다 크면, RTCRtpSender[[SendEncodings]]에 지정된 각 인코딩에 대해 대응하는 미디어 섹션에 a=rid send 줄을 추가하고, RID를 encodings 필드에 지정된 것과 같은 순서로 나열하는 a=simulcast:send 줄을 추가한다. RID 제한은 설정하지 않는다.

    3. filteredCodecstransceiver.[[PreferredCodecs]]에 다음 필터를 적용한 결과로 한다. 필터링은 코덱 선호도의 순서를 변경해서는 안 된다:

      1. kindtransceiver[[Receiver]][[ReceiverTrack]]kind로 한다.

      2. transceiver.direction이 "sendonly" 또는 "sendrecv"이면, ignoreLevelstrue로 설정한 코덱 사전 일치 알고리즘을 사용하여 kind구현된 송신 코덱 목록에 포함되지 않은 코덱을 제외한다.

      3. transceiver.direction이 "recvonly" 또는 "sendrecv"이면, ignoreLevelstrue로 설정한 코덱 사전 일치 알고리즘을 사용하여 kind구현된 수신 코덱 목록에 포함되지 않은 코덱을 제외한다.

      미디어 설명연결된 트랜시버 transceiver코덱 선호도filteredCodecs가 비어 있지 않으면 그 값으로 정의되고, 그렇지 않으면 설정되지 않은 것으로 정의된다.

    4. 이것이 동시 송출 수신 제안에 대한 응답이면, 동시 송출 수신을 요청하는 각 미디어 섹션에 대해 다음 단계를 실행한다:

      1. a=simulcast 속성에 RID의 쉼표로 구분된 대안이 포함되어 있으면 첫 번째 항목을 제외한 나머지를 모두 제거한다.

      2. a=simulcast 속성에 이름이 같은 RID가 있으면 첫 번째 항목을 제외한 나머지를 모두 제거한다. RID 제한은 설정하지 않는다.

      3. 대응하는 트랜시버의 [[Sender]].[[SendEncodings]]에서 찾을 수 없는 RID를 응답의 미디어 섹션에서 제외한다.

      참고

      setRemoteDescription(offer)가 송신자의 제안된 엔벌로프를 설정하면, 송신자의 [[SendEncodings]]은 "have-remote-offer"에서 갱신되어 롤백에 노출된다. 그러나 송신자에 대해 동시 송출 엔벌로프가 설정된 후에는, 송신자의 [[SendEncodings]]에 대한 이후의 가지치기는 이 응답이 setLocalDescription으로 설정될 때 발생한다.

  4. answer를 새로 생성된 RTCSessionDescriptionInit 사전으로 한다. 이 사전의 type 멤버는 문자열 "answer"로 초기화하고, sdp 멤버는 sdpString으로 초기화한다.

  5. [[LastCreatedAnswer]] 내부 슬롯을 sdpString으로 설정한다.

  6. panswer이행한다.

setLocalDescription

setLocalDescription 메서드는 제공된 RTCLocalSessionDescriptionInit을 로컬 설명으로 적용하도록 RTCPeerConnection에 지시한다.

이 API는 로컬 미디어 상태를 변경한다. 애플리케이션이 한 미디어 형식에서 호환되지 않는 다른 형식으로 변경하도록 제안하려는 시나리오를 성공적으로 처리하기 위해, RTCPeerConnection은 최종 응답을 받을 때까지 현재 로컬 설명과 보류 중인 로컬 설명을 모두 동시에 사용할 수 있도록 반드시 지원해야 한다 (예: 두 설명에 모두 존재하는 코덱을 지원해야 한다). 최종 응답을 받으면 RTCPeerConnection은 보류 중인 로컬 설명을 완전히 채택하거나, 원격 측이 변경을 거부했다면 현재 설명으로 롤백할 수 있다.

설명 전달은 선택 사항이다. 생략하면 setLocalDescription은 필요에 따라 암시적으로 제안을 생성하거나 응답을 생성한다. [RFC9429] (5.4절 )에 명시된 것처럼 SDP가 포함된 설명을 전달하는 경우, 해당 SDP는 createOffer 또는 createAnswer에서 반환된 이후 변경되어서는 안 된다.

이 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. description을 메서드의 첫 번째 인수로 한다.

  2. connection을 메서드가 호출된 RTCPeerConnection 객체로 한다.

  3. sdpdescription.sdp로 한다.

  4. 다음 단계들을 connection작업 체인연결한 결과를 반환한다:

    1. typedescription.type이 있으면 그 값으로 한다. 없고 connection.[[SignalingState]]이 "stable", "have-local-offer" 또는 "have-remote-pranswer" 중 하나이면 "offer"로 한다. 그렇지 않으면 "answer"로 한다.

    2. type이 "offer"이고, sdp가 빈 문자열이 아니며 connection.[[LastCreatedOffer]]와 같지 않으면, 새로 생성된 InvalidModificationError거부된 프로미스를 반환하고 이 단계들을 중단한다.

    3. type이 "answer" 또는 "pranswer"이고, sdp가 빈 문자열이 아니며 connection.[[LastCreatedAnswer]]와 같지 않으면, 새로 생성된 InvalidModificationError거부된 프로미스를 반환하고 이 단계들을 중단한다.

    4. sdp가 빈 문자열이고 type이 "offer"이면 다음 하위 단계를 실행한다:

      1. sdpconnection.[[LastCreatedOffer]]의 값으로 설정한다.

      2. sdp가 빈 문자열이거나 더 이상 connection제안자의 시스템 상태를 정확히 나타내지 않으면, pconnection으로 제안을 생성한 결과로 하고, p에 첫 번째 인수가 나타내는 로컬 세션 설명을 설정하는 이행 단계로 반응한 결과를 반환한다.

    5. sdp가 빈 문자열이고 type이 "answer" 또는 "pranswer"이면, 다음 하위 단계를 실행한다:

      1. sdpconnection.[[LastCreatedAnswer]]의 값으로 설정한다.

      2. sdp가 빈 문자열이거나 더 이상 connection응답자의 시스템 상태를 정확히 나타내지 않으면, pconnection으로 응답을 생성한 결과로 하고, 다음 이행 단계로 p반응한 결과를 반환한다:

        1. answer를 이 이행 단계의 첫 번째 인수로 한다.

        2. {type, answer.sdp}가 나타내는 로컬 세션 설명을 설정한 결과를 반환한다.

    6. {type, sdp}가 나타내는 로컬 세션 설명을 설정한 결과를 반환한다.

참고

[RFC9429] (5.9절 )에 명시된 것처럼 이 메서드를 호출하면 ICE 에이전트의 ICE 후보 수집 절차가 시작될 수 있다.

setRemoteDescription

setRemoteDescription 메서드는 제공된 RTCSessionDescriptionInit을 원격 제안 또는 응답으로 적용하도록 RTCPeerConnection에 지시한다. 이 API는 로컬 미디어 상태를 변경한다.

이 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. description을 메서드의 첫 번째 인수로 한다.

  2. connection을 메서드가 호출된 RTCPeerConnection 객체로 한다.

  3. 다음 단계들을 connection작업 체인연결한 결과를 반환한다:

    1. description.type이 "offer"이고 [RFC9429] (5.5절 5.6절 )에 설명된 현재 connection.[[SignalingState]]에 유효하지 않으면 다음 하위 단계를 실행한다:

      1. p{type: "rollback"}이 나타내는 로컬 세션 설명을 설정한 결과로 한다.

      2. pdescription원격 세션 설명으로 설정하는 이행 단계로 반응한 결과를 반환하고, 이 단계들을 중단한다.

    2. description원격 세션 설명으로 설정한 결과를 반환한다.

addIceCandidate

addIceCandidate 메서드는 원격 후보를 ICE 에이전트에 제공한다. 이 메서드는 candidate 멤버가 빈 문자열인 상태로 호출하면 원격 후보의 끝을 나타내는 데도 사용할 수 있다. 이 메서드가 사용하는 인수의 멤버는 candidate, sdpMid, sdpMLineIndex, 그리고 usernameFragment뿐이며, 나머지는 무시된다. 이 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. candidate를 메서드의 인수로 한다.

  2. connection을 메서드가 호출된 RTCPeerConnection 객체로 한다.

  3. candidate.candidate가 빈 문자열이 아니고, candidate.sdpMidcandidate.sdpMLineIndex가 모두 null이면, 새로 생성된 TypeError거부된 프로미스를 반환한다.

  4. 다음 단계들을 connection작업 체인연결한 결과를 반환한다:

    1. remoteDescriptionnull이면 새로 생성된 InvalidStateError거부된 프로미스를 반환한다.

    2. candidate.sdpMidnull이 아니면 다음 단계를 실행한다:

      1. candidate.sdpMidremoteDescription에 있는 어떤 미디어 설명의 mid와도 같지 않으면, 새로 생성된 OperationError거부된 프로미스를 반환한다.

    3. 그렇지 않고 candidate.sdpMLineIndexnull이 아니면 다음 단계를 실행한다:

      1. candidate.sdpMLineIndexremoteDescription의 미디어 설명 수 이상이면, 새로 생성된 OperationError거부된 프로미스를 반환한다.

    4. candidate.sdpMid 또는 candidate.sdpMLineIndex 중 하나가 remoteDescription에서 연결된 트랜시버가 stopped인 미디어 설명을 나타내면, undefined이행된 프로미스를 반환한다.

    5. candidate.usernameFragmentnull이 아니고, 적용된 원격 설명의 대응하는 미디어 설명에 존재하는 어떤 사용자 이름 프래그먼트와도 같지 않으면, 새로 생성된 OperationError거부된 프로미스를 반환한다.

    6. p를 새 프로미스로 한다.

    7. 병렬로, 후보가 관리상 금지되지 않았다면, [RFC9429] (4.1.19절 )에 설명된 대로 ICE 후보 candidate를 추가한다. ICE 세대를 식별하려면 candidate.usernameFragment를 사용한다. usernameFragmentnull이면 가장 최근 ICE 세대에 대해 candidate를 처리한다.

      candidate.candidate가 빈 문자열이면 candidate를 대응하는 미디어 설명과 ICE 후보 세대에 대한 후보 끝 표시로 처리한다. candidate.sdpMidcandidate.sdpMLineIndex가 모두 null이면 이 후보 끝 표시는 모든 미디어 설명에 적용된다.

      1. candidate를 성공적으로 추가하지 못했다면 사용자 에이전트는 다음 단계를 실행하는 태스크를 반드시 대기열에 추가해야 한다:

        1. connection.[[IsClosed]]true이면 이 단계들을 중단한다.

        2. 새로 생성된 OperationErrorp거부하고 이 단계들을 중단한다.

      2. candidate가 성공적으로 적용되었거나 후보가 관리상 금지된 경우, 사용자 에이전트는 다음 단계를 실행하는 태스크를 반드시 대기열에 추가해야 한다:

        1. connection.[[IsClosed]]true이면 이 단계들을 중단한다.

        2. connection.[[PendingRemoteDescription]]null이 아니고 candidate가 처리된 ICE 세대를 나타내면, candidateconnection.[[PendingRemoteDescription]].sdp에 추가한다.

        3. connection.[[CurrentRemoteDescription]]null이 아니고 candidate가 처리된 ICE 세대를 나타내면, candidateconnection.[[CurrentRemoteDescription]].sdp에 추가한다.

        4. pundefined이행한다.

    8. p를 반환한다.

UA가 이 주소에 대한 연결 시도를 허용하지 않기로 결정한 경우 후보는 관리상 금지된 것이다.

개인정보 보호를 위해 개발자에게 주소/포트의 차단 여부를 알리지 않는다. 해당 주소에서 응답이 전혀 없는 것과 정확히 같은 방식으로 동작한다.

UA는 [Fetch]의 잘못된 포트 차단 목록에 있는 주소로의 연결을 반드시 금지해야 하며, 다른 주소로의 연결도 금지하도록 선택할 수 있다.

RTCConfigurationiceTransportPolicy 멤버가 relay이면, mDNS 후보나 DNS 후보처럼 외부 확인이 필요한 후보는 반드시 금지해야 한다.

참고

WebIDL 처리로 인해 addIceCandidate(null)은 기본 사전이 존재하는 호출로 해석된다. 위 알고리즘에서 이는 모든 미디어 설명과 ICE 후보 세대에 대한 후보 끝을 나타낸다. 이는 레거시 사유로 의도된 동작이다.

restartIce

restartIce 메서드는 ICE를 다시 시작해야 한다고 RTCPeerConnection에 알린다. 이후 createOffer 호출은 [RFC5245] 9.1.1.1절에 설명된 대로 ICE를 다시 시작하는 설명을 생성한다.

이 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. connection을 메서드가 호출된 RTCPeerConnection으로 한다.

  2. connection.[[LocalIceCredentialsToReplace]]를 비운 다음, connection.[[CurrentLocalDescription]]에서 찾은 모든 ICE 자격 증명과 connection.[[PendingLocalDescription]]에서 찾은 모든 ICE 자격 증명([RFC5245] 15.4절에 정의된 ice-ufrag 및 ice-pwd)으로 채운다.

  3. connection협상 필요 플래그를 갱신한다.

getConfiguration

RTCPeerConnection 객체의 현재 구성을 나타내는 RTCConfiguration 객체를 반환한다.

이 메서드가 호출되면 사용자 에이전트는 [[Configuration]] 내부 슬롯에 저장된 RTCConfiguration 객체를 반드시 반환해야 한다.

setConfiguration

setConfiguration 메서드는 이 RTCPeerConnection 객체의 구성을 갱신한다. 여기에는 ICE 에이전트의 구성 변경도 포함된다. [RFC9429] (3.5.1절 )에 명시된 것처럼 ICE 구성이 새 수집 단계를 요구하는 방식으로 변경되면 ICE를 다시 시작해야 한다.

setConfiguration 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. connection을 메서드가 호출된 RTCPeerConnection으로 한다.

  2. connection.[[IsClosed]]true이면 다음 예외를 던진다: InvalidStateError.

  3. configuration이 지정한 구성을 설정한다.

close

close 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 한다:

  1. connection을 메서드가 호출된 RTCPeerConnection 객체로 한다.

  2. connectionfalse 값을 사용하여 연결을 닫는다.

connection과 불리언 disappear가 주어졌을 때 연결을 닫는 알고리즘은 다음과 같다:

  1. connection.[[IsClosed]]true이면 이 단계들을 중단한다.

  2. connection.[[IsClosed]]true로 설정한다.

  3. connection.[[SignalingState]]을 "closed"로 설정한다. 이때는 어떤 이벤트도 발생하지 않는다.

  4. transceiversCollectTransceivers 알고리즘을 실행한 결과로 한다. transceivers의 모든 RTCRtpTransceiver transceiver에 대해 다음 단계를 실행한다:

    1. transceiver.[[Stopped]]true이면 이 하위 단계들을 중단한다.

    2. transceiverdisappear를 사용하여 RTCRtpTransceiver를 중지한다.

  5. connection의 각 RTCDataChannel[[ReadyState]] 슬롯을 "closed"로 설정한다.

    참고
    RTCDataChannel은 갑자기 닫히며 닫기 절차는 호출되지 않는다.
  6. connection.[[SctpTransport]]null이 아니면 SCTP ABORT 청크를 전송하여 기반 SCTP 연결을 해제하고, [[SctpTransportState]]을 "closed"로 설정한다.

  7. connection의 각 RTCDtlsTransport[[DtlsTransportState]] 슬롯을 "closed"로 설정한다.

  8. connectionICE 에이전트를 제거하여 활성 ICE 처리를 즉시 종료하고 관련 리소스 (예: TURN 권한)를 해제한다.

  9. connection의 각 RTCIceTransport[[IceTransportState]] 슬롯을 "closed"로 설정한다.

  10. connection.[[IceConnectionState]]을 "closed"로 설정한다. 이때는 어떤 이벤트도 발생하지 않는다.

  11. connection.[[ConnectionState]]을 "closed"로 설정한다. 이때는 어떤 이벤트도 발생하지 않는다.

4.4.3 레거시 인터페이스 확장

참고
메서드들의 IDL 정의는 다음 인터페이스의 주 정의에 문서화되어 있다: RTCPeerConnection. 오버로드된 함수는 부분 인터페이스에 정의할 수 없기 때문이다.

이 절의 메서드 지원 여부는 선택 사항이다. 그러나 이 메서드들을 지원하는 경우에는 여기에 명시된 내용에 따라 반드시 구현해야 한다.

참고
addStream 메서드는 RTCPeerConnection에 존재했으며, 다음과 같이 쉽게 폴리필할 수 있다:
RTCPeerConnection.prototype.addStream = function(stream) {
  stream.getTracks().forEach((track) => this.addTrack(track, stream));
};
4.4.3.1 메서드 확장
메서드
createOffer

createOffer 메서드가 호출되면, 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. successCallback을 메서드의 첫 번째 인수로 한다.

  2. failureCallback을 메서드의 두 번째 인수가 나타내는 콜백으로 한다.

  3. options을 메서드의 세 번째 인수가 나타내는 콜백으로 한다.

  4. RTCPeerConnectioncreateOffer() 메서드에 지정된 단계를 실행한다. 인수는 options 하나뿐이며, p를 그 결과로 생성된 프로미스로 한다.

  5. 이행되는 p의 값이 offer인 경우, successCallbackoffer를 인수로 하여 호출한다.

  6. 거부되는 p의 이유가 r인 경우, failureCallbackr를 인수로 하여 호출한다.

  7. 프로미스를 반환한다. 이 프로미스는 해결되며 그 값은 undefined이다.

setLocalDescription

setLocalDescription 메서드가 호출되면, 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. description을 메서드의 첫 번째 인수로 한다.

  2. successCallback을 메서드의 두 번째 인수가 나타내는 콜백으로 한다.

  3. failureCallback을 메서드의 세 번째 인수가 나타내는 콜백으로 한다.

  4. RTCPeerConnectionsetLocalDescription 메서드에 지정된 단계를 실행한다. 인수는 description 하나뿐이며, p를 그 결과로 생성된 프로미스로 한다.

  5. 이행되는 p의 경우, successCallbackundefined를 인수로 하여 호출한다.

  6. 거부되는 p의 이유가 r인 경우, failureCallbackr를 인수로 하여 호출한다.

  7. 프로미스를 반환한다. 이 프로미스는 해결되며 그 값은 undefined이다.

createAnswer
참고
레거시 createAnswer 메서드는 RTCAnswerOptions 매개변수를 받지 않는다. 알려진 레거시 createAnswer 구현 중 이를 지원한 사례가 없기 때문이다.

createAnswer 메서드가 호출되면, 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. successCallback을 메서드의 첫 번째 인수로 한다.

  2. failureCallback을 메서드의 두 번째 인수가 나타내는 콜백으로 한다.

  3. RTCPeerConnectioncreateAnswer() 메서드에 지정된 단계를 실행한다. 인수는 없으며, p를 그 결과로 생성된 프로미스로 한다.

  4. 이행되는 p의 값이 answer인 경우, successCallbackanswer를 인수로 하여 호출한다.

  5. 거부되는 p의 이유가 r인 경우, failureCallbackr를 인수로 하여 호출한다.

  6. 프로미스를 반환한다. 이 프로미스는 해결되며 그 값은 undefined이다.

setRemoteDescription

setRemoteDescription 메서드가 호출되면, 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. description을 메서드의 첫 번째 인수로 한다.

  2. successCallback을 메서드의 두 번째 인수가 나타내는 콜백으로 한다.

  3. failureCallback을 메서드의 세 번째 인수가 나타내는 콜백으로 한다.

  4. RTCPeerConnectionsetRemoteDescription 메서드에 지정된 단계를 실행한다. 인수는 description 하나뿐이며, p를 그 결과로 생성된 프로미스로 한다.

  5. 이행되는 p의 경우, successCallbackundefined를 인수로 하여 호출한다.

  6. 거부되는 p의 이유가 r인 경우, failureCallbackr를 인수로 하여 호출한다.

  7. 프로미스를 반환한다. 이 프로미스는 해결되며 그 값은 undefined이다.

addIceCandidate

addIceCandidate 메서드가 호출되면, 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. candidate을 메서드의 첫 번째 인수로 한다.

  2. successCallback을 메서드의 두 번째 인수가 나타내는 콜백으로 한다.

  3. failureCallback을 메서드의 세 번째 인수가 나타내는 콜백으로 한다.

  4. RTCPeerConnectionaddIceCandidate() 메서드에 지정된 단계를 실행한다. 인수는 candidate 하나뿐이며, p를 그 결과로 생성된 프로미스로 한다.

  5. 이행되는 p의 경우, successCallbackundefined를 인수로 하여 호출한다.

  6. 거부되는 p의 이유가 r인 경우, failureCallbackr를 인수로 하여 호출한다.

  7. 프로미스를 반환한다. 이 프로미스는 해결되며 그 값은 undefined이다.

콜백 정의

이 콜백들은 레거시 API에서만 사용된다.

RTCPeerConnectionErrorCallback
WebIDLcallback RTCPeerConnectionErrorCallback = undefined (DOMException error);
콜백 RTCPeerConnectionErrorCallback 매개변수
error의 형식은 DOMException
발생한 문제에 관한 정보를 캡슐화한 오류 객체이다.
RTCSessionDescriptionCallback
WebIDLcallback RTCSessionDescriptionCallback = undefined (RTCSessionDescriptionInit description);
콜백 RTCSessionDescriptionCallback 매개변수
description의 형식은 RTCSessionDescriptionInit
SDP [SDP]를 포함하는 객체이다.
4.4.3.2 레거시 구성 확장

이 절에서는 제안 생성 방식에 영향을 주는 데 사용할 수 있는 레거시 확장 집합을 설명한다. 이는 다음에 추가된 미디어와 함께 사용된다: RTCPeerConnection. 개발자는 RTCRtpTransceiver API를 대신 사용하는 것이 좋다.

createOffer가 이 절에 지정된 레거시 옵션 중 하나라도 포함하여 호출되면, 일반 createOffer 단계 대신 다음 단계를 실행한다:

  1. options을 메서드의 첫 번째 인수로 한다.

  2. connection을 현재 RTCPeerConnection 객체로 한다.

  3. offerToReceive<Kind> 멤버에 대해, options에서 kind가 kind인 경우 다음 단계를 실행한다:

    1. 사전 멤버의 값이 false이면 다음을 수행한다:
      1. 중지되지 않은 각 "sendrecv" 트랜시버 중 트랜시버 종류가 kind인 것에 대해, transceiver.[[Direction]]을 "sendonly"로 설정한다.

      2. 중지되지 않은 각 "recvonly" 트랜시버 중 트랜시버 종류가 kind인 것에 대해, transceiver.[[Direction]]을 "inactive"로 설정한다.

      다음 옵션이 있는 경우 그 옵션으로 계속한다.

    2. connection에 중지되지 않은 "sendrecv" 또는 "recvonly" 트랜시버가 있고, 그 트랜시버 종류가 kind이면, 다음 옵션이 있는 경우 그 옵션으로 계속한다.

    3. transceiver를 다음 호출과 동등한 작업의 결과로 한다: connection.addTransceiver(kind). 다만 이 작업에서는 다음을 해서는 안 된다: 협상 필요 플래그 갱신.

    4. transceiver가 이전 작업에서 오류가 발생하여 설정되지 않았다면, 이 단계를 중단한다.

    5. transceiver.[[Direction]]을 "recvonly"로 설정한다.

  4. createOffer에 지정된 단계를 실행하여 제안을 생성한다.

WebIDLpartial dictionary RTCOfferOptions {
  boolean offerToReceiveAudio;
  boolean offerToReceiveVideo;
};
속성
offerToReceiveAudio의 형식은 boolean

이 설정은 오디오 방향성을 추가로 제어한다. 예를 들어 오디오 전송 여부와 관계없이 오디오를 수신할 수 있도록 보장하는 데 사용할 수 있다.

offerToReceiveVideo의 형식은 boolean

이 설정은 비디오 방향성을 추가로 제어한다. 예를 들어 비디오 전송 여부와 관계없이 비디오를 수신할 수 있도록 보장하는 데 사용할 수 있다.

4.4.4 가비지 컬렉션

RTCPeerConnection 객체는 반드시 객체에서 이벤트 핸들러가 트리거되게 할 수 있는 이벤트가 하나라도 있는 동안 가비지 컬렉션되어서는 안 된다. 객체의 [[IsClosed]] 내부 슬롯이 true이면 이러한 이벤트 핸들러는 트리거될 수 없으므로 객체를 안전하게 가비지 컬렉션할 수 있다.

모든 RTCDataChannelMediaStreamTrack 객체가 RTCPeerConnection에 연결되어 있으면, 해당 객체는 RTCPeerConnection 객체에 대한 강한 참조를 가진다.

4.5 오류 처리

4.5.1 일반 원칙

프로미스를 반환하는 모든 메서드에는 프로미스의 표준 오류 처리 규칙이 적용된다. 프로미스를 반환하지 않는 메서드는 오류를 나타내기 위해 예외를 던질 수 있다.

4.6 세션 기술 모델

4.6.1 RTCSdpType

RTCSdpType 열거형은 RTCSessionDescriptionInit, RTCLocalSessionDescriptionInit 또는 RTCSessionDescription 인스턴스의 유형을 설명한다.

WebIDLenum RTCSdpType {
  "offer",
  "pranswer",
  "answer",
  "rollback"
};
RTCSdpType 열거형 설명
열거형 값 설명
offer

RTCSdpType의 값이 "offer"이면 기술은 반드시 [SDP] 제안으로 취급해야 한다.

pranswer

RTCSdpType의 값이 "pranswer"이면 기술은 반드시 [SDP] 응답으로 취급해야 하지만 최종 응답은 아니다. SDP pranswer로 사용된 기술은 SDP 제안에 대한 응답이나 이전에 전송한 SDP pranswer의 업데이트로 적용할 수 있다.

answer

RTCSdpType의 값이 "answer"이면 기술은 반드시 [SDP] 최종 응답으로 취급해야 하며, 제안-응답 교환은 반드시 완료된 것으로 간주해야 한다. SDP answer로 사용된 기술은 SDP 제안에 대한 응답이나 이전에 전송한 SDP pranswer의 업데이트로 적용할 수 있다.

rollback

RTCSdpType의 값이 "rollback"이면 기술은 반드시 현재 SDP 협상을 취소하고 SDP [SDP] 제안을 이전 안정 상태로 되돌리는 것으로 취급해야 한다. 이전 안정 상태의 로컬 또는 원격 SDP 기술은 null일 수 있다. 아직 성공적인 제안-응답 협상이 없었던 경우가 이에 해당한다. "answer" 또는 "pranswer"은 롤백할 수 없다.

4.6.2 RTCSessionDescription 클래스

RTCSessionDescription 클래스는 RTCPeerConnection에서 로컬 및 원격 세션 기술을 노출하는 데 사용된다.

WebIDL[Exposed=Window]
interface RTCSessionDescription {
  constructor(RTCSessionDescriptionInit descriptionInitDict);
  readonly attribute RTCSdpType type;
  readonly attribute DOMString sdp;
  [Default] RTCSessionDescriptionInit toJSON();
};
생성자
constructor()

RTCSessionDescription() 생성자는 사전 인수 description을 받으며, 그 내용은 새로운 RTCSessionDescription 객체를 초기화하는 데 사용된다. 이 생성자는 더 이상 사용되지 않으며 레거시 호환성을 위해서만 존재한다.

속성
type의 형식은 RTCSdpType이며 읽기 전용
이 세션 기술의 유형이다.
sdp의 형식은 DOMString이며 읽기 전용이고 기본값은 ""
SDP [SDP]의 문자열 표현이다.
메서드
toJSON()
호출되면 [WEBIDL]의 기본 toJSON 단계를 실행한다.
WebIDLdictionary RTCSessionDescriptionInit {
  required RTCSdpType type;
  DOMString sdp = "";
};
사전 RTCSessionDescriptionInit 멤버
type의 형식은 RTCSdpType이며 필수이다
이 세션 기술의 유형이다.
sdp의 형식은 DOMString
SDP [SDP]의 문자열 표현이다. type이 "rollback"이면 이 멤버는 사용되지 않는다.
WebIDLdictionary RTCLocalSessionDescriptionInit {
  RTCSdpType type;
  DOMString sdp = "";
};
사전 RTCLocalSessionDescriptionInit 멤버
type의 형식은 RTCSdpType
이 기술의 유형이다. 존재하지 않으면 setLocalDescription은 다음을 기반으로 유형을 추론한다: RTCPeerConnection[[SignalingState]].
sdp의 형식은 DOMString
SDP [SDP]의 문자열 표현이다. type이 "rollback"이면 이 멤버는 사용되지 않는다.

4.7 세션 협상 모델

다음 객체의 상태에 대한 많은 변경은 RTCPeerConnection에서 원하는 효과를 내기 위해 신호 채널을 통해 원격 측과 통신해야 한다. 앱은 negotiationneeded 이벤트를 수신하여 신호 처리가 필요한 시점을 알 수 있다. 이 이벤트는 연결의 협상 필요 플래그의 상태에 따라 발생하며, 이 플래그는 [[NegotiationNeeded]] 내부 슬롯으로 표현된다.

4.7.1 협상 필요 상태 설정

이 절은 비규범적이다.

다음 객체인 RTCPeerConnection에서 신호 처리가 필요한 작업을 수행하면 연결에 협상이 필요하다고 표시된다. 이러한 작업의 예로는 RTCRtpTransceiver의 추가 또는 중지와 첫 번째 RTCDataChannel의 추가가 있다.

구현 내부의 변경으로 인해 연결에 협상이 필요하다고 표시될 수도 있다.

정확한 협상 필요 플래그 갱신 절차는 아래에 명시되어 있다.

4.7.2 협상 필요 상태 해제

이 절은 비규범적이다.

협상 필요 플래그는 유형이 "answer"인 세션 기술을 설정하는 데 성공하고 제공된 기술이 RTCRtpTransceiver들과 RTCDataChannel들의 상태와 일치하면 지워진다. 이 객체들은 현재 RTCPeerConnection에 존재한다. 구체적으로 이는 모든 비-stopped 트랜시버가 연결된 섹션을 로컬 기술에 가지고 있고 그 속성이 일치해야 하며, 데이터 채널을 하나라도 생성했다면 로컬 기술에 데이터 섹션이 있어야 한다는 뜻이다.

정확한 협상 필요 플래그 갱신 절차는 아래에 명시되어 있다.

4.7.3 협상 필요 플래그 갱신

아래 절차는 이 문서의 다른 곳에서 참조된 위치에서 수행된다. 협상에 영향을 주는 구현 내부 변경의 결과로 수행될 수도 있다. 이러한 변경이 발생하면 사용자 에이전트는 반드시 협상 필요 플래그를 갱신해야 한다.

협상 필요 플래그를 갱신하려면 connection에 대해 다음 단계를 실행한다:

  1. 만약 connection.[[Operations]]의 길이가 0이 아니면 connection.[[UpdateNegotiationNeededFlagOnEmptyChain]]true로 설정하고 이 단계를 중단한다.

  2. 다음 단계를 실행하는 태스크를 큐에 넣는다:

    1. 만약 connection.[[IsClosed]]true이면 이 단계를 중단한다.

    2. 만약 connection.[[Operations]]의 길이가 0이 아니면 connection.[[UpdateNegotiationNeededFlagOnEmptyChain]]true로 설정하고 이 단계를 중단한다.

    3. 만약 connection.[[SignalingState]]이 "stable"이 아니면 이 단계를 중단한다.

    4. 만약 협상이 필요한지 확인한 결과false이면, 협상 필요 플래그를 지운다: connection.[[NegotiationNeeded]]false로 설정하고 이 단계를 중단한다.

    5. 만약 connection.[[NegotiationNeeded]]이 이미 true이면 이 단계를 중단한다.

    6. connection.[[NegotiationNeeded]]true로 설정한다.

    7. 다음 이벤트를 발생시킨다: 이름은 negotiationneeded이고 대상은 connection.

    참고

    태스크 큐잉은 negotiationneeded 이벤트가 너무 일찍 발생하는 것을 방지한다. 이는 흔히 connection을 여러 번 동시에 수정하는 상황에서 필요하다.

    또한 협상 메서드와의 경쟁을 피하기 위해 negotiationneeded 이벤트는 작업 체인이 비어 있을 때만 발생시킨다.

협상이 필요한지 확인하려면 connection에 대해 다음 사항을 확인한다:

  1. 이 절의 시작 부분에서 설명한 구현별 협상이 필요하면 다음을 반환한다: true.

  2. 만약 connection.[[LocalIceCredentialsToReplace]]이 비어 있지 않으면 다음을 반환한다: true.

  3. description을 다음 값으로 한다: connection.[[CurrentLocalDescription]].

  4. 만약 connection에서 하나 이상의 RTCDataChannel을 생성했고, description에서 데이터용 m= 섹션이 아직 협상되지 않았다면 다음을 반환한다: true.

  5. transceiver에 대해, connection트랜시버 집합에서 다음 사항을 확인한다:

    1. 만약 transceiver.[[Stopping]]true이고 transceiver.[[Stopped]]false이면 다음을 반환한다: true.

    2. 만약 transceiverstopped 상태가 아니고 아직 연결된 m= 섹션이 description에 없으면 다음을 반환한다: true.

    3. 만약 transceiverstopped 상태가 아니고 연결된 m= 섹션이 description에 있으면 다음 사항을 확인한다:

      1. 만약 transceiver.[[Direction]]이 "sendrecv" 또는 "sendonly"이고 연결된 m= 섹션이 description에서 a=msid 줄을 하나도 포함하지 않거나, a=msid 줄에서 가져온 MSID 수 또는 이 m= 섹션의 MSID 값 자체가 transceiver.sender.[[AssociatedMediaStreamIds]]의 값과 다르면 다음을 반환한다: true.

      2. 만약 description의 유형이 "offer"이고 연결된 m= 섹션의 방향이 connection.[[CurrentLocalDescription]]connection.[[CurrentRemoteDescription]] 어느 쪽에서도 transceiver.[[Direction]]과 일치하지 않으면 다음을 반환한다: true. 이 단계에서 방향을 다음에 있는 방향과 비교할 때: [[CurrentRemoteDescription]]에 있는 기술의 방향은 피어의 관점을 나타내도록 반대로 바꿔야 한다.

      3. 만약 description의 유형이 "answer"이고 연결된 m= 섹션이 description에 있으며 그 방향이 transceiver.[[Direction]]과 제안된 방향의 교집합과 일치하지 않으면(다음에 설명됨: [RFC9429] (5.3.1절)), 다음을 반환한다: true.

    4. 만약 transceiverstopped 상태이고 연결된 m= 섹션이 있지만, 해당 m= 섹션이 아직 connection.[[CurrentLocalDescription]] 또는 connection.[[CurrentRemoteDescription]]에서 거부되지 않았다면 다음을 반환한다: true.

  6. 앞선 모든 확인을 수행했는데 true가 반환되지 않았다면 협상할 항목이 남아 있지 않으므로 다음을 반환한다: false.

4.8 상호 연결 설정을 위한 인터페이스

4.8.1 RTCIceCandidate 인터페이스

이 인터페이스는 [RFC5245] 2절에서 설명하는 ICE 후보를 나타낸다. candidate, sdpMid, sdpMLineIndexusernameFragment를 제외한 나머지 속성은 candidateInitDictcandidate 멤버의 형식이 올바른 경우 이를 파싱하여 파생된다.

후보 추가 사항 16: RTCIceCandidate.relayProtocol 추가 (PR #2763)
후보 추가 사항 23: RTCIceCandidate.url 추가 (PR #2773)
[Exposed=Window]
interface RTCIceCandidate {
  constructor(optional RTCIceCandidateInit candidateInitDict = {});
  readonly attribute DOMString candidate;
  readonly attribute DOMString? sdpMid;
  readonly attribute unsigned short? sdpMLineIndex;
  readonly attribute DOMString? foundation;
  readonly attribute RTCIceComponent? component;
  readonly attribute unsigned long? priority;
  readonly attribute DOMString? address;
  readonly attribute RTCIceProtocol? protocol;
  readonly attribute unsigned short? port;
  readonly attribute RTCIceCandidateType? type;
  readonly attribute RTCIceTcpCandidateType? tcpType;
  readonly attribute DOMString? relatedAddress;
  readonly attribute unsigned short? relatedPort;
  readonly attribute DOMString? usernameFragment;
  readonly attribute RTCIceServerTransportProtocol? relayProtocol;
  readonly attribute DOMString? url;
  RTCIceCandidateInit toJSON();
};
생성자
constructor()

RTCIceCandidate() 생성자는 사전 인수 candidateInitDict를 받으며, 그 내용은 새 RTCIceCandidate 객체를 초기화하는 데 사용된다.

호출되면 다음 단계를 실행한다.

  1. candidateInitDictsdpMidsdpMLineIndex 멤버가 모두 null이면 다음 예외를 던진다: TypeError.
  2. candidateInitDictRTCIceCandidate를 생성한 결과를 반환한다.

candidateInitDict 사전으로 RTCIceCandidate를 생성하려면 다음 단계를 실행한다.

  1. iceCandidate를 새로 생성한 RTCIceCandidate 객체로 한다.
  2. iceCandidate의 다음 속성에 대해 null로 초기화된 내부 슬롯을 생성한다. foundation, component, priority, address, protocol, port, type, tcpType, relatedAddressrelatedPort.
  3. iceCandidate의 다음 속성에 대해 candidateInitDict에서 같은 이름을 가진 멤버의 값으로 초기화된 내부 슬롯을 생성한다. candidate, sdpMid, sdpMLineIndex, usernameFragment.
  4. candidatecandidateInitDictcandidate 사전 멤버로 한다. candidate가 빈 문자열이 아니면 다음 단계를 실행한다.
    1. candidatecandidate-attribute 문법을 사용하여 파싱한다.
    2. candidate-attribute 파싱에 실패하면 이 단계들을 중단한다.
    3. 파싱 결과의 필드 중 iceCandidate의 대응 속성에 유효하지 않은 값을 나타내는 것이 있으면 이 단계들을 중단한다.
    4. iceCandidate의 대응 내부 슬롯을 파싱 결과의 필드 값으로 설정한다.
  5. iceCandidate를 반환한다.
참고

RTCIceCandidate 생성자는 candidateInitDict의 사전 멤버에 대해 기본적인 파싱과 형식 검사만 수행한다. candidate, sdpMid, sdpMLineIndex, usernameFragment의 형식 적합성 및 대응하는 세션 기술과의 일치 여부에 대한 상세 검증은 RTCIceCandidate 객체를 addIceCandidate()에 전달할 때 수행된다.

하위 호환성을 유지하기 위해 candidate 속성을 파싱할 때 발생하는 모든 오류는 무시된다. 이 경우 candidate 속성은 candidateInitDict에 제공된 원시 candidate 문자열을 보유하지만, foundation, priority 등의 파생 속성은 null로 설정된다.

속성

아래 속성 대부분은 [RFC5245] 15.1절에 정의되어 있다.

candidate의 형식은 DOMString이며 읽기 전용이다.
[RFC5245] 15.1절에 정의된 candidate-attribute를 담는다. 이 RTCIceCandidate가 후보 종료 표시 또는 피어 반사형 원격 후보를 나타내면 candidate는 빈 문자열이다.
sdpMid의 형식은 DOMString이며 읽기 전용이고 null을 허용한다.
null이 아니면 이 후보가 연결된 미디어 구성요소에 대해 [RFC5888]에 정의된 미디어 스트림 “식별 태그”를 포함한다.
sdpMLineIndex의 형식은 unsigned short이며 읽기 전용이고 null을 허용한다.
null이 아니면 SDP에서 이 후보가 연결된 미디어 기술의 인덱스(0부터 시작)를 나타낸다.
foundation의 형식은 DOMString이며 읽기 전용이고 null을 허용한다.
여러 RTCIceTransport에 나타나는 후보를 ICE가 서로 연관 지을 수 있게 하는 고유 식별자이다.
component의 형식은 RTCIceComponent이며 읽기 전용이고 null을 허용한다.
후보에 할당된 네트워크 구성요소 (“rtp” 또는 “rtcp”)이다. 이는 candidate-attributecomponent-id 필드에 대응하며, RTCIceComponent에 정의된 문자열 표현으로 디코딩된다.
priority의 형식은 unsigned long이며 읽기 전용이고 null을 허용한다.
후보에 할당된 우선순위이다.
address의 형식은 DOMString이며 읽기 전용이고 null을 허용한다.

IPv4 주소, IPv6 주소 및 정규화된 도메인 이름(FQDN)을 허용하는 후보의 주소이다. 이는 candidate-attributeconnection-address 필드에 대응한다.

예를 들어 [[SelectedCandidatePair]].remote를 통해 원격 후보가 노출될 수 있다. 기본적으로 사용자 에이전트는 노출되는 모든 원격 후보의 address 속성을 null반드시 유지해야 한다. 웹 애플리케이션이 addIceCandidate를 사용하여 RTCPeerConnection 인스턴스에 주소를 알려 주면 사용자 에이전트는 새로 알게 된 해당 주소를 가진 원격 후보를 나타내는 그 RTCPeerConnection 인스턴스의 모든 RTCIceCandidate에서 address 속성 값을 노출할 수 있다.

참고

ICE를 통해 수집되어 RTCIceCandidate 인스턴스에서 애플리케이션에 표시되는 후보의 주소는 WebRTC를 지원하지 않는 브라우저에서 사용자가 예상했을 수 있는 것보다 기기와 사용자에 관한 더 많은 정보(예: 위치, 로컬 네트워크 토폴로지)를 드러낼 수 있다.

이 주소는 항상 애플리케이션에 노출되고 잠재적으로 통신 상대방에게도 노출되며, 특정한 사용자 동의 없이도 노출될 수 있다 (예: 데이터 채널과 함께 사용하는 피어 연결 또는 미디어 수신 전용 연결).

또한 이 주소는 일시적 또는 영구적인 교차 출처 상태로 사용될 수 있으므로 기기의 지문 식별 표면을 넓힌다. (지문 식별 벡터이다.)

애플리케이션은 RTCConfigurationiceTransportPolicy 멤버를 통해 ICE 에이전트가 릴레이 후보만 보고하도록 강제함으로써 일시적 또는 영구적으로 통신 상대방에게 주소가 노출되지 않게 할 수 있다.

애플리케이션 자체에 노출되는 주소를 제한하기 위해 브라우저는 [RFC8828]에 정의된 대로 로컬 주소 공유에 관한 다양한 정책을 사용자에게 제공할 수 있다.

protocol의 형식은 RTCIceProtocol이며 읽기 전용이고 null을 허용한다.
후보의 프로토콜 (“udp”/“tcp”)이다. 이는 candidate-attributetransport 필드에 대응한다.
port의 형식은 unsigned short이며 읽기 전용이고 null을 허용한다.
후보의 포트이다.
type의 형식은 RTCIceCandidateType이며 읽기 전용이고 null을 허용한다.
후보의 유형이다. 이는 candidate-attributecandidate-types 필드에 대응한다.
tcpType의 형식은 RTCIceTcpCandidateType이며 읽기 전용이고 null을 허용한다.
protocol이 “tcp”이면 tcpType은 TCP 후보의 유형을 나타낸다. 그렇지 않으면 tcpTypenull이다. 이는 candidate-attributetcp-type 필드에 대응한다.
relatedAddress의 형식은 DOMString이며 읽기 전용이고 null을 허용한다.
릴레이 후보나 반사형 후보처럼 다른 후보에서 파생된 후보의 경우 relatedAddress는 그 후보가 파생된 원본 후보의 IP 주소이다. 호스트 후보의 경우 relatedAddressnull이다. 이는 candidate-attributerel-address 필드에 대응한다.
relatedPort의 형식은 unsigned short이며 읽기 전용이고 null을 허용한다.
릴레이 후보나 반사형 후보처럼 다른 후보에서 파생된 후보의 경우 relatedPort는 그 후보가 파생된 원본 후보의 포트이다. 호스트 후보의 경우 relatedPortnull이다. 이는 candidate-attributerel-port 필드에 대응한다.
usernameFragment의 형식은 DOMString이며 읽기 전용이고 null을 허용한다.
[RFC5245] 15.4절에 정의된 ufrag를 담는다.
후보 추가 사항 16:RTCIceCandidate.relayProtocol 추가 (PR #2763)
relayProtocol의 형식은 RTCIceServerTransportProtocol이며 읽기 전용이고 null을 허용한다.
유형이 “relay”인 로컬 후보의 경우, 이는 엔드포인트가 TURN 서버와 통신하는 데 사용하는 프로토콜이다. 그 밖의 모든 후보에서는 null이다.
후보 추가 사항 23:RTCIceCandidate.url 추가 (PR #2773)
url의 형식은 DOMString이며 읽기 전용이고 null을 허용한다.
유형이 “srflx” 또는 “relay”인 로컬 후보의 경우, 이는 후보를 얻은 ICE 서버의 URL이다. 그 밖의 모든 후보에서는 null이다.
메서드
toJSON()
RTCIceCandidate 인터페이스의 toJSON() 연산을 호출하려면 다음 단계를 실행한다.
  1. json을 새 RTCIceCandidateInit 사전으로 한다.
  2. «candidate, sdpMid, sdpMLineIndex, usernameFragment»의 각 속성 식별자 attr에 대해 다음 단계를 실행한다.
    1. RTCIceCandidate 객체가 주어졌을 때 attr로 식별되는 속성의 기저 값을 가져온 결과를 value로 한다.
    2. json[attr]value로 설정한다.
  3. json을 반환한다.
WebIDLdictionary RTCIceCandidateInit {
  DOMString candidate = "";
  DOMString? sdpMid = null;
  unsigned short? sdpMLineIndex = null;
  DOMString? usernameFragment = null;
};
RTCIceCandidateInit 사전 멤버
candidate의 형식은 DOMString이며 기본값은 ""이다.
[RFC5245] 15.1절에 정의된 candidate-attribute를 담는다. 이것이 후보 종료 표시를 나타내면 candidate는 빈 문자열이다.
sdpMid의 형식은 DOMString이며 null을 허용하고 기본값은 null이다.
null이 아니면 이 후보가 연결된 미디어 구성요소에 대해 [RFC5888]에 정의된 미디어 스트림 “식별 태그”를 포함한다.
sdpMLineIndex의 형식은 unsigned short이며 null을 허용하고 기본값은 null이다.
null이 아니면 SDP에서 이 후보가 연결된 미디어 기술의 인덱스(0부터 시작)를 나타낸다.
usernameFragment의 형식은 DOMString이며 null을 허용하고 기본값은 null이다.
null이 아니면 [RFC5245] 15.4절에 정의된 ufrag를 담는다.
4.8.1.1 candidate-attribute 문법

candidate-attribute 문법은 RTCIceCandidate() 생성자에서 candidateInitDictcandidate 멤버를 파싱하는 데 사용된다.

candidate-attribute의 기본 문법은 [RFC5245] 15.1절에 정의되어 있다. 또한 브라우저는 [RFC6544] 4.5절에 정의된 ICE TCP 문법 확장을 반드시 지원해야 한다.

브라우저는 다른 RFC에 정의된 candidate-attribute의 기타 문법 확장을 지원할 수 있다.

4.8.1.2 RTCIceProtocol 열거형

RTCIceProtocol은 ICE 후보의 프로토콜을 나타낸다.

WebIDLenum RTCIceProtocol {
  "udp",
  "tcp"
};
RTCIceProtocol 열거형 설명
열거형 값 설명
udp [RFC5245]에 설명된 UDP 후보이다.
tcp [RFC6544]에 설명된 TCP 후보이다.
4.8.1.3 RTCIceTcpCandidateType 열거형

RTCIceTcpCandidateType은 [RFC6544]에 정의된 ICE TCP 후보의 유형을 나타낸다.

WebIDLenum RTCIceTcpCandidateType {
  "active",
  "passive",
  "so"
};
RTCIceTcpCandidateType 열거형 설명
열거형 값 설명
active active” TCP 후보는 전송 계층이 발신 연결을 열려고 시도하지만 들어오는 연결 요청은 받지 않는 후보이다.
passive passive” TCP 후보는 전송 계층이 들어오는 연결 시도는 받지만 연결을 시도하지 않는 후보이다.
so so” 후보는 전송 계층이 피어와 동시에 연결을 열려고 시도하는 후보이다.
참고

사용자 에이전트는 일반적으로 active ICE TCP 후보만 수집한다.

4.8.1.4 RTCIceCandidateType 열거형

RTCIceCandidateType은 [RFC5245] 15.1절에 정의된 ICE 후보의 유형을 나타낸다.

WebIDLenum RTCIceCandidateType {
  "host",
  "srflx",
  "prflx",
  "relay"
};
RTCIceCandidateType 열거형 설명
열거형 값 설명
host [RFC5245] 4.1.1.1절에 정의된 호스트 후보이다.
srflx [RFC5245] 4.1.1.2절에 정의된 서버 반사형 후보이다.
prflx [RFC5245] 4.1.1.2절에 정의된 피어 반사형 후보이다.
relay [RFC5245] 7.1.3.2.1절에 정의된 릴레이 후보이다.
후보 추가 사항 16: RTCIceCandidate.relayProtocol 추가 (PR #2763)
4.8.1.5 RTCIceServerTransportProtocol 열거형

RTCIceServerTransportProtocol은 [RFC8656] 3.1절에 정의된 클라이언트와 서버 사이에서 사용되는 전송 프로토콜의 유형을 나타낸다.

WebIDLenum RTCIceServerTransportProtocol {
  "udp",
  "tcp",
  "tls",
};
RTCIceServerTransportProtocol 열거형 설명
열거형 값 설명
udp TURN 클라이언트가 서버로의 전송에 UDP를 사용한다.
tcp TURN 클라이언트가 서버로의 전송에 TCP를 사용한다.
tls TURN 클라이언트가 서버로의 전송에 TLS를 사용한다.

4.8.2 RTCPeerConnectionIceEvent

icecandidate 이벤트는 RTCPeerConnection에서 발생하며 RTCPeerConnectionIceEvent 인터페이스를 사용한다.

RTCPeerConnectionIceEvent 이벤트가 RTCIceCandidate 객체를 포함하는 상태로 발생할 때는 반드시 sdpMidsdpMLineIndex 값을 모두 포함해야 한다. RTCIceCandidate의 유형이 “srflx” 또는 “relay”이면 이벤트의 url 속성은 반드시 후보를 얻은 ICE 서버의 URL로 설정되어야 한다.

참고
icecandidate 이벤트는 서로 다른 세 가지 유형의 표시를 위해 사용된다.
  • 후보가 수집되었다. 이벤트의 candidate 멤버는 정상적으로 채워진다. 이 후보는 원격 피어에 시그널링하고 addIceCandidate에 전달해야 한다.

  • RTCIceTransport가 후보의 한 세대에 대한 수집을 마쳤으며, [RFC8838] 8.2절에 정의된 후보 종료 표시를 제공한다. 이는 candidate.candidate를 빈 문자열로 설정하여 나타낸다. candidate 객체는 원격 피어에 후보 종료 표시를 제공하기 위해 일반적인 ICE 후보와 마찬가지로 원격 피어에 시그널링하고 addIceCandidate에 전달해야 한다.

  • 모든 RTCIceTransport가 후보 수집을 마쳤으며 RTCPeerConnectionRTCIceGatheringState가 “complete”로 전환되었다. 이는 이벤트의 candidate 멤버를 null로 설정하여 나타낸다. 이는 하위 호환성만을 위해 존재하며 이 이벤트를 원격 피어에 시그널링할 필요는 없다. 이는 icegatheringstatechange 이벤트의 상태가 “complete”인 것과 동일하다.

WebIDL[Exposed=Window]
interface RTCPeerConnectionIceEvent : Event {
  constructor(DOMString type, optional RTCPeerConnectionIceEventInit eventInitDict = {});
  readonly attribute RTCIceCandidate? candidate;
  readonly attribute DOMString? url;
};
생성자
RTCPeerConnectionIceEvent.constructor()
속성
candidate의 형식은 RTCIceCandidate이며 읽기 전용이고 null을 허용한다.

candidate 속성은 이벤트를 발생시킨 새 ICE 후보를 담은 RTCIceCandidate 객체이다.

후보 수집 종료를 나타내기 위해 이벤트가 생성되면 이 속성은 null로 설정된다.

참고

미디어 구성요소가 여러 개여도 null 후보를 포함하는 이벤트는 하나만 발생한다.

url의 형식은 DOMString이며 읽기 전용이고 null을 허용한다.

url 속성은 이 후보를 수집하는 데 사용된 STUN 또는 TURN 서버를 식별하는 STUN 또는 TURN URL이다. 후보가 STUN 또는 TURN 서버에서 수집되지 않았으면 이 매개변수는 null로 설정된다.

후보 수정 사항 23:RTCPeerConnectionIceEvent.url을 사용 중단으로 표시 (PR #2773)

이 속성은 사용이 중단되었으며, 이전 버전과의 호환성을 위해서만 존재한다. 후보의 url을 사용하는 것이 좋다.

WebIDLdictionary RTCPeerConnectionIceEventInit : EventInit {
  RTCIceCandidate? candidate;
  DOMString? url;
};
RTCPeerConnectionIceEventInit 사전 멤버
candidate의 형식은 RTCIceCandidate이며 null을 허용한다.

candidate 속성에 대해서는 RTCPeerConnectionIceEvent 인터페이스의 해당 설명을 참조한다.

url의 형식은 DOMString이며 null을 허용한다.
url 속성은 이 후보를 수집하는 데 사용된 STUN 또는 TURN 서버를 식별하는 STUN 또는 TURN URL이다.

4.8.3 RTCPeerConnectionIceErrorEvent

icecandidateerror 이벤트는 RTCPeerConnection에서 발생하며 RTCPeerConnectionIceErrorEvent 인터페이스를 사용한다.

WebIDL[Exposed=Window]
interface RTCPeerConnectionIceErrorEvent : Event {
  constructor(DOMString type, RTCPeerConnectionIceErrorEventInit eventInitDict);
  readonly attribute DOMString? address;
  readonly attribute unsigned short? port;
  readonly attribute DOMString url;
  readonly attribute unsigned short errorCode;
  readonly attribute USVString errorText;
};
생성자
RTCPeerConnectionIceErrorEvent.constructor()
속성
address의 형식은 DOMString이며 읽기 전용이고 null을 허용한다.

address 속성은 STUN 또는 TURN 서버와 통신하는 데 사용된 로컬 IP 주소이다.

다중 홈 시스템에서는 서버에 연결하기 위해 여러 인터페이스가 사용될 수 있으며, 이 속성을 통해 애플리케이션은 어느 인터페이스에서 실패가 발생했는지 알아낼 수 있다.

로컬 IP 주소 값이 로컬 후보의 일부로 이미 노출되어 있지 않으면 address 속성은 null로 설정된다.

port의 형식은 unsigned short이며 읽기 전용이고 null을 허용한다.

port 속성은 STUN 또는 TURN 서버와 통신하는 데 사용된 포트이다.

address 속성이 null이면 port 속성도 null로 설정된다.

url의 형식은 DOMString이며 읽기 전용이다.

url 속성은 실패가 발생한 STUN 또는 TURN 서버를 식별하는 STUN 또는 TURN URL이다.

errorCode의 형식은 unsigned short이며 읽기 전용이다.

errorCode 속성은 STUN 또는 TURN 서버가 반환한 숫자형 STUN 오류 코드이다 [STUN-PARAMETERS].

서버에 도달할 수 있는 호스트 후보가 없으면 errorCode는 STUN 오류 코드 범위를 벗어난 값 701로 설정된다. 이 오류는 RTCIceGatheringState가 “gathering”인 동안 각 서버 URL에 대해 한 번만 발생한다.

errorText의 형식은 USVString이며 읽기 전용이다.

errorText 속성은 STUN 또는 TURN 서버가 반환한 STUN 사유 텍스트이다 [STUN-PARAMETERS].

서버에 도달할 수 없으면 errorText는 오류의 상세 정보를 제공하는 구현별 값으로 설정된다.

WebIDLdictionary RTCPeerConnectionIceErrorEventInit : EventInit {
  DOMString? address;
  unsigned short? port;
  DOMString url;
  required unsigned short errorCode;
  USVString errorText;
};
RTCPeerConnectionIceErrorEventInit 사전 멤버
address의 형식은 DOMString이며 null을 허용한다.

STUN 또는 TURN 서버와 통신하는 데 사용된 로컬 주소이거나 null이다.

port의 형식은 unsigned short이며 null을 허용한다.

STUN 또는 TURN 서버와 통신하는 데 사용된 로컬 포트이거나 null이다.

url의 형식은 DOMString이다.

실패가 발생한 STUN 또는 TURN 서버를 식별하는 STUN 또는 TURN URL이다.

errorCode의 형식은 unsigned short이며 필수이다.

STUN 또는 TURN 서버가 반환한 숫자형 STUN 오류 코드이다.

errorText의 형식은 USVString이다.

STUN 또는 TURN 서버가 반환한 STUN 사유 텍스트이다.

4.9 인증서 관리

RTCPeerConnection 인스턴스가 피어와 인증하는 데 사용하는 인증서는 RTCCertificate 인터페이스를 사용한다. 애플리케이션은 generateCertificate 메서드를 사용하여 이 객체를 명시적으로 생성할 수 있으며, RTCConfiguration에 제공하여 새 RTCPeerConnection 인스턴스를 생성할 수 있다.

여기에 제공된 명시적 인증서 관리 기능은 선택 사항이다. 애플리케이션이 certificates 구성 옵션을 제공하지 않고 RTCPeerConnection을 생성하면, 새 인증서 세트는 반드시 사용자 에이전트가 생성해야 한다. 이 세트에는 P-256 곡선의 개인 키와 SHA-256 해시를 사용하는 서명이 포함된 ECDSA 인증서가 반드시 포함되어야 한다.

WebIDLpartial interface RTCPeerConnection {
  static Promise<RTCCertificate>
      generateCertificate(AlgorithmIdentifier keygenAlgorithm);
};

메서드

generateCertificate, 정적

generateCertificate 함수는 사용자 에이전트가 X.509 인증서 [X509V3]와 이에 대응하는 개인 키를 생성하게 한다. 이 정보에 대한 핸들은 RTCCertificate 인터페이스의 형태로 제공된다. 반환된 RTCCertificate를 사용하면 RTCPeerConnection이 설정한 DTLS 세션에서 제시할 인증서를 제어할 수 있다.

keygenAlgorithm 인수는 인증서와 연결된 개인 키가 생성되는 방식을 제어하는 데 사용된다. keygenAlgorithm 인수는 WebCrypto [WebCryptoAPI]의 AlgorithmIdentifier 형식을 사용한다.

다음 값은 반드시 사용자 에이전트에서 지원되어야 한다: { name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" }{ name: "ECDSA", namedCurve: "P-256" }.

참고

사용자 에이전트가 허용하는 값의 집합은 작거나 고정되어 있을 것으로 예상된다.

이 과정에서 생성되는 인증서에는 서명도 포함된다. 이 서명의 유효성은 호환성을 위해서만 중요하다. 공개 키와 그 결과로 생성된 인증서 지문만 RTCPeerConnection에서 사용되지만, 인증서의 형식이 올바르면 그 인증서가 허용될 가능성이 더 높다. 브라우저는 인증서 서명에 사용할 알고리즘을 선택한다. 해시 알고리즘이 필요한 경우 브라우저는 다음 알고리즘을 선택하는 것이 좋다: SHA-256 [FIPS-180-4].

결과 인증서에는 다음과 연계할 수 있는 정보를 포함해서는 안 된다: 사용자 또는 사용자 에이전트. 식별 이름과 일련번호에는 무작위 값을 사용하는 것이 좋다.

메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.

  1. keygenAlgorithmgenerateCertificate의 첫 번째 인수로 한다.

  2. expires를 2592000000(30*24*60*60*1000)으로 한다.

    참고

    이는 기본적으로 generateCertificate 호출 시점부터 30일 후에 인증서가 만료됨을 의미한다.

  3. keygenAlgorithm이 객체이면 다음 단계를 실행한다.

    1. certificateExpirationkeygenAlgorithm이 나타내는 ECMAScript 객체를 변환하여 RTCCertificateExpiration 사전으로 만든 결과로 한다.

    2. 변환이 error와 함께 실패하면 error거부된 프로미스를 반환한다.

    3. certificateExpiration.expiresundefined가 아니면 expirescertificateExpiration.expires로 설정한다.

    4. expires가 31536000000보다 크면 expires를 31536000000으로 설정한다.

      참고

      이는 인증서의 유효 기간이 generateCertificate 호출 시점부터 365일을 초과할 수 없음을 의미한다.

      사용자 에이전트expires 값의 상한을 더 낮게 설정할 수 있다.

  4. normalizedKeygenAlgorithm을 연산 이름 generateKeysupportedAlgorithms 값 중 RTCPeerConnection용 인증서 생성에 특정된 값을 사용하여 알고리즘을 정규화한 결과로 한다.

  5. 위의 정규화 단계가 error와 함께 실패하면 error거부된 프로미스를 반환한다.

  6. normalizedKeygenAlgorithm 매개변수가 사용자 에이전트RTCPeerConnection용 인증서를 생성하는 데 사용할 수 없거나 사용하지 않을 알고리즘을 식별하면, 거부된 프로미스를 반환한다. 거부 사유는 DOMException이며 그 유형은 NotSupportedError이다. 특히 normalizedKeygenAlgorithm은 DTLS 연결 인증에 사용되는 서명을 생성할 수 있는 비대칭 알고리즘이어야 한다.

  7. p를 새 프로미스로 한다.

  8. 다음 단계를 병렬로 실행한다.

    1. keygenAlgorithm을 사용하여 normalizedKeygenAlgorithm이 지정한 키 생성 연산을 수행한다.

    2. generatedKeyingMaterialgeneratedKeyCertificate를 위 단계에서 생성한 개인 키 자료와 인증서로 한다.

    3. certificate를 새 RTCCertificate 객체로 한다.

    4. certificate.[[Expires]]를 현재 시각에 expires 값을 더한 값으로 설정한다.

    5. certificate.[[Origin]]관련 설정 객체출처로 설정한다.

    6. generatedKeyingMaterial을 보안 모듈에 저장하고, handle을 이를 참조하는 식별자로 한다.

    7. certificate.[[KeyingMaterialHandle]]handle로 설정한다.

    8. certificate.[[Certificate]]generatedCertificate로 설정한다.

    9. 현재 영역의 전역 객체global로 주어졌을 때, pcertificate이행하기 위해 네트워킹 작업 소스전역 작업을 대기열에 추가한다.

  9. p를 반환한다.

4.9.1 RTCCertificateExpiration 사전

RTCCertificateExpirationgenerateCertificate로 생성한 인증서의 만료일을 설정하는 데 사용된다.

WebIDLdictionary RTCCertificateExpiration {
  [EnforceRange] unsigned long long expires;
};
expires, 형식은 unsigned long long이다.

선택적인 expires 속성을 추가할 수 있다. 추가 대상은 generateCertificate에 전달되는 알고리즘의 정의이다. 이 매개변수가 있으면 인증서가 생성된 시점부터 측정하여 RTCCertificate이 유효한 최대 시간을 밀리초 단위로 나타낸다.

4.9.2 RTCCertificate 인터페이스

RTCCertificate 인터페이스는 WebRTC 통신을 인증하는 데 사용되는 인증서를 나타낸다. 표시되는 속성 외에도 내부 슬롯에는 생성된 개인 키 자료에 대한 핸들 ([[KeyingMaterialHandle]]), 인증서 ([[Certificate]])가 포함된다. 이 인증서는 RTCPeerConnection이 피어와 인증할 때 사용한다. 또한 내부 슬롯에는 이 객체를 생성한 출처 ([[Origin]])도 포함된다.

WebIDL[Exposed=Window, Serializable]
interface RTCCertificate {
  readonly attribute EpochTimeStamp expires;
  sequence<RTCDtlsFingerprint> getFingerprints();
};
속성
expires의 형식은 EpochTimeStamp이며 읽기 전용이다.

expires 속성은 1970-01-01T00:00:00Z를 기준으로 한 밀리초 단위의 날짜와 시간을 나타내며, 이 시간이 지나면 브라우저는 인증서를 유효하지 않은 것으로 간주한다. 이 시간이 지난 후 해당 인증서를 사용하여 RTCPeerConnection을 생성하려는 시도는 실패한다.

이 값은 인증서 자체의 notAfter 매개변수에 반영되지 않을 수도 있다.

메서드
getFingerprints

인증서 지문 목록을 반환한다. 이 가운데 하나는 인증서 서명에 사용된 다이제스트 알고리즘으로 계산된다.

이 API에서는 [[Certificate]] 슬롯이 비구조화 이진 데이터를 포함한다. 애플리케이션이 [[KeyingMaterialHandle]] 내부 슬롯이나 이 슬롯이 참조하는 키 자료에 접근할 수 있는 방법은 제공되지 않는다. 구현은 RTCCertificate 객체를 영구 저장소에 저장하고 다시 가져오는 기능을 애플리케이션에 반드시 지원해야 한다. 이 과정에서는 [[KeyingMaterialHandle]]이 참조하는 키 자료도 보존되어야 한다. 구현은 민감한 키 자료를 동일 프로세스 메모리 공격으로부터 안전한 보안 모듈에 저장하는 것이 좋다. 그러면 개인 키를 저장하고 사용할 수 있으면서도 메모리 공격으로 쉽게 읽을 수 없게 된다.

RTCCertificate 객체는 직렬화 가능한 객체이다 [HTML]. valueserialized가 주어졌을 때 이 객체의 직렬화 단계는 다음과 같다.

  1. serialized.[[Expires]]를 value.expires 속성의 값으로 설정한다.
  2. serialized.[[Certificate]]를 value.[[Certificate]]에 있는 비구조화 이진 데이터의 복사본으로 설정한다.
  3. serialized.[[Origin]]을 value.[[Origin]]에 있는 비구조화 이진 데이터의 복사본으로 설정한다.
  4. serialized.[[KeyingMaterialHandle]]을 value.[[KeyingMaterialHandle]]에 있는 핸들을 직렬화한 값으로 설정한다. 개인 키 자료 자체를 직렬화하는 것은 아니다.

serializedvalue가 주어졌을 때 이 객체의 역직렬화 단계는 다음과 같다.

  1. value.expires 속성이 serialized.[[Expires]]를 포함하도록 초기화한다.
  2. value.[[Certificate]]serialized.[[Certificate]]의 복사본으로 설정한다.
  3. value.[[Origin]]serialized.[[Origin]]의 복사본으로 설정한다.
  4. value.[[KeyingMaterialHandle]]serialized.[[KeyingMaterialHandle]]을 역직렬화하여 얻은 개인 키 자료 핸들로 설정한다.
참고

이 방식으로 구조화된 복제를 지원하면 RTCCertificate 인스턴스를 저장소에 영구 저장할 수 있다. 또한 postMessage(message, options) [html] 같은 API를 사용하여 인스턴스를 다른 출처로 전달할 수도 있다. 그러나 이 객체는 원래 객체를 생성한 출처 이외의 다른 출처에서는 사용할 수 없다.

5. RTP 미디어 API

RTP 미디어 API를 사용하면 웹 애플리케이션이 피어 간 연결을 통해 MediaStreamTrack을 송수신할 수 있다. 트랙을 RTCPeerConnection에 추가하면 시그널링이 발생하며, 이 시그널링이 원격 피어로 전달되면 원격 측에 대응하는 트랙이 생성된다.

참고

RTCPeerConnection에서 전송되고 다른 쪽에서 수신되는 트랙 사이에는 정확한 1:1 대응 관계가 없다. 우선 전송된 트랙의 ID는 수신된 트랙의 ID와 매핑되지 않는다. 또한 replaceTrackRTCRtpSender가 전송하는 트랙을 수신 측에 새 트랙을 생성하지 않고 변경한다. 이에 대응하는 RTCRtpReceiver에는 하나의 트랙만 있으며, 이 트랙은 서로 이어 붙인 여러 미디어 소스를 나타낼 수도 있다. addTransceiverreplaceTrack을 사용하면 동일한 트랙을 여러 번 전송할 수 있으며, 수신 측에서는 이를 각각 별도의 트랙을 보유한 여러 수신기로 관찰하게 된다. 따라서 한쪽의 RTCRtpSender와 다른 쪽의 RTCRtpReceiver 트랙 사이에 1:1 관계가 있다고 보는 것이 더 정확하다. 필요한 경우 송신기와 수신기는 RTCRtpTransceivermid를 사용하여 대응시킬 수 있다.

미디어를 전송할 때 송신기는 SDP로 협상된 범위, 인코더의 정렬 제한, CPU 과부하 감지 또는 대역폭 추정 등의 여러 요구 사항을 충족하기 위해 미디어의 크기나 샘플링을 조정해야 할 수 있다.

[RFC9429]의 규칙(3.6절)에 따라 비디오는 축소할 수 있다. 입력 소스에 존재하지 않았던 가짜 데이터를 만들기 위해 미디어를 확대해서는 안 되며, 픽셀 수 제한을 충족하는 데 필요한 경우를 제외하고 미디어를 잘라내서는 안 되고, 종횡비를 변경해서는 안 된다.

참고

WebRTC 워킹 그룹은 이 상황을 더 복잡하게 처리할 필요성과 그 일정에 관한 구현 피드백을 구하고 있다. 가능한 몇 가지 설계는 GitHub 이슈 1283에서 논의되었다.

scaleResolutionDownBy의 결과로 비디오 크기가 조정될 때 결과 너비 또는 높이가 정수가 아닌 상황이 발생할 수 있다. 사용자 에이전트는 전송해서는 안 된다. 단, 정수 부분을 기준으로 scaleResolutionDownBy로 조정된 너비와 높이보다 큰 비디오는 인코더의 최소 해상도를 준수하기 위한 경우를 제외하고 전송해서는 안 된다. 조정된 너비 또는 높이의 정수 부분이 0일 때 무엇을 전송할지는 구현에서 정의된다.

MediaStreamTrack의 실제 인코딩 및 전송은 RTCRtpSender라는 객체를 통해 관리된다. 마찬가지로 MediaStreamTrack의 수신 및 디코딩은 RTCRtpReceiver라는 객체를 통해 관리된다. 각 RTCRtpSender에는 최대 하나의 트랙이 연결되며, 수신할 각 트랙에는 정확히 하나의 RTCRtpReceiver가 연결된다.

MediaStreamTrack의 인코딩 및 전송은 해당 특성(비디오 트랙의 width, heightframeRate, 오디오 트랙의 sampleSize, sampleRatechannelCount)이 원격 측에서 생성되는 트랙에도 합리적인 수준으로 유지되도록 구성하는 것이 좋다. 이 원칙이 적용되지 않는 상황도 있다. 예를 들어 어느 한 엔드포인트나 네트워크에 리소스 제약이 있거나 RTCRtpSender에 구현이 다르게 동작하도록 지시하는 설정이 적용될 수 있다.

RTCPeerConnection 객체에는 일부 상태를 공유하는 쌍으로 구성된 송신기와 수신기를 나타내는 다음 객체의 집합이 있다: RTCRtpTransceiver. 이 집합은 RTCPeerConnection 객체가 생성될 때 빈 집합으로 초기화된다. RTCRtpSenderRTCRtpReceiver는 항상 RTCRtpTransceiver와 동시에 생성되며, 수명 내내 해당 객체에 연결된 상태로 유지된다. RTCRtpTransceiver는 애플리케이션이 MediaStreamTrackRTCPeerConnectionaddTrack() 메서드로 연결할 때 암시적으로 생성되거나, 애플리케이션이 addTransceiver 메서드를 사용할 때 명시적으로 생성된다. 새로운 미디어 기술을 포함하는 원격 기술이 적용될 때도 생성된다. 또한 원격 엔드포인트에 전송할 미디어가 있음을 나타내는 원격 기술이 적용되면 관련 MediaStreamTrackRTCRtpReceiver가 애플리케이션에 track 이벤트를 통해 제공된다.

RTCRtpTransceiver가 다른 엔드포인트와 미디어를 송신하거나 수신하려면 양쪽 엔드포인트에 RTCRtpTransceiver 객체가 있고, 이 객체가 동일한 대상과 연결되도록 SDP로 협상해야 한다. 그 대상은 동일한 미디어 기술이다.

제안을 생성할 때 해당 측의 모든 트랜시버를 포함하기에 충분한 수의 미디어 기술이 생성된다. 이 제안을 로컬 기술로 설정하면 연결되지 않았던 모든 트랜시버가 제안의 미디어 기술과 연결된다.

제안이 원격 기술로 설정되면 제안 안에서 아직 트랜시버와 연결되지 않은 모든 미디어 기술이 새 트랜시버 또는 기존 트랜시버와 연결된다. 이 경우 addTrack() 메서드로 생성된 연결되지 않은 트랜시버만 연결될 수 있다. addTransceiver() 메서드로 생성된 연결되지 않은 트랜시버는 원격 제안에 사용 가능한 미디어 기술이 있더라도 연결되지 않는다. 대신 addTrack()으로 생성된 트랜시버가 충분하지 않으면 새 트랜시버가 생성되어 연결된다. 이로 인해 addTrack()으로 생성된 트랜시버와 addTransceiver()로 생성된 트랜시버 사이에는 속성을 검사해서는 관찰할 수 없는 중요한 차이가 생긴다.

응답을 생성할 때는 제안에 존재했던 미디어 기술만 응답에 나열할 수 있다. 따라서 원격 제안을 설정할 때 연결되지 않았던 트랜시버는 로컬 응답을 설정한 뒤에도 연결되지 않은 상태로 남는다. 응답자가 후속 제안을 생성하여 또 다른 제안/응답 교환을 시작하면 이를 해결할 수 있다. 또는 addTrack()으로 생성된 트랜시버를 사용하는 경우에는 최초 교환에서 충분한 수의 미디어 기술을 제안하도록 보장할 수 있다.

5.1 RTCPeerConnection 인터페이스 확장

RTP 미디어 API는 아래 설명과 같이 RTCPeerConnection 인터페이스를 확장한다.

WebIDL          partial interface RTCPeerConnection {
  sequence<RTCRtpSender> getSenders();
  sequence<RTCRtpReceiver> getReceivers();
  sequence<RTCRtpTransceiver> getTransceivers();
  RTCRtpSender addTrack(MediaStreamTrack track, MediaStream... streams);
  undefined removeTrack(RTCRtpSender sender);
  RTCRtpTransceiver addTransceiver((MediaStreamTrack or DOMString) trackOrKind,
                                   optional RTCRtpTransceiverInit init = {});
  attribute EventHandler ontrack;
};

속성

ontrack의 타입은 EventHandler

이 이벤트 처리기의 이벤트 타입은 track이다.

메서드

getSenders

RTCRtpSender 객체의 시퀀스를 반환한다. 이 객체들은 중지되지 않은 RTCRtpTransceiver 객체에 속하며 현재 이 RTCPeerConnection 객체에 연결된 RTP 송신기를 나타낸다.

getSenders 메서드가 호출되면 사용자 에이전트는 반드시 CollectSenders 알고리즘을 실행한 결과를 반환해야 한다.

CollectSenders 알고리즘을 다음과 같이 정의한다.

  1. transceiversCollectTransceivers 알고리즘을 실행한 결과로 둔다.
  2. senders를 새로운 빈 시퀀스로 둔다.
  3. transceiver에 대해(transceivers 안에서)
    1. transceiver.[[Stopped]]false이면 transceiver.[[Sender]]senders에 추가한다.
  4. senders를 반환한다.
getReceivers

RTCRtpReceiver 객체의 시퀀스를 반환한다. 이 객체들은 중지되지 않은 RTCRtpTransceiver 객체에 속하며 현재 이 RTCPeerConnection 객체에 연결된 RTP 수신기를 나타낸다.

getReceivers 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.

  1. transceiversCollectTransceivers 알고리즘을 실행한 결과로 둔다.
  2. receivers를 새로운 빈 시퀀스로 둔다.
  3. transceiver에 대해(transceivers 안에서)
    1. transceiver.[[Stopped]]false이면 transceiver.[[Receiver]]receivers에 추가한다.
  4. receivers를 반환한다.
getTransceivers

현재 연결된 RTP 트랜시버를 나타내는 RTCRtpTransceiver 객체의 시퀀스를 반환한다. 이 트랜시버들은 이 RTCPeerConnection 객체에 연결되어 있다.

getTransceivers 메서드는 반드시 CollectTransceivers 알고리즘을 실행한 결과를 반환해야 한다.

CollectTransceivers 알고리즘을 다음과 같이 정의한다.

  1. transceivers를 모든 RTCRtpTransceiver 객체로 구성된 새 시퀀스로 둔다. 이 객체들은 이 RTCPeerConnection 객체의 트랜시버 집합에 있으며 삽입 순서에 따라 배치된다.
  2. transceivers를 반환한다.
addTrack

새 트랙을 RTCPeerConnection에 추가하고, 해당 트랙이 지정된 MediaStream에 포함됨을 나타낸다.

addTrack 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.

  1. connection을 이 메서드가 호출된 RTCPeerConnection 객체로 둔다.

  2. track을 메서드의 첫 번째 인수가 나타내는 MediaStreamTrack 객체로 둔다.

  3. kindtrack.kind로 둔다.

  4. streamsMediaStream 객체의 목록으로 둔다. 이 목록은 메서드의 나머지 인수로 구성하며, 메서드가 하나의 인수로 호출되었다면 빈 목록으로 둔다.

  5. connection.[[IsClosed]]true이면 다음 예외를 발생시킨다: InvalidStateError.

  6. sendersCollectSenders 알고리즘을 실행한 결과로 둔다. RTCRtpSendertrack에 대한 객체가 이미 senders에 있으면 다음 예외를 발생시킨다: InvalidAccessError.

  7. 아래 단계에서는 기존 송신기를 재사용할 수 있는지 판단하는 방법을 설명한다. 기존 송신기를 재사용하면 이후 createOffercreateAnswer를 호출할 때 대응하는 미디어 기술sendrecv 또는 sendonly로 표시하고 송신기 스트림의 MSID를 추가한다. 이는 [RFC9429]의 ( 5.2.2절 5.3.2절)에 정의되어 있다.

    senders에 있는 RTCRtpSender 객체 중 다음 기준을 모두 충족하는 객체가 있으면 sender를 그 객체로 두고, 그렇지 않으면 null로 둔다.

  8. sendernull이 아니면 해당 송신기를 사용하기 위해 다음 단계를 실행한다.

    1. sender.[[SenderTrack]]track으로 설정한다.

    2. sender.[[AssociatedMediaStreamIds]]를 빈 집합으로 설정한다.

    3. stream에 대해(streams 안에서) stream.id[[AssociatedMediaStreamIds]]에 추가한다. 단, 아직 그곳에 없는 경우에만 추가한다.

    4. transceiverRTCRtpTransceiver로 둔다. 이 객체는 sender와 연결되어 있다.

    5. transceiver.[[Direction]]이 "recvonly"이면 transceiver.[[Direction]]을 "sendrecv"로 설정한다.

    6. transceiver.[[Direction]]이 "inactive"이면 transceiver.[[Direction]]을 "sendonly"로 설정한다.

  9. sendernull이면 다음 단계를 실행한다.

    1. RTCRtpSender를 생성한다. 이때 track, kindstreams를 사용하고 그 결과를 sender로 둔다.

    2. RTCRtpReceiver를 생성한다. 이때 kind를 사용하고 그 결과를 receiver로 둔다.

    3. RTCRtpTransceiver를 생성한다. 이때 sender, receiver 및 값이 "sendrecv"인 RTCRtpTransceiverDirection을 사용하고 그 결과를 transceiver로 둔다.

    4. transceiverconnection트랜시버 집합에 추가한다.

  10. 트랙의 콘텐츠에 애플리케이션이 접근할 수 없는 경우가 있다. 트랙을 CORS 교차 출처가 되게 하는 모든 원인으로 인해 이런 상황이 발생할 수 있다. 이러한 트랙도 addTrack() 메서드에 제공할 수 있으며 해당 트랙의 RTCRtpSender를 생성할 수 있지만, 콘텐츠는 전송해서는 안 된다. 트랙 콘텐츠 대신 무음(오디오), 검은 프레임(비디오) 또는 이와 동등하게 콘텐츠가 없는 상태를 전송한다.

    이 속성은 시간에 따라 변경될 수 있다는 점에 유의한다.

  11. 협상 필요 플래그를 갱신한다. 대상은 connection이다.

  12. sender를 반환한다.

removeTrack

sender의 미디어 전송을 중지한다. RTCRtpSender는 계속 getSenders에 나타난다. 이렇게 하면 이후 createOffer를 호출할 때 대응하는 트랜시버의 미디어 기술을 "recvonly" 또는 "inactive"로 표시한다. 이는 [RFC9429]의 ( 5.2.2절)에 정의되어 있다.

다른 피어가 이러한 방식으로 트랙 전송을 중지하면 해당 트랙은 원격 MediaStream에서 제거된다. 이 스트림은 최초 track 이벤트에서 공개된 스트림이다. 또한 MediaStreamTrack이 아직 음소거되지 않았다면 트랙에서 mute 이벤트가 발생한다.

참고
removeTrack()과 같은 효과는 대응하는 트랜시버의 RTCRtpTransceiver.direction 속성을 설정하고 송신기에서 RTCRtpSender.replaceTrack(null)을 호출하여 얻을 수 있다. 한 가지 사소한 차이는 replaceTrack()은 비동기식이고 removeTrack()은 동기식이라는 점이다.

removeTrack 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.

  1. senderremoveTrack에 전달된 인수로 둔다.

  2. connection을 이 메서드가 호출된 RTCPeerConnection 객체로 둔다.

  3. connection.[[IsClosed]]true이면 다음 예외를 발생시킨다: InvalidStateError.

  4. senderconnection에 의해 생성된 것이 아니면 다음 예외를 발생시킨다: InvalidAccessError.

  5. transceiverRTCRtpTransceiver 객체로 둔다. 이 객체는 sender에 대응한다.

  6. transceiver.[[Stopping]]true이면 이 단계를 중단한다.

  7. sendersCollectSenders 알고리즘을 실행한 결과로 둔다.

  8. sendersenders에 없으면 이 단계를 중단한다. 이는 해당 트랜시버가 중지되었거나 세션 기술을 설정하여 제거되었음을 나타낸다. 해당 세션 기술의 type은 "rollback"이다.

  9. sender.[[SenderTrack]]이 null이면 이 단계를 중단한다.

  10. sender.[[SenderTrack]]을 null로 설정한다.

  11. transceiver.[[Direction]]이 "sendrecv"이면 transceiver.[[Direction]]을 "recvonly"로 설정한다.

  12. transceiver.[[Direction]]이 "sendonly"이면 transceiver.[[Direction]]을 "inactive"로 설정한다.

  13. 협상 필요 플래그를 갱신한다. 대상은 connection이다.

addTransceiver

RTCRtpTransceiver를 생성하여 트랜시버 집합에 추가한다.

트랜시버를 추가하면 이후 createOffer를 호출할 때 대응하는 트랜시버의 미디어 기술이 추가된다. 이는 [RFC9429]의 ( 5.2.2절)에 정의되어 있다.

mid의 초기값은 null이다. 세션 기술을 설정하면 나중에 이 값이 null이 아닌 값으로 변경될 수 있다.

sendEncodings 인수를 사용하여 제안할 동시 전송 인코딩의 수와 선택적으로 해당 RID 및 인코딩 매개변수를 지정할 수 있다.

이 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.

  1. init을 두 번째 인수로 둔다.

  2. streamsinit.streams로 둔다.

  3. sendEncodingsinit.sendEncodings로 둔다.

  4. directioninit.direction으로 둔다.

  5. 첫 번째 인수가 문자열이면 kind를 첫 번째 인수로 두고 다음 단계를 실행한다.

    1. kind"audio"도 아니고 "video"도 아니면 다음 예외를 발생시킨다: TypeError.

    2. tracknull로 둔다.

  6. 첫 번째 인수가 MediaStreamTrack이면 track을 첫 번째 인수로 두고 kindtrack.kind로 둔다.

  7. connection.[[IsClosed]]true이면 다음 예외를 발생시킨다: InvalidStateError.

  8. 다음 sendEncodings에 대해 addTransceiver sendEncodings 검증 단계를 실행한다. 그 안의 각 RTCRtpEncodingParameters 딕셔너리를 “인코딩”이라고 하며, 이를 통해 검증한다.

    1. rid 값이 sendEncodings에서 [RFC8851] 10절에 명시된 문법을 준수하는지 확인한다. RID 중 하나라도 이 요구 사항을 충족하지 않으면 다음 예외를 발생시킨다: TypeError.

      다음 조건 중 하나라도 충족되면 다음 예외를 발생시킨다: TypeError.
      • 어떤 인코딩이 포함하는 rid 멤버의 값이 [RFC8851] 10절에 명시된 문법 요구 사항을 준수하지 않는다.
      • 일부 인코딩에는 포함된 rid 멤버가 있지만 모든 인코딩에 있는 것은 아니다.
      • 어떤 인코딩이 포함하는 rid 멤버의 값이 다른 인코딩의 rid 멤버에 포함된 값과 같다. 해당 다른 인코딩은 sendEncodings에 있다.
    2. 어떤 인코딩이 포함하는 읽기 전용 매개변수rid가 아니면 다음 예외를 발생시킨다: InvalidAccessError.

    3. 후보 추가 49:RTCRtpEncodingParameters에 codec 추가 (PR #2985)

      어떤 인코딩이 포함하는 codec 멤버의 값이 어떤 코덱과도 일치하지 않으면 다음에서 지원하는 코덱이 아니다: RTCRtpSender.getCapabilities(kind).codecs. 이 경우 다음 예외를 발생시킨다: OperationError.

    4. 후보 추가 49:RTCRtpEncodingParameters에 codec 추가 (PR #2985)

      사용자 에이전트가 협상 없이 코덱을 변경하는 기능을 지원하지 않거나 개별 인코딩에 코덱을 설정하는 기능을 지원하지 않으면 프로미스를 거부된 상태로 반환한다. 이때 새로 생성한 OperationError를 사용한다.

    5. kind"audio"이면 scaleResolutionDownBymaxFramerate 멤버 중 하나라도 포함하는 모든 인코딩에서 해당 멤버를 제거한다.

    6. 어떤 인코딩이 포함하는 scaleResolutionDownBy 멤버의 값이 1.0보다 작으면 다음 예외를 발생시킨다: RangeError.

    7. 정의된 각 maxFramerate 멤버가 sendEncodings에서 0.0보다 큰 값을 갖는지 확인한다. maxFramerate 값 중 하나라도 이 요구 사항을 충족하지 않으면 다음 예외를 발생시킨다: RangeError.

    8. maxN을 사용자 에이전트가 지원할 수 있는 동시 인코딩 총수의 최댓값으로 둔다. 이는 해당 kind에 적용되며 최소값은 1이다. 아직 사용할 코덱을 알 수 없으므로 이 값은 낙관적으로 정하는 것이 좋다.

    9. 어떤 인코딩이 포함하는 scaleResolutionDownBy 멤버가 있으면 해당 멤버가 없는 각 인코딩에 scaleResolutionDownBy 멤버를 값 1.0과 함께 추가한다.

    10. 저장된 인코딩 수가 sendEncodings에서 maxN을 초과하면 sendEncodings의 길이가 maxN이 될 때까지 끝에서부터 잘라낸다.

    11. kind"video"이고 어느 인코딩에도 포함되어 있지 않은 scaleResolutionDownBy 멤버라면 각 인코딩에 scaleResolutionDownBy 멤버를 다음 값과 함께 추가한다: 2^(length of sendEncodings - encoding index - 1). 그 결과 해상도가 작은 것부터 큰 것 순으로 배치되며 마지막 인코딩에는 크기 조정이 적용되지 않는다. 예를 들어 길이가 3이면 4:2:1이 된다.

    12. 현재 저장된 인코딩 수가 sendEncodings에서 1이면 유일한 항목에서 모든 rid 멤버를 제거한다.

      참고
      하나의 기본 RTCRtpEncodingParameterssendEncodings에 제공하면 애플리케이션이 나중에 setParameters를 사용하여 인코딩 매개변수를 설정할 수 있다. 동시 전송을 사용하지 않는 경우에도 가능하다.
  9. RTCRtpSender를 생성한다. 이때 track, kind, streamssendEncodings를 사용하고 그 결과를 sender로 둔다.

    sendEncodings가 설정되어 있으면 이후 createOffer 호출은 여러 RTP 인코딩을 전송하도록 구성된다. 이는 [RFC9429]의 ( 5.2.2절 5.2.1절)에 정의되어 있다. setRemoteDescription이 여러 RTP 인코딩을 수신할 수 있는 대응 원격 기술로 호출되었다고 하자. 이 기능은 [RFC9429]의 ( 3.7절)에 정의되어 있다. 이 경우 RTCRtpSender가 여러 RTP 인코딩을 전송할 수 있으며, 트랜시버의 sender.getParameters()를 통해 가져온 매개변수에는 협상된 인코딩이 반영된다.

  10. RTCRtpReceiver를 생성한다. 이때 kind를 사용하고 그 결과를 receiver로 둔다.

  11. RTCRtpTransceiver를 생성한다. 이때 sender, receiverdirection을 사용하고 그 결과를 transceiver로 둔다.

  12. transceiverconnection트랜시버 집합에 추가한다.

  13. 협상 필요 플래그를 갱신한다. 대상은 connection이다.

  14. transceiver를 반환한다.

WebIDLdictionary RTCRtpTransceiverInit {
  RTCRtpTransceiverDirection direction = "sendrecv";
  sequence<MediaStream> streams = [];
  sequence<RTCRtpEncodingParameters> sendEncodings = [];
};

딕셔너리 RTCRtpTransceiverInit 멤버

direction의 타입은 RTCRtpTransceiverDirection이며, 기본값은 "sendrecv"이다.
RTCRtpTransceiver의 방향이다.
streams의 타입은 sequence<MediaStream>이다.

원격 RTCPeerConnection의 트랙 이벤트가 발생할 때, 추가되는 RTCRtpReceiver에 대응하여 이벤트에 포함될 스트림이다.

sendEncodings의 타입은 sequence<RTCRtpEncodingParameters>이다.

미디어의 RTP 인코딩을 전송하기 위한 매개변수를 포함하는 시퀀스이다.

WebIDLenum RTCRtpTransceiverDirection {
  "sendrecv",
  "sendonly",
  "recvonly",
  "inactive",
  "stopped"
};
RTCRtpTransceiverDirection 열거형 설명
열거형 값 설명
sendrecv RTCRtpTransceiverRTCRtpSender sender는 RTP 전송을 제안하며, 원격 피어가 이를 수락하고 sender.getParameters().encodings[i].active가 어떤 i 값에 대해서든 true이면 RTP를 전송한다. RTCRtpTransceiverRTCRtpReceiver는 RTP 수신을 제안하며, 원격 피어가 수락하면 RTP를 수신한다.
sendonly RTCRtpTransceiverRTCRtpSender sender는 RTP 전송을 제안하며, 원격 피어가 이를 수락하고 sender.getParameters().encodings[i].active가 어떤 i 값에 대해서든 true이면 RTP를 전송한다. RTCRtpTransceiverRTCRtpReceiver는 RTP 수신을 제안하지 않으며 RTP를 수신하지 않는다.
recvonly RTCRtpTransceiverRTCRtpSender는 RTP 전송을 제안하지 않으며 RTP를 전송하지 않는다. RTCRtpTransceiverRTCRtpReceiver는 RTP 수신을 제안하며, 원격 피어가 수락하면 RTP를 수신한다.
inactive RTCRtpTransceiverRTCRtpSender는 RTP 전송을 제안하지 않으며 RTP를 전송하지 않는다. RTCRtpTransceiverRTCRtpReceiver는 RTP 수신을 제안하지 않으며 RTP를 수신하지 않는다.
stopped RTCRtpTransceiver는 RTP를 송신하지도 수신하지도 않는다. 제안에서는 포트 0을 생성한다. 응답에서는 RTCRtpSender가 RTP 전송을 제안하지 않고, RTCRtpReceiver도 RTP 수신을 제안하지 않는다. 이는 종단 상태이다.

5.1.1 원격 MediaStreamTrack 처리

애플리케이션은 트랜시버의 방향을 양방향 모두 일시적으로 끄는 "inactive"로 설정하거나 수신 방향만 거부하는 "sendonly"로 설정하여 수신 미디어 기술을 거부할 수 있다. m-line을 재사용할 수 있게 하면서 영구적으로 거부하려면 애플리케이션이 RTCRtpTransceiver.stop()을 호출한 후 해당 측에서 협상을 시작해야 한다.

원격 트랙을 처리하려면 RTCRtpTransceiver transceiver, direction, msids, addList, removeListtrackEventInits가 주어졌을 때 다음 단계를 실행한다.

  1. 연결된 원격 스트림을 설정한다. 이때 transceiver.[[Receiver]], msids, addListremoveList를 사용한다.

  2. direction이 "sendrecv" 또는 "recvonly"이고 transceiver.[[FiredDirection]]이 "sendrecv"도 아니고 "recvonly"도 아니거나, 이전 단계에서 addList의 길이가 증가했다면 원격 트랙의 추가를 처리한다. 이때 transceivertrackEventInits를 사용한다.

  3. direction이 "sendonly" 또는 "inactive"이면 transceiver.[[Receptive]]false로 설정한다.

  4. direction이 "sendonly" 또는 "inactive"이고 transceiver.[[FiredDirection]]이 "sendrecv" 또는 "recvonly"이면 원격 트랙의 제거를 처리한다. 대상은 미디어 기술이며, transceivermuteTracks를 사용한다.

  5. transceiver.[[FiredDirection]]direction으로 설정한다.

원격 트랙의 추가를 처리하려면 다음 값이 주어진다: RTCRtpTransceiver transceivertrackEventInits. 그런 다음 다음 단계를 실행한다.

  1. receivertransceiver.[[Receiver]]로 둔다.

  2. trackreceiver.[[ReceiverTrack]]으로 둔다.

  3. streamsreceiver.[[AssociatedRemoteMediaStreams]]로 둔다.

  4. RTCTrackEventInit 딕셔너리를 생성한다. 그 멤버는 receiver, track, streamstransceiver이며, 이 딕셔너리를 trackEventInits에 추가한다.

원격 트랙의 제거를 처리하려면 RTCRtpTransceiver transceivermuteTracks를 사용하여 다음 단계를 실행한다.

  1. receivertransceiver.[[Receiver]]로 둔다.

  2. trackreceiver.[[ReceiverTrack]]으로 둔다.

  3. track.mutedfalse이면 trackmuteTracks에 추가한다.

연결된 원격 스트림을 설정하려면 다음 값이 주어진다: RTCRtpReceiver receiver, msids, addListremoveList. 그런 다음 다음 단계를 실행한다.

  1. connectionRTCPeerConnection 객체로 둔다. 이 객체는 receiver와 연결되어 있다.

  2. msids의 각 MSID에 대해 MediaStream 객체가 해당 id를 사용하여 이 connection에 대해 이전에 생성되지 않았다면 그 id를 가진 MediaStream 객체를 생성한다.

  3. streamsMediaStream 객체의 목록으로 둔다. 이 객체들은 이 connection에 대해 id로 생성되었으며, 해당 ID는 msids에 대응한다.

  4. trackreceiver.[[ReceiverTrack]]으로 둔다.

  5. stream에 대해, 해당 항목이 receiver.[[AssociatedRemoteMediaStreams]]에 있지만 streams에는 없다면 streamtrack을 한 쌍으로 removeList에 추가한다.

  6. streams에 있는 각 streamreceiver.[[AssociatedRemoteMediaStreams]]에 없다면 streamtrack을 한 쌍으로 addList에 추가한다.

  7. receiver.[[AssociatedRemoteMediaStreams]]streams로 설정한다.

5.2 RTCRtpSender Interface

The RTCRtpSender interface allows an application to control how a given MediaStreamTrack is encoded and transmitted to a remote peer. When setParameters is called on an RTCRtpSender object, the encoding is changed appropriately.

To create an RTCRtpSender with a MediaStreamTrack, track, a string, kind, a list of MediaStream objects, streams, and optionally a list of RTCRtpEncodingParameters objects, sendEncodings, run the following steps:

  1. Let sender be a new RTCRtpSender object.

  2. Let sender have a [[SenderTrack]] internal slot initialized to track.

  3. Let sender have a [[SenderTransport]] internal slot initialized to null.

  4. Let sender have a [[LastStableStateSenderTransport]] internal slot initialized to null.

  5. Let sender have a [[Dtmf]] internal slot initialized to null.

  6. If kind is "audio" then create an RTCDTMFSender dtmf and set the [[Dtmf]] internal slot to dtmf.

  7. Let sender have an [[AssociatedMediaStreamIds]] internal slot, representing a list of Ids of MediaStream objects that this sender is to be associated with. The [[AssociatedMediaStreamIds]] slot is used when sender is represented in SDP as described in [RFC9429] (section 5.2.1.).

  8. Set sender.[[AssociatedMediaStreamIds]] to an empty set.

  9. For each stream in streams, add stream.id to [[AssociatedMediaStreamIds]] if it's not already there.

  10. Let sender have a [[SendEncodings]] internal slot, representing a list of RTCRtpEncodingParameters dictionaries.

  11. If sendEncodings is given as input to this algorithm, and is non-empty, set the [[SendEncodings]] slot to sendEncodings. Otherwise, set it to a list containing a single new RTCRtpEncodingParameters dictionary, and if kind is "video", add a scaleResolutionDownBy member with the value 1.0 to that dictionary.

    Note

    RTCRtpEncodingParameters dictionaries contain active members whose values are true by default.

  12. Candidate Correction 13:Rollback restores ridless encoding trounced by sRD(simulcastOffer). (PR #2797)

    Let sender have a [[LastStableRidlessSendEncodings]] internal slot initialized to null.

  13. Let sender have a [[SendCodecs]] internal slot, representing a list of RTCRtpCodecParameters dictionaries, and initialized to an empty list.

  14. Let sender have a [[LastReturnedParameters]] internal slot, which will be used to match getParameters and setParameters transactions.

  15. Return sender.

WebIDL[Exposed=Window]
interface RTCRtpSender {
  readonly attribute MediaStreamTrack? track;
  readonly attribute RTCDtlsTransport? transport;
  static RTCRtpCapabilities? getCapabilities(DOMString kind);
  Promise<undefined> setParameters(RTCRtpSendParameters parameters,
      optional RTCSetParameterOptions setParameterOptions = {});
  RTCRtpSendParameters getParameters();
  Promise<undefined> replaceTrack(MediaStreamTrack? withTrack);
  undefined setStreams(MediaStream... streams);
  Promise<RTCStatsReport> getStats();
};

Attributes

track of type MediaStreamTrack, readonly, nullable

The track attribute is the track that is associated with this RTCRtpSender object. If track is ended, or if the track's output is disabled, i.e. the track is disabled and/or muted, the RTCRtpSender MUST send black frames (video) and MUST NOT send (audio). In the case of video, the RTCRtpSender SHOULD send one black frame per second. If track is null then the RTCRtpSender does not send. On getting, the attribute MUST return the value of the [[SenderTrack]] slot.

transport of type RTCDtlsTransport, readonly, nullable

The transport attribute is the transport over which media from track is sent in the form of RTP packets. Prior to construction of the RTCDtlsTransport object, the transport attribute will be null. When bundling is used, multiple RTCRtpSender objects will share one transport and will all send RTP and RTCP over the same transport.

On getting, the attribute MUST return the value of the [[SenderTransport]] slot.

Methods

getCapabilities, static

The static RTCRtpSender.getCapabilities() method provides a way to discover the types of capabilities the user agent supports for sending media of the given kind, without reserving any resources, ports, or other state.

When the getCapabilities method is called, the user agent MUST run the following steps:

  1. Let kind be the method's first argument.

  2. If kind is neither "video" nor "audio" return null.

  3. Return a new RTCRtpCapabilities dictionary, with its codecs member initialized to the list of implemented send codecs for kind, and its headerExtensions member initialized to the list of implemented header extensions for sending with kind.

The list of implemented send codecs, given kind, is an implementation-defined list of RTCRtpCodec dictionaries representing the most optimistic view of the codecs the user agent supports for sending media of the given kind (video or audio).

The list of implemented header extensions for sending, given kind, is an implementation-defined list of RTCRtpHeaderExtensionCapability dictionaries representing the most optimistic view of the header extensions the user agent supports for sending media of the given kind (video or audio).

These capabilities provide generally persistent cross-origin information on the device and thus increases the fingerprinting surface of the application. In privacy-sensitive contexts, user agents MAY consider mitigations such as reporting only a common subset of the capabilities. (This is a fingerprinting vector.)

Note

The codec capabilities returned affect the setCodecPreferences() algorithm and what inputs it throws InvalidModificationError on, and should also be consistent with information revealed by createOffer() and createAnswer() about codecs negotiated for sending, to ensure any privacy mitigations are effective.

setParameters

The setParameters method updates how track is encoded and transmitted to a remote peer.

When the setParameters method is called, the user agent MUST run the following steps:

  1. Let parameters be the method's first argument.
  2. Let sender be the RTCRtpSender object on which setParameters is invoked.
  3. Let transceiver be the RTCRtpTransceiver object associated with sender (i.e. sender is transceiver.[[Sender]]).
  4. If transceiver.[[Stopping]] is true, return a promise rejected with a newly created InvalidStateError.
  5. If sender.[[LastReturnedParameters]] is null, return a promise rejected with a newly created InvalidStateError.
  6. Validate parameters by running the following setParameters validation steps:
    1. Let encodings be parameters.encodings.
    2. Let codecs be parameters.codecs.
    3. Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)

      Let choosableCodecs be codecs.

    4. Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)

      If choosableCodecs is an empty list, set choosableCodecs to transceiver.[[PreferredCodecs]] and exclude any codecs not included in the list of implemented send codecs.

    5. Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)

      If choosableCodecs is still an empty list, set choosableCodecs to the list of implemented send codecs for transceiver's kind.

    6. Let N be the number of RTCRtpEncodingParameters stored in sender.[[SendEncodings]].
    7. If any of the following conditions are met, return a promise rejected with a newly created InvalidModificationError:
      • encodings.length is different from N.
      • encodings has been re-ordered.
      • Any parameter in parameters is marked as a Read-only parameter (such as RID) and has a value that is different from the corresponding parameter value in sender.[[LastReturnedParameters]]. Note that this also applies to transactionId.
      • Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)
        Any encoding in encodings contains a codec not found in choosableCodecs, using the codec dictionary match algorithm with ignoreLevels set to true.
    8. If transceiver kind is "audio", remove the scaleResolutionDownBy and maxFramerate members from all encodings that contain any of them.

    9. If transceiver kind is "video", then for each encoding in encodings that doesn't contain a scaleResolutionDownBy member, add a scaleResolutionDownBy member with the value 1.0.

    10. If transceiver kind is "video", and any encoding in encodings contains a scaleResolutionDownBy member whose value is less than 1.0, return a promise rejected with a newly created RangeError.

    11. Verify that each encoding in encodings has a maxFramerate member whose value is greater than or equal to 0.0. If one of the maxFramerate values does not meet this requirement, return a promise rejected with a newly created RangeError.

    12. Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)

      If the user agent does not support setting the codec for any encoding or mixing different codec values on the different encodings, return a promise rejected with a newly created OperationError.

  7. Let p be a new promise.
  8. In parallel, configure the media stack to use parameters to transmit sender.[[SenderTrack]].
    1. If the media stack is successfully configured with parameters, queue a task to run the following steps:
      1. Set sender.[[LastReturnedParameters]] to null.
      2. Set sender.[[SendEncodings]] to parameters.encodings.
      3. Resolve p with undefined.
    2. If any error occurred while configuring the media stack, queue a task to run the following steps:
      1. If an error occurred due to hardware resources not being available, reject p with a newly created RTCError whose errorDetail is set to "hardware-encoder-not-available" and abort these steps.
      2. If an error occurred due to a hardware encoder not supporting parameters, reject p with a newly created RTCError whose errorDetail is set to "hardware-encoder-error" and abort these steps.
      3. For all other errors, reject p with a newly created OperationError.
  9. Return p.

setParameters does not cause SDP renegotiation and can only be used to change what the media stack is sending or receiving within the envelope negotiated by Offer/Answer. The attributes in the RTCRtpSendParameters dictionary are designed to not enable this, so attributes like cname that cannot be changed are read-only. Other things, like bitrate, are controlled using limits such as maxBitrate, where the user agent needs to ensure it does not exceed the maximum bitrate specified by maxBitrate, while at the same time making sure it satisfies constraints on bitrate specified in other places such as the SDP.

getParameters

The getParameters() method returns the RTCRtpSender object's current parameters for how track is encoded and transmitted to a remote RTCRtpReceiver.

When getParameters is called, the user agent MUST run the following steps:

  1. Let sender be the RTCRtpSender object on which the getter was invoked.

  2. If sender.[[LastReturnedParameters]] is not null, return sender.[[LastReturnedParameters]], and abort these steps.

  3. Let result be a new RTCRtpSendParameters dictionary constructed as follows:

  4. Set sender.[[LastReturnedParameters]] to result.

  5. Queue a task that sets sender.[[LastReturnedParameters]] to null.

  6. Return result.

getParameters may be used with setParameters to change the parameters in the following way:

async function updateParameters() {
  try {
    const params = sender.getParameters();
    // ... make changes to parameters
    params.encodings[0].active = false;
    await sender.setParameters(params);
  } catch (err) {
    console.error(err);
  }
}

After a completed call to setParameters, subsequent calls to getParameters will return the modified set of parameters.

replaceTrack

Attempts to replace the RTCRtpSender's current track with another track provided (or with a null track), without renegotiation.

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

  1. Let sender be the RTCRtpSender object on which replaceTrack is invoked.

  2. Let transceiver be the RTCRtpTransceiver object associated with sender.

  3. Let connection be the RTCPeerConnection object associated with sender.

  4. Let withTrack be the argument to this method.

  5. If withTrack is non-null and withTrack.kind differs from the transceiver kind of transceiver, return a promise rejected with a newly created TypeError.

  6. Return the result of chaining the following steps to connection's operations chain:

    1. If transceiver.[[Stopping]] is true, return a promise rejected with a newly created InvalidStateError.

    2. Let p be a new promise.

    3. Let sending be true if transceiver.[[CurrentDirection]] is "sendrecv" or "sendonly", and false otherwise.

    4. Run the following steps in parallel:

      1. If sending is true, and withTrack is null, have the sender stop sending.

      2. If sending is true, and withTrack is not null, determine if withTrack can be sent immediately by the sender without violating the sender's already-negotiated envelope, and if it cannot, then:

        1. Queue a global task on the networking task source given the current realm's global object as global to reject p with a newly created InvalidModificationError.
        2. Abort these steps.
      3. If sending is true, and withTrack is not null, have the sender switch seamlessly to transmitting withTrack instead of the sender's existing track.

      4. Queue a task that runs the following steps:

        1. If connection.[[IsClosed]] is true, abort these steps.

        2. Set sender.[[SenderTrack]] to withTrack.

        3. Queue a global task on the networking task source given the current realm's global object as global to resolve p with undefined.

    5. Return p.

Note

Changing dimensions and/or frame rates might not require negotiation. Cases that may require negotiation include:

  1. Changing a resolution to a value outside of the negotiated imageattr bounds, as described in [RFC6236].
  2. Changing a frame rate to a value that causes the block rate for the codec to be exceeded.
  3. A video track differing in raw vs. pre-encoded format.
  4. An audio track having a different number of channels.
  5. Sources that also encode (typically hardware encoders) might be unable to produce the negotiated codec; similarly, software sources might not implement the codec that was negotiated for an encoding source.
setStreams

Sets the MediaStreams to be associated with this sender's track.

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

  1. Let sender be the RTCRtpSender object on which this method was invoked.

  2. Let connection be the RTCPeerConnection object on which this method was invoked.

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

  4. Let streams be a list of MediaStream objects constructed from the method's arguments, or an empty list if the method was called without arguments.

  5. Set sender.[[AssociatedMediaStreamIds]] to an empty set.

  6. For each stream in streams, add stream.id to [[AssociatedMediaStreamIds]] if it's not already there.

  7. Update the negotiation-needed flag for connection.

getStats

Gathers stats for this sender only and reports the result asynchronously.

When the getStats() method is invoked, the user agent MUST run the following steps:

  1. Let selector be the RTCRtpSender object on which the method was invoked.

  2. Let p be a new promise, and run the following steps in parallel:

    1. Gather the stats indicated by selector according to the stats selection algorithm.

    2. Queue a global task on the networking task source given the current realm's global object as global to resolve p with the resulting RTCStatsReport object, containing the gathered stats.

  3. Return p.

5.2.1 RTCRtpParameters Dictionary

WebIDLdictionary RTCRtpParameters {
  required sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
  required RTCRtcpParameters rtcp;
  required sequence<RTCRtpCodecParameters> codecs;
};
Dictionary RTCRtpParameters Members
headerExtensions of type sequence<RTCRtpHeaderExtensionParameters>, required

A sequence containing parameters for RTP header extensions. Read-only parameter.

rtcp of type RTCRtcpParameters, required

Parameters used for RTCP. Read-only parameter.

codecs of type sequence<RTCRtpCodecParameters>, required

A sequence containing the media codecs that an RTCRtpSender will choose from, as well as entries for RTX, RED and FEC mechanisms. Corresponding to each media codec where retransmission via RTX is enabled, there will be an entry in codecs with a mimeType attribute indicating retransmission via audio/rtx or video/rtx, and an sdpFmtpLine attribute (providing the "apt" and "rtx-time" parameters). Read-only parameter.

5.2.2 RTCRtpSendParameters Dictionary

WebIDLdictionary RTCRtpSendParameters : RTCRtpParameters {
  required DOMString transactionId;
  required sequence<RTCRtpEncodingParameters> encodings;
};
Dictionary RTCRtpSendParameters Members
transactionId of type DOMString, required

A unique identifier for the last set of parameters applied. Ensures that setParameters can only be called based on a previous getParameters, and that there are no intervening changes. Read-only parameter.

encodings of type sequence<RTCRtpEncodingParameters>, required

A sequence containing parameters for RTP encodings of media.

5.2.3 RTCRtpReceiveParameters Dictionary

WebIDLdictionary RTCRtpReceiveParameters : RTCRtpParameters {
};

5.2.4 RTCRtpCodingParameters Dictionary

WebIDLdictionary RTCRtpCodingParameters {
  DOMString rid;
};
Dictionary RTCRtpCodingParameters Members
rid of type DOMString

If set, this RTP encoding will be sent with the RID header extension as defined by [RFC9429] (section 5.2.1.). The RID is not modifiable via setParameters. It can only be set or modified in addTransceiver on the sending side. Read-only parameter.

5.2.5 RTCRtpEncodingParameters Dictionary

WebIDLdictionary RTCRtpEncodingParameters : RTCRtpCodingParameters {
  boolean active = true;
  RTCRtpCodec codec;
  unsigned long maxBitrate;
  double maxFramerate;
  double scaleResolutionDownBy;
};
Dictionary RTCRtpEncodingParameters Members
active of type boolean, defaulting to true

Indicates that this encoding is actively being sent. Setting it to false causes this encoding to no longer be sent. Setting it to true causes this encoding to be sent. Since setting the value to false does not cause the SSRC to be removed, an RTCP BYE is not sent.

Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)
codec of type RTCRtpCodec

Optional value selecting which codec is used for this encoding's RTP stream. If absent, the user agent can choose to use any codec negotiated for sending.

When codec is set and [[SendCodecs]] have been negotiated, the user agent SHOULD use the first [[SendCodecs]] matching codec for sending, according to the codec dictionary match algorithm with ignoreLevels set to true.

maxBitrate of type unsigned long

When present, indicates the maximum bitrate that can be used to send this encoding. The user agent is free to allocate bandwidth between the encodings, as long as the maxBitrate value is not exceeded. The encoding may also be further constrained by other limits (such as per-transport or per-session bandwidth limits) below the maximum specified here. maxBitrate is computed the same way as the Transport Independent Application Specific Maximum (TIAS) bandwidth defined in [RFC3890] Section 6.2.2, which is the maximum bandwidth needed without counting IP or other transport layers like TCP or UDP. The unit of maxBitrate is bits per second.

Note

How the bitrate is achieved is media and encoding dependent. For video, a frame will always be sent as fast as possible, but frames may be dropped until bitrate is low enough. Thus, even a bitrate of zero will allow sending one frame. For audio, it might be necessary to stop playing if the bitrate does not allow the chosen encoding enough bandwidth to be sent.

maxFramerate of type double

This member can only be present if the sender's kind is "video". When present, indicates the maximum frame rate that can be used to send this encoding, in frames per second. The user agent is free to allocate bandwidth between the encodings, as long as the maxFramerate value is not exceeded.

If changed with setParameters(), the new frame rate takes effect after the current picture is completed; setting the max frame rate to zero thus has the effect of freezing the video on the next frame.

scaleResolutionDownBy of type double

This member is only present if the sender's kind is "video". The video's resolution will be scaled down in each dimension by the given value before sending. For example, if the value is 2.0, the video will be scaled down by a factor of 2 in each dimension, resulting in sending a video of one quarter the size. If the value is 1.0, the video will not be affected. The value must be greater than or equal to 1.0. By default, scaling is applied in reverse order by a factor of two, to produce an order of smaller to higher resolutions, e.g. 4:2:1. If there is only one layer, the sender will by default not apply any scaling, (i.e. scaleResolutionDownBy will be 1.0).

5.2.6 RTCRtcpParameters Dictionary

WebIDLdictionary RTCRtcpParameters {
  DOMString cname;
  boolean reducedSize;
};
Dictionary RTCRtcpParameters Members
cname of type DOMString

The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages). Read-only parameter.

reducedSize of type boolean

Whether reduced size RTCP [RFC5506] is configured (if true) or compound RTCP as specified in [RFC3550] (if false). Read-only parameter.

5.2.7 RTCRtpHeaderExtensionParameters Dictionary

WebIDLdictionary RTCRtpHeaderExtensionParameters {
  required DOMString uri;
  required unsigned short id;
  boolean encrypted = false;
};
Dictionary RTCRtpHeaderExtensionParameters Members
uri of type DOMString, required

The URI of the RTP header extension, as defined in [RFC5285]. Read-only parameter.

id of type unsigned short, required

The value put in the RTP packet to identify the header extension. Read-only parameter.

encrypted of type boolean

Whether the header extension is encrypted or not. Read-only parameter.

Note

The RTCRtpHeaderExtensionParameters dictionary enables an application to determine whether a header extension is configured for use within an RTCRtpSender or RTCRtpReceiver. For an RTCRtpTransceiver transceiver, an application can determine the "direction" parameter (defined in Section 5 of [RFC5285]) of a header extension as follows without having to parse SDP:

  1. sendonly: The header extension is only included in transceiver.sender.getParameters().headerExtensions.
  2. recvonly: The header extension is only included in transceiver.receiver.getParameters().headerExtensions.
  3. sendrecv: The header extension is included in both transceiver.sender.getParameters().headerExtensions and transceiver.receiver.getParameters().headerExtensions.
  4. inactive: The header extension is included in neither transceiver.sender.getParameters().headerExtensions nor transceiver.receiver.getParameters().headerExtensions.

5.2.8 RTCRtpCodec Dictionary

WebIDLdictionary RTCRtpCodec {
  required DOMString mimeType;
  required unsigned long clockRate;
  unsigned short channels;
  DOMString sdpFmtpLine;
};
Dictionary RTCRtpCodec Members

The RTCRtpCodec dictionary provides information about codec objects.

mimeType of type DOMString, required

The codec MIME media type/subtype. Valid media types and subtypes are listed in [IANA-RTP-2].

clockRate of type unsigned long, required

The codec clock rate expressed in Hertz.

channels of type unsigned short

If present, indicates the maximum number of channels (mono=1, stereo=2).

sdpFmtpLine of type DOMString

The "format specific parameters" field from the a=fmtp line in the SDP corresponding to the codec, if one exists, as defined by [RFC9429] (section 5.8.).

5.2.9 RTCRtpCodecParameters Dictionary

WebIDLdictionary RTCRtpCodecParameters : RTCRtpCodec {
  required octet payloadType;
};
Dictionary RTCRtpCodecParameters Members

The RTCRtpCodecParameters dictionary provides information about the negotiated codecs. The fields inherited from RTCRtpCodec MUST all be Read-only parameters.

For an RTCRtpSender, the sdpFmtpLine parameters come from the [[CurrentRemoteDescription]], and for an RTCRtpReceiver, they come from the local description (which is [[PendingLocalDescription]] if not null, and [[CurrentLocalDescription]] otherwise).

payloadType of type octet, required

The RTP payload type used to identify this codec. Read-only parameter.

5.2.10 RTCRtpCapabilities Dictionary

WebIDLdictionary RTCRtpCapabilities {
  required sequence<RTCRtpCodec> codecs;
  required sequence<RTCRtpHeaderExtensionCapability> headerExtensions;
};
Dictionary RTCRtpCapabilities Members
codecs of type sequence<RTCRtpCodec>, required

Supported media codecs as well as entries for RTX, RED and FEC mechanisms. Only combinations that would utilize distinct payload types in a generated SDP offer are to be provided. For example:

  1. Two H.264/AVC codecs, one for each of two supported packetization-mode values.
  2. Two CN codecs with different clock rates.

There MUST only be a single entry in codecs for retransmission via RTX, with sdpFmtpLine not present.

headerExtensions of type sequence<RTCRtpHeaderExtensionCapability>, required

Supported RTP header extensions.

5.2.11 RTCRtpHeaderExtensionCapability Dictionary

WebIDLdictionary RTCRtpHeaderExtensionCapability {
  required DOMString uri;
};
Dictionary RTCRtpHeaderExtensionCapability Members
uri of type DOMString, required

The URI of the RTP header extension, as defined in [RFC5285].

5.2.12 RTCSetParameterOptions Dictionary

WebIDLdictionary RTCSetParameterOptions {
};
Dictionary RTCSetParameterOptions Members

RTCSetParameterOptions is defined as an empty dictionary to allow for extensibility.

5.3 RTCRtpReceiver Interface

The RTCRtpReceiver interface allows an application to inspect the receipt of a MediaStreamTrack.

To create an RTCRtpReceiver with a string, kind, run the following steps:

  1. Let receiver be a new RTCRtpReceiver object.

  2. Let track be a new MediaStreamTrack object [GETUSERMEDIA]. The source of track is a remote source provided by receiver. Note that the track.id is generated by the user agent and does not map to any track IDs on the remote side.

  3. Initialize track.kind to kind.

  4. Initialize track.label to the result of concatenating the string "remote " with kind.

  5. Initialize track.readyState to live.

  6. Initialize track.muted to true. See the MediaStreamTrack section about how the muted attribute reflects if a MediaStreamTrack is receiving media data or not.

  7. Let receiver have a [[ReceiverTrack]] internal slot initialized to track.

  8. Let receiver have a [[ReceiverTransport]] internal slot initialized to null.

  9. Let receiver have a [[LastStableStateReceiverTransport]] internal slot initialized to null.

  10. Let receiver have an [[AssociatedRemoteMediaStreams]] internal slot, representing a list of MediaStream objects that the MediaStreamTrack object of this receiver is associated with, and initialized to an empty list.

  11. Let receiver have a [[LastStableStateAssociatedRemoteMediaStreams]] internal slot and initialize it to an empty list.

  12. Let receiver have a [[ReceiveCodecs]] internal slot, representing a list of RTCRtpCodecParameters dictionaries, and initialized to an empty list.

  13. Let receiver have a [[LastStableStateReceiveCodecs]] internal slot and initialize it to an empty list.

  14. Let receiver have a [[JitterBufferTarget]] internal slot initialized to null.

  15. Return receiver.

WebIDL[Exposed=Window]
interface RTCRtpReceiver {
  readonly attribute MediaStreamTrack track;
  readonly attribute RTCDtlsTransport? transport;
  static RTCRtpCapabilities? getCapabilities(DOMString kind);
  RTCRtpReceiveParameters getParameters();
  sequence<RTCRtpContributingSource> getContributingSources();
  sequence<RTCRtpSynchronizationSource> getSynchronizationSources();
  Promise<RTCStatsReport> getStats();
  attribute DOMHighResTimeStamp? jitterBufferTarget;
};

Attributes

track of type MediaStreamTrack, readonly

The track attribute is the track that is associated with this RTCRtpReceiver object receiver.

Note that track.stop() is final, although clones are not affected. Since receiver.track.stop() does not implicitly stop receiver, Receiver Reports continue to be sent. On getting, the attribute MUST return the value of the [[ReceiverTrack]] slot.

transport of type RTCDtlsTransport, readonly, nullable

The transport attribute is the transport over which media for the receiver's track is received in the form of RTP packets. Prior to construction of the RTCDtlsTransport object, the transport attribute will be null. When bundling is used, multiple RTCRtpReceiver objects will share one transport and will all receive RTP and RTCP over the same transport.

On getting, the attribute MUST return the value of the [[ReceiverTransport]] slot.

jitterBufferTarget of type DOMHighResTimeStamp, nullable

This attribute allows the application to specify a target duration of time in milliseconds of media for the RTCRtpReceiver's jitter buffer to hold. This influences the amount of buffering done by the user agent, which in turn affects retransmissions and packet loss recovery. Altering the target value allows applications to control the tradeoff between playout delay and the risk of running out of audio or video frames due to network jitter.

The user agent MUST have a minimum allowed target and a maximum allowed target reflecting what the user agent is able or willing to provide based on network conditions and memory constraints, which can change at any time.

Note

This is a target value. The resulting change in delay can be gradually observed over time. The receiver's average jitter buffer delay can be measured as the delta jitterBufferDelay divided by the delta jitterBufferEmittedCount.

An average delay is expected even if DTX is used. For example, if DTX is used and packets start flowing after silence, larger targets can influence the user agent to buffer these packets rather than playing them out.

On getting, this attribute MUST return the value of the [[JitterBufferTarget]] internal slot.

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

  1. Let receiver be the RTCRtpReceiver object on which the setter is invoked.

  2. Let target be the argument to the setter.

  3. If target is negative or larger than 4000 milliseconds, then throw a RangeError.

  4. Set receiver's [[JitterBufferTarget]] to target.

  5. Let track be receiver's [[ReceiverTrack]].

  6. in parallel, begin executing the following steps:

    1. Update the underlying system about the new target, or that there is no application preference if target is null.

      If track is synchronized with another RTCRtpReceiver's track for audio/video synchronization, then the user agent SHOULD use the larger of the two receivers' [[JitterBufferTarget]] for both receivers.

      When the underlying system is applying a jitter buffer target, it will continuously make sure that the actual jitter buffer target is clamped within the minimum allowed target and maximum allowed target.

      Note

      If the user agent ends up using a target different from the requested one (e.g. due to network conditions or physical memory constraints), this is not reflected in the [[JitterBufferTarget]] internal slot.

    2. Modifying the jitter buffer target of the underlying system SHOULD affect the internal audio or video buffering gradually in order not to hurt user experience. Audio samples or video frames SHOULD be accelerated or decelerated before playout, similarly to how it is done for audio/video synchronization or in response to congestion control.

      The acceleration or deceleration rate may vary depending on network conditions or the type of audio received (e.g. speech or background noise). It MAY take several seconds to achieve 1 second of buffering but SHOULD not take more than 30 seconds assuming packets are being received. The speed MAY be different for audio and video.

      Note

      For audio, acceleration and deceleration can be measured with insertedSamplesForDeceleration and removedSamplesForAcceleration. For video, this may result in the same frame being rendered multiple times or frames may be dropped.

Methods

getCapabilities, static

The static RTCRtpReceiver.getCapabilities() method provides a way to discover the types of capabilities the user agent supports for receiving media of the given kind, without reserving any resources, ports, or other state.

When the getCapabilities method is called, the user agent MUST run the following steps:

  1. Let kind be the method's first argument.

  2. If kind is neither "video" nor "audio" return null.

  3. Return a new RTCRtpCapabilities dictionary, with its codecs member initialized to the list of implemented receive codecs for kind, and its headerExtensions member initialized to the list of implemented header extensions for receiving for kind.

The list of implemented receive codecs, given kind, is an implementation-defined list of RTCRtpCodec dictionaries representing the most optimistic view of the codecs the user agent supports for receiving media of the given kind (video or audio).

The list of implemented header extensions for receiving, given kind, is an implementation-defined list of RTCRtpHeaderExtensionCapability dictionaries representing an optimistic view of the header extensions the user agent supports for receiving media of the given kind (video or audio).

These capabilities provide generally persistent cross-origin information on the device and thus increases the fingerprinting surface of the application. In privacy-sensitive contexts, user agents MAY consider mitigations such as reporting only a common subset of the capabilities. (This is a fingerprinting vector.)

Note

The codec capabilities returned affect the setCodecPreferences() algorithm and what inputs it throws InvalidModificationError on, and should also be consistent with information revealed by createOffer() and createAnswer() about codecs negotiated for reception, to ensure any privacy mitigations are effective.

getParameters

The getParameters() method returns the RTCRtpReceiver object's current parameters for how track is decoded.

When getParameters is called, the RTCRtpReceiveParameters dictionary is constructed as follows:

  • The headerExtensions sequence is populated based on the header extensions that the receiver is currently prepared to receive.
  • codecs is set to the value of the [[ReceiveCodecs]] internal slot.

    Note
    Both the local and remote description may affect this list of codecs. For example, if three codecs are offered, the receiver will be prepared to receive each of them and will return them all from getParameters. But if the remote endpoint only answers with two, the absent codec will no longer be returned by getParameters as the receiver no longer needs to be prepared to receive it.
  • rtcp.reducedSize is set to true if the receiver is currently prepared to receive reduced-size RTCP packets, and false otherwise. rtcp.cname is left out.
getContributingSources

Returns an RTCRtpContributingSource for each unique CSRC identifier received by this RTCRtpReceiver in the last 10 seconds, in descending timestamp order.

getSynchronizationSources

Returns an RTCRtpSynchronizationSource for each unique SSRC identifier received by this RTCRtpReceiver in the last 10 seconds, in descending timestamp order.

getStats

Gathers stats for this receiver only and reports the result asynchronously.

When the getStats() method is invoked, the user agent MUST run the following steps:

  1. Let selector be the RTCRtpReceiver object on which the method was invoked.

  2. Let p be a new promise, and run the following steps in parallel:

    1. Gather the stats indicated by selector according to the stats selection algorithm.

    2. Queue a global task on the networking task source given the current realm's global object as global to resolve p with the resulting RTCStatsReport object, containing the gathered stats.

  3. Return p.

The RTCRtpContributingSource and RTCRtpSynchronizationSource dictionaries contain information about a given contributing source (CSRC) or synchronization source (SSRC) respectively. When an audio or video frame from one or more RTP packets is delivered to the RTCRtpReceiver's MediaStreamTrack, the user agent MUST queue a task to update the relevant information for the RTCRtpContributingSource and RTCRtpSynchronizationSource dictionaries based on the content of those packets. The information relevant to the RTCRtpSynchronizationSource dictionary corresponding to the SSRC identifier, is updated each time, and if an RTP packet contains CSRC identifiers, then the information relevant to the RTCRtpContributingSource dictionaries corresponding to those CSRC identifiers is also updated. The user agent MUST process RTP packets in order of ascending RTP timestamps. The user agent MUST keep information from RTP packets delivered to the RTCRtpReceiver's MediaStreamTrack in the previous 10 seconds.

Note
Even if the MediaStreamTrack is not attached to any sink for playout, getSynchronizationSources and getContributingSources returns up-to-date information as long as the track is not ended; sinks are not a prerequisite for decoding RTP packets.
Note
As stated in the conformance section, requirements phrased as algorithms may be implemented in any manner so long as the end result is equivalent. So, an implementation does not need to literally queue a task for every frame, as long as the end result is that within a single event loop task execution, all returned RTCRtpSynchronizationSource and RTCRtpContributingSource dictionaries for a particular RTCRtpReceiver contain information from a single point in the RTP stream.
WebIDLdictionary RTCRtpContributingSource {
  required DOMHighResTimeStamp timestamp;
  required unsigned long source;
  double audioLevel;
  required unsigned long rtpTimestamp;
};

Dictionary RTCRtpContributingSource Members

timestamp of type DOMHighResTimeStamp, required

The timestamp indicating the most recent time a frame from an RTP packet, originating from this source, was delivered to the RTCRtpReceiver's MediaStreamTrack. The timestamp is defined as Performance.timeOrigin + Performance.now() at that time.

source of type unsigned long, required

The CSRC or SSRC identifier of the contributing or synchronization source.

audioLevel of type double

Only present for audio receivers. This is a value between 0..1 (linear), where 1.0 represents 0 dBov, 0 represents silence, and 0.5 represents approximately 6 dBSPL change in the sound pressure level from 0 dBov.

For CSRCs, this MUST be converted from the level value defined in [RFC6465] if the RFC 6465 header extension is present, otherwise this member MUST be absent.

For SSRCs, this MUST be converted from the level value defined in [RFC6464]. If the RFC 6464 header extension is not present in the received packets (such as if the other endpoint is not a user agent or is a legacy endpoint), this value SHOULD be absent.

Both RFCs define the level as an integral value from 0 to 127 representing the audio level in negative decibels relative to the loudest signal that the system could possibly encode. Thus, 0 represents the loudest signal the system could possibly encode, and 127 represents silence.

To convert these values to the linear 0..1 range, a value of 127 is converted to 0, and all other values are converted using the equation: 10^(-rfc_level/20).

rtpTimestamp of type unsigned long, required

The RTP timestamp, as defined in [RFC3550] Section 5.1, of the media played out at timestamp.

WebIDLdictionary RTCRtpSynchronizationSource : RTCRtpContributingSource {};

The RTCRtpSynchronizationSource dictionary is expected to serve as an extension point for the specification to surface data only available in SSRCs.

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 [RFC9429] (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 RFC9429 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 [RFC9429] (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.
WebIDL[Exposed=Window]
interface RTCRtpTransceiver {
  readonly attribute DOMString? mid;
  [SameObject] readonly attribute RTCRtpSender sender;
  [SameObject] readonly attribute RTCRtpReceiver receiver;
  attribute RTCRtpTransceiverDirection direction;
  readonly attribute RTCRtpTransceiverDirection? currentDirection;
  undefined stop();
  undefined setCodecPreferences(sequence<RTCRtpCodec> codecs);
};

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 [RFC9429] (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 [RFC9429] (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 [RFC9429] (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 [RFC9429] (section 4.2.1.) (The user agent MUST treat a stopping transceiver as stopped for the purposes of RFC9429 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 [RFC9429] (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. In parallel, stop sending media with sender, and send an RTCP BYE for each RTP stream that was being sent by sender, as specified in [RFC3550].

  4. In parallel, stop receiving media with receiver.

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

  6. Set transceiver.[[Direction]] to "inactive".

  7. 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
Candidate Addition 51:setCodecPreferences supports both send and receive codecs (filtered by direction) (PR #3018)

The setCodecPreferences method overrides the default codec preferences used by the user agent as input to negotiation. When When generating a session description using either using either createOffer or createAnswer, the user agent MUST use MUST filter the indicated codecspreferred codecs on direction and, if this results in the order a non-empty list, it MUST use the specified codecs in the the order of the codecs argument, for the media section section corresponding to this 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 by listing all codecs except for sendingthe ones to disable.

Note

If the m= section is used for receiving, the order of the codecs in the SDP (both the offer and the answer) tells the remote endpoint which codec the local endpoint prefers to receive. Even if the m= section is not used for receiving, an answerer that does not have any codec preferences of their own defaults to using the same order for its SDP answer.

Note

An RTCRtpSender defaults to sending what the remote endpoint indicated that it prefers to receive, but the application can change which codec to send amongst negotiated codecs by calling setParameters and specifying which codec to send. An RTCRtpReceiver is prepared to receive any negotiated codec.

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 sequence, or one that becomes empty after direction filtering, results in default valuecodec preferences.

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 [RFC8829RFC9429]. 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 will reject attempts to set codecs not matching codecs that are returned by found in either 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 is 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. Remove any duplicate values in codecs, ensuring that the first occurrence of each value remains in place.

  6. Let kind be the transceiver's transceiver kind.

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

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

  9. For each codec in codecs,

    1. If codec is not in codecCapabilities, throw InvalidModificationError.
  10. For each codec in codecs,

    1. If codec does not match any codec in codecCapabilities, throw InvalidModificationError.

  11. If codecs only contains entries for RTX, RED, FEC or Comfort Noise or is an empty set, throw InvalidModificationError. This ensures that we always have something to offer, regardless of transceiver.direction.

  12. Set transceiver.[[PreferredCodecs]] to codecs.

The codec dictionary match algorithm given two RTCRtpCodec dictionaries first and second, and an ignoreLevels boolean defaulting to false if not specified, is as follows:

  1. If first.mimeType is not an ASCII case-insensitive match for second.mimeType, return false.

  2. If first.clockRate is different from second.clockRate, return false.

  3. If either (but not both) of first.channels and second.channels are missing, or if they both exist and first.channels is different from second.channels, return false.

  4. If either (but not both) of first.sdpFmtpLine and second.sdpFmtpLine are missing, return false.

  5. If both first.sdpFmtpLine and second.sdpFmtpLine exist, run the following steps:

    1. If either of first.sdpFmtpLine and second.sdpFmtpLine is not in key-value format, return the result of performing an equals comparison between first.sdpFmtpLine and second.sdpFmtpLine.

    2. Let firstMediaFormat be a key-value map of the media formats constructed from first.sdpFmtpLine and secondMediaFormat be a key-value map of the media formats constructed from second.sdpFmtpLine.

      Note

      Which FMTP parameters make up the media format is codec specific. In some cases a parameter can be omitted and still be inferred, in which case it is also a part of the media format of that codec.

    3. If firstMediaFormat is not equal to secondMediaFormat, return false.

    4. Candidate Correction 52:Two codecs are considered the same even if level-id is not (PR #3023)

      If ignoreLevels is false and the highest complying bitstream levels inferred from first.sdpFmtpLine and second.sdpFmtpLine are different, return false.

      Note

      Even if ignoreLevels is true, some codecs (such as H.264) include levels in the media format, so that ignoring the level requires codec-specific parsing.

  6. Return true.

Note

If set, the offerer's receive 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 sending functionality is enabled by the addTransceiver method via its sendEncodings argument, or the setRemoteDescription method with a remote offer to receive simulcast, which are both methods on the RTCPeerConnection object. Additionally, the setParameters method on each RTCRtpSender object can be used to inspect and modify the functionality.

An RTCRtpSender's simulcast envelope is established in the first successful negotiation that involves it sending simulcast instead of unicast, and includes the maximum number of simulcast streams that can be sent, as well as the ordering of its encodings. This simulcast envelope may be narrowed (reducing the number of layers) in subsequent renegotiation, but cannot be reexpanded. Characteristics of individual simulcast streams can be modified using the setParameters method, but the simulcast envelope itself cannot be changed by that method.

One way to configure simulcast is with the sendEncodings option to addTransceiver(). While the addTrack() method lacks the sendEncodings argument necessary to configure simulcast, senders can be promoted to simulcast when the user agent is the answerer. Upon calling the setRemoteDescription method with a remote offer to receive simulcast, a proposed envelope is configured on an RTCRtpSender to contain the layers described in the specified session description. As long as this description isn't rolled back, the proposed envelope becomes the RTCRtpSender's simulcast envelope when negotiation completes. As above, this simulcast envelope may be narrowed in subsequent renegotiation, but not reexpanded.

Candidate Correction 12:Mark RTP Pause/Resume as not supported (PR #2755)

While setParameters cannot modify the simulcast 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. [RFC7728] (RTP Pause/Resume) is not supported, nor is signaling of pause/resume via SDP Offer/Answer. 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 [RFC9429] (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 [RFC9429], 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 of 3-layer spatial simulcast with all but the lowest resolution layer disabled
var encodings = [
  {rid: 'q', active: true, scaleResolutionDownBy: 4.0}
  {rid: 'h', active: false, scaleResolutionDownBy: 2.0},
  {rid: 'f', active: false},
];

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):

async function playMusicOnHold() {
  try {
    // Assume we have an audio transceiver and a music track named musicTrack
    await audio.sender.replaceTrack(musicTrack);
    // Mute received audio
    audio.receiver.track.enabled = false;
    // Set the direction to send-only (requires negotiation)
    audio.direction = 'sendonly';
  } catch (err) {
    console.error(err);
  }
}

To respond to a remote peer's "sendonly" offer:

async function handleSendonlyOffer() {
  try {
    // Apply the sendonly offer first,
    // to ensure the receiver is ready for ICE candidates.
    await pc.setRemoteDescription(sendonlyOffer);
    // Stop sending audio
    await audio.sender.replaceTrack(null);
    // Align our direction to avoid further negotiation
    audio.direction = 'recvonly';
    // Call createAnswer and send a recvonly answer
    await doAnswer();
  } catch (err) {
    // handle signaling error
  }
}

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

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

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

async function onOffHold() {
  try {
    // Apply the sendrecv offer first, to ensure receiver is ready for ICE candidates.
    await pc.setRemoteDescription(sendrecvOffer);
    // Start sending audio
    await audio.sender.replaceTrack(micTrack);
    // Set the direction sendrecv (just in time for the answer)
    audio.direction = 'sendrecv';
    // Call createAnswer and send a sendrecv answer
    await doAnswer();
  } catch (err) {
    // handle signaling error
  }
}

5.5 RTCDtlsTransport Interface

The RTCDtlsTransport interface allows an application access to information about the Datagram Transport Layer Security (DTLS) transport over which RTP and RTCP packets are sent and received by RTCRtpSender and RTCRtpReceiver objects, as well other data such as SCTP packets sent and received by data channels. In particular, DTLS adds security to an underlying transport, and the RTCDtlsTransport interface allows access to information about the underlying transport and the security added. RTCDtlsTransport objects are constructed as a result of calls to setLocalDescription() and setRemoteDescription(). Each RTCDtlsTransport object represents the DTLS transport layer for the RTP or RTCP component of a specific RTCRtpTransceiver, or a group of RTCRtpTransceivers if such a group has been negotiated via [RFC8843].

Note
A new DTLS association for an existing RTCRtpTransceiver will be represented by an existing RTCDtlsTransport object, whose state will be updated accordingly, as opposed to being represented by a new object.

An RTCDtlsTransport has a [[DtlsTransportState]] internal slot initialized to "new" and a [[RemoteCertificates]] slot initialized to an empty list.

When the underlying DTLS transport experiences an error, such as a certificate validation failure, or a fatal alert (see [RFC5246] section 7.2), the user agent MUST queue a task that runs the following steps:

  1. Let transport be the RTCDtlsTransport object to receive the state update and error notification.

  2. If the state of transport is already "failed", abort these steps.

  3. Set transport.[[DtlsTransportState]] to "failed".

  4. Fire an event named error using the RTCErrorEvent interface with its errorDetail attribute set to either "dtls-failure" or "fingerprint-failure", as appropriate, and other fields set as described under the RTCErrorDetailType enum description, at transport.

  5. Fire an event named statechange at transport.

When the underlying DTLS transport needs to update the state of the corresponding RTCDtlsTransport object for any other reason, the user agent MUST queue a task that runs the following steps:

  1. Let transport be the RTCDtlsTransport object to receive the state update.

  2. Let newState be the new state.

  3. Set transport.[[DtlsTransportState]] to newState.

  4. If newState is connected then let newRemoteCertificates be the certificate chain in use by the remote side, with each certificate encoded in binary Distinguished Encoding Rules (DER) [X690], and set transport.[[RemoteCertificates]] to newRemoteCertificates.

  5. Fire an event named statechange at transport.

WebIDL[Exposed=Window]
interface RTCDtlsTransport : EventTarget {
  [SameObject] readonly attribute RTCIceTransport iceTransport;
  readonly attribute RTCDtlsTransportState state;
  sequence<ArrayBuffer> getRemoteCertificates();
  attribute EventHandler onstatechange;
  attribute EventHandler onerror;
};

Attributes

iceTransport of type RTCIceTransport, readonly

The iceTransport attribute is the underlying transport that is used to send and receive packets. The underlying transport may not be shared between multiple active RTCDtlsTransport objects.

state of type RTCDtlsTransportState, readonly

The state attribute MUST, on getting, return the value of the [[DtlsTransportState]] slot.

onstatechange of type EventHandler
The event type of this event handler is statechange.
onerror of type EventHandler
The event type of this event handler is error.

Methods

getRemoteCertificates

Returns the value of [[RemoteCertificates]].

5.5.1 RTCDtlsTransportState Enum

WebIDLenum RTCDtlsTransportState {
  "new",
  "connecting",
  "connected",
  "closed",
  "failed"
};
RTCDtlsTransportState Enumeration description
Enum value Description
new DTLS has not started negotiating yet.
connecting DTLS is in the process of negotiating a secure connection and verifying the remote fingerprint.
connected DTLS has completed negotiation of a secure connection and verified the remote fingerprint.
closed The transport has been closed intentionally as the result of receipt of a close_notify alert, or calling close().
failed The transport has failed as the result of an error (such as receipt of an error alert or failure to validate the remote fingerprint).

5.5.2 RTCDtlsFingerprint Dictionary

The RTCDtlsFingerprint dictionary includes the hash function algorithm and certificate fingerprint as described in [RFC4572].

WebIDLdictionary RTCDtlsFingerprint {
  DOMString algorithm;
  DOMString value;
};
Dictionary RTCDtlsFingerprint Members
algorithm of type DOMString

One of the the hash function algorithms defined in the 'Hash function Textual Names' registry [IANA-HASH-FUNCTION].

value of type DOMString

The value of the certificate fingerprint in lowercase hex string as expressed utilizing the syntax of 'fingerprint' in [RFC4572] Section 5.

5.6 RTCIceTransport Interface

The RTCIceTransport interface allows an application access to information about the ICE transport over which packets are sent and received. In particular, ICE manages peer-to-peer connections which involve state which the application may want to access. RTCIceTransport objects are constructed as a result of calls to setLocalDescription() and setRemoteDescription(). The underlying ICE state is managed by the ICE agent; as such, the state of an RTCIceTransport changes when the ICE Agent provides indications to the user agent as described below. Each RTCIceTransport object represents the ICE transport layer for the RTP or RTCP component of a specific RTCRtpTransceiver, or a group of RTCRtpTransceivers if such a group has been negotiated via [RFC8843].

Note
An ICE restart for an existing RTCRtpTransceiver will be represented by an existing RTCIceTransport object, whose state will be updated accordingly, as opposed to being represented by a new object.
Candidate Correction 24:Queue two tasks upon finishing ICE gathering, and fire gatheringstatechange & icegatheringstatechange in same task (PR #2894)

When the ICE Agent indicates that it began gathering a generation of candidates for an RTCIceTransport transport associated with an RTCPeerConnection connection, the user agent MUST queue a task that runs the following steps:

  1. Let connection be the RTCPeerConnection object associated with this ICE Agent.

  2. If connection.[[IsClosed]] is true, abort these steps.

  3. Let transport be the RTCIceTransport for which candidate gathering began.

  4. Set transport.[[IceGathererState]] to gathering.

    .

  5. Set connection.[[IceGatheringState]] to the value of deriving a new state value as described by the RTCIceGatheringState enum.

  6. Let connectionIceGatheringStateChanged be true if connection.[[IceGatheringState]] changed in the previous step, otherwise false.

  7. Do not read or modify state beyond this point.

  8. Fire an event named gatheringstatechange at transport.

  9. Update the ICE gathering state of connection.

  10. If connectionIceGatheringStateChanged is true, fire an event named icegatheringstatechange at connection.

When the ICE Agent is finished gathering a generation of candidates for an RTCIceTransport transport associated with an RTCPeerConnection connection, and those candidates have been surfaced to the application, the user agent MUST queue a task that runs to run the following following steps:

  1. Let connection be the RTCPeerConnection object associated with this ICE Agent.

  2. If connection.[[IsClosed]] is true, abort these steps.

  3. Let transport be the RTCIceTransport for which candidate gathering finished.

  4. If connection.[[PendingLocalDescription]] is not null, and represents the ICE generation for which gathering finished, add a=end-of-candidates to connection.[[PendingLocalDescription]].sdp.

  5. If connection.[[CurrentLocalDescription]] is not null, and represents the ICE generation for which gathering finished, add a=end-of-candidates to connection.[[CurrentLocalDescription]].sdp.

  6. Let newCandidateendOfGatheringCandidate be the result of creating an an RTCIceCandidate with a new dictionary whose sdpMid and sdpMLineIndex are set to the values associated with this RTCIceTransport, usernameFragment is is set to the username fragment of the generation of candidates for which gathering finished, and candidate is set set to an empty string"".

  7. Fire an event named icecandidate using the RTCPeerConnectionIceEvent interface with the candidate attribute set to newCandidateendOfGatheringCandidate at connection.

  1. If another generation of candidates is still being gathered, abort these steps.

    Note
    This may occur if an ICE restart is initiated while the ICE agent is still gathering the previous generation of candidates.
  2. Set transport.[[IceGathererState]] to complete.

  3. Fire an event named gatheringstatechange at transport.

  4. Update the ICE gathering state of connection.

When the ICE Agent has queued the above task, and no other generations of candidates is being gathered, the user agent MUST also queue a second task to run the following steps:

Note
Other generations of candidates might still be gathering if an ICE restart was initiated while the ICE agent is still gathering the previous generation of candidates.
  1. If connection.[[IsClosed]] is true, abort these steps.

  2. Set transport.[[IceGathererState]] to complete.

  3. Set connection.[[IceGatheringState]] to the value of deriving a new state value as described by the RTCIceGatheringState enum.

  4. Let connectionIceGatheringStateChanged be true if connection.[[IceGatheringState]] changed in the previous step, otherwise false.

  5. Do not read or modify state beyond this point.

  6. Fire an event named gatheringstatechange at transport.

  7. If connectionIceGatheringStateChanged is true, fire an event named icegatheringstatechange at connection.

  8. Fire an event named icecandidate using the RTCPeerConnectionIceEvent interface with the candidate attribute set to null at connection.

    Note
    The null candidate event is fired to ensure legacy compatibility. New code should monitor the gathering state of RTCIceTransport and/or RTCPeerConnection.

When the ICE Agent indicates that a new ICE candidate is available for an RTCIceTransport, either by taking one from the ICE candidate pool or gathering it from scratch, the user agent MUST queue a task that runs the following steps:

  1. Let candidate be the available ICE candidate.

  2. Let connection be the RTCPeerConnection object associated with this ICE Agent.

  3. If connection.[[IsClosed]] is true, abort these steps.

  4. If either connection.[[PendingLocalDescription]] or connection.[[CurrentLocalDescription]] are not null, and represent the ICE generation for which candidate was gathered, surface the candidate with candidate and connection, and abort these steps.

  5. Otherwise, append candidate to connection.[[EarlyCandidates]].

When the ICE Agent signals that the ICE role has changed due to an ICE binding request with a role collision per [RFC8445] section 7.3.1.1, the UA will queue a task to set the value of [[IceRole]] to the new value.

To release early candidates of a connection, run the following steps:

  1. For each candidate, candidate, in connection.[[EarlyCandidates]], queue a task to surface the candidate with candidate and connection.

  2. Set connection.[[EarlyCandidates]] to an empty list.

To surface a candidate with candidate and connection, run the following steps:

  1. If connection.[[IsClosed]] is true, abort these steps.

  2. Let transport be the RTCIceTransport for which candidate is being made available.

  3. If connection.[[PendingLocalDescription]] is not null, and represents the ICE generation for which candidate was gathered, add candidate to connection.[[PendingLocalDescription]].sdp.

  4. If connection.[[CurrentLocalDescription]] is not null, and represents the ICE generation for which candidate was gathered, add candidate to connection.[[CurrentLocalDescription]].sdp.

  5. Let newCandidate be the result of creating an RTCIceCandidate with a new dictionary whose sdpMid and sdpMLineIndex are set to the values associated with this RTCIceTransport, usernameFragment is set to the username fragment of the candidate, and candidate is set to a string encoded using the candidate-attribute grammar to represent candidate.

  6. Add newCandidate to transport's set of local candidates.

  7. Fire an event named icecandidate using the RTCPeerConnectionIceEvent interface with the candidate attribute set to newCandidate at connection.

The RTCIceTransportState of an RTCIceTransport may change because a candidate pair with a usable connection was found and selected or it may change without the selected candidate pair changing. The selected pair and RTCIceTransportState are related and are handled in the same task.

When the ICE Agent indicates that an RTCIceTransport has changed either the selected candidate pair, the RTCIceTransportState or both, the user agent MUST queue a task that runs the steps to change the selected candidate pair and state:

  1. Let connection be the RTCPeerConnection object associated with this ICE Agent.

  2. If connection.[[IsClosed]] is true, abort these steps.

  3. Let transport be the RTCIceTransport whose state is changing.

  4. Let selectedCandidatePairChanged be false.

  5. Let transportIceConnectionStateChanged be false.

  6. Let connectionIceConnectionStateChanged be false.

  7. Let connectionStateChanged be false.

  8. If transport's selected candidate pair was changed, run the following steps:

    1. Let newCandidatePair be the result of creating an RTCIceCandidatePair with local and remote, representing the local and remote candidates of the indicated pair if one is selected, and null otherwise.

    2. Set transport.[[SelectedCandidatePair]] to newCandidatePair.

    3. Set selectedCandidatePairChanged to true.

  9. If transport's RTCIceTransportState was changed, run the following steps:

    1. Set transport.[[IceTransportState]] to the new indicated RTCIceTransportState.

    2. Set transportIceConnectionStateChanged to true.

    3. Set connection.[[IceConnectionState]] to the value of deriving a new state value as described by the RTCIceConnectionState enum.

    4. If connection.[[IceConnectionState]] changed in the previous step, set connectionIceConnectionStateChanged to true.

    5. Set connection.[[ConnectionState]] to the value of deriving a new state value as described by the RTCPeerConnectionState enum.

    6. If connection.[[ConnectionState]] changed in the previous step, set connectionStateChanged to true.

  10. If selectedCandidatePairChanged is true, fire an event named selectedcandidatepairchange at transport.

  11. If transportIceConnectionStateChanged is true, fire an event named statechange at transport.

  12. If connectionIceConnectionStateChanged is true, fire an event named iceconnectionstatechange at connection.

  13. If connectionStateChanged is true, fire an event named connectionstatechange at connection.

An RTCIceTransport object has the following internal slots:

WebIDL[Exposed=Window]
interface RTCIceTransport : EventTarget {
  readonly attribute RTCIceRole role;
  readonly attribute RTCIceComponent component;
  readonly attribute RTCIceTransportState state;
  readonly attribute RTCIceGathererState gatheringState;
  sequence<RTCIceCandidate> getLocalCandidates();
  sequence<RTCIceCandidate> getRemoteCandidates();
  RTCIceCandidatePair? getSelectedCandidatePair();
  RTCIceParameters? getLocalParameters();
  RTCIceParameters? getRemoteParameters();
  attribute EventHandler onstatechange;
  attribute EventHandler ongatheringstatechange;
  attribute EventHandler onselectedcandidatepairchange;
};

Attributes

role of type RTCIceRole, readonly

The role attribute MUST, on getting, return the value of the [[IceRole]] internal slot.

component of type RTCIceComponent, readonly

The component attribute MUST return the ICE component of the transport. When RTCP mux is used, a single RTCIceTransport transports both RTP and RTCP and component is set to "rtp".

state of type RTCIceTransportState, readonly

The state attribute MUST, on getting, return the value of the [[IceTransportState]] slot.

gatheringState of type RTCIceGathererState, readonly

The gatheringState attribute MUST, on getting, return the value of the [[IceGathererState]] slot.

onstatechange of type EventHandler
This event handler, of event handler event type statechange, MUST be fired any time the RTCIceTransport state changes.
ongatheringstatechange of type EventHandler
This event handler, of event handler event type gatheringstatechange, MUST be fired any time the RTCIceTransport's [[IceGathererState]] changes.
onselectedcandidatepairchange of type EventHandler
This event handler, of event handler event type selectedcandidatepairchange, MUST be fired any time the RTCIceTransport's selected candidate pair changes.

Methods

getLocalCandidates

Returns a sequence describing the local ICE candidates gathered for this RTCIceTransport and sent in onicecandidate.

getRemoteCandidates

Returns a sequence describing the remote ICE candidates received by this RTCIceTransport via addIceCandidate().

Note
getRemoteCandidates will not expose peer reflexive candidates since they are not received via addIceCandidate().
getSelectedCandidatePair

Returns the selected candidate pair on which packets are sent. This method MUST return the value of the [[SelectedCandidatePair]] slot. When RTCIceTransport.state is "new" or "closed" getSelectedCandidatePair returns null.

getLocalParameters

Returns the local ICE parameters received by this RTCIceTransport via setLocalDescription, or null if the parameters have not yet been received.

getRemoteParameters

Returns the remote ICE parameters received by this RTCIceTransport via setRemoteDescription or null if the parameters have not yet been received.

5.6.1 RTCIceParameters Dictionary

WebIDLdictionary RTCIceParameters {
  DOMString usernameFragment;
  DOMString password;
};
Dictionary RTCIceParameters Members
usernameFragment of type DOMString

The ICE username fragment as defined in [RFC5245], Section 7.1.2.3.

password of type DOMString

The ICE password as defined in [RFC5245], Section 7.1.2.3.

Candidate Addition 45:Convert RTCIceCandidatePair dictionary to an interface (PR #2961)

5.6.2 RTCIceCandidatePair Dictionary

5.6.2 RTCIceCandidatePair Interface

This interface represents an ICE candidate pair, described in Section 4 in [RFC8445]. An RTCIceCandidatePair is a pairing of a local and a remote RTCIceCandidate.

To create an RTCIceCandidatePair with RTCIceCandidate objects, local and remote, run the following steps:

  1. Let candidatePair be a newly created RTCIceCandidatePair object.
  2. Let candidatePair have a [[Local]] internal slot, initialized to local.
  3. Let candidatePair have a [[Remote]] internal slot, initialized to remote.
  4. Return candidatePair.
dictionary [Exposed=Window]
interface RTCIceCandidatePair {
  [SameObject] readonly attribute RTCIceCandidate local;
  [SameObject] readonly attribute RTCIceCandidate remote;
};
Dictionary RTCIceCandidatePair Members
Attributes
local of type RTCIceCandidate , readonly

The local ICE candidate.

The local attribute MUST, on getting, return the value of the [[Local]] internal slot.

remote of type RTCIceCandidate , readonly

The remote ICE candidate.

The remote attribute MUST, on getting, return the value of the [[Remote]] internal slot.

5.6.3 RTCIceGathererState Enum

WebIDLenum RTCIceGathererState {
  "new",
  "gathering",
  "complete"
};
RTCIceGathererState Enumeration description
Enum value Description
new The RTCIceTransport was just created, and has not started gathering candidates yet.
gathering The RTCIceTransport is in the process of gathering candidates.
complete The RTCIceTransport has completed gathering and the end-of-candidates indication for this transport has been sent. It will not gather candidates again until an ICE restart causes it to restart.

5.6.4 RTCIceTransportState Enum

WebIDLenum RTCIceTransportState {
  "closed",
  "failed",
  "disconnected",
  "new",
  "checking",
  "completed",
  "connected"
};
RTCIceTransportState Enumeration description
Enum value Description
closed The RTCIceTransport has shut down and is no longer responding to STUN requests.
failed
The RTCIceTransport has finished gathering, received an indication that there are no more remote candidates, finished checking all candidate pairs, and all pairs have either failed connectivity checks or lost consent, and either zero local candidates were gathered or the PAC timer has expired [RFC8863]. This is a terminal state until ICE is restarted. Since an ICE restart may cause connectivity to resume, entering the "failed" state does not cause DTLS transports, SCTP associations or the data channels that run over them to close, or tracks to mute.
disconnected The ICE Agent has determined that connectivity is currently lost for this RTCIceTransport. This is a transient state that may trigger intermittently (and resolve itself without action) on a flaky network. The way this state is determined is implementation dependent. Examples include:
  • Losing the network interface for the connection in use.
  • Repeatedly failing to receive a response to STUN requests.
Alternatively, the RTCIceTransport has finished checking all existing candidates pairs and not found a connection (or consent checks [RFC7675] once successful, have now failed), but it is still gathering and/or waiting for additional remote candidates.
new The RTCIceTransport is gathering candidates and/or waiting for remote candidates to be supplied, and has not yet started checking.
checking The RTCIceTransport has received at least one remote candidate (by means of addIceCandidate() or discovered as a peer-reflexive candidate when receiving a STUN binding request) and is checking candidate pairs and has either not yet found a connection or consent checks [RFC7675] have failed on all previously successful candidate pairs. In addition to checking, it may also still be gathering.
completed The RTCIceTransport has finished gathering, received an indication that there are no more remote candidates, finished checking all candidate pairs and found a connection. If consent checks [RFC7675] subsequently fail on all successful candidate pairs, the state transitions to "failed".
connected The RTCIceTransport has found a usable connection, but is still checking other candidate pairs to see if there is a better connection. It may also still be gathering and/or waiting for additional remote candidates. If consent checks [RFC7675] fail on the connection in use, and there are no other successful candidate pairs available, then the state transitions to "checking" (if there are candidate pairs remaining to be checked) or "disconnected" (if there are no candidate pairs to check, but the peer is still gathering and/or waiting for additional remote candidates).
Note

The most common transitions for a successful call will be new -> checking -> connected -> completed, but under specific circumstances (only the last checked candidate succeeds, and gathering and the no-more candidates indication both occur prior to success), the state can transition directly from "checking" to "completed".

An ICE restart causes candidate gathering and connectivity checks to begin anew, causing a transition to "connected" if begun in the "completed" state. If begun in the transient "disconnected" state, it causes a transition to "checking", effectively forgetting that connectivity was previously lost.

The "failed" and "completed" states require an indication that there are no additional remote candidates. This can be indicated by calling addIceCandidate with a candidate value whose candidate property is set to an empty string or by canTrickleIceCandidates being set to false.

Some example state transitions are:

ICE transport state transition diagram
Figure 2 Non-normative ICE transport state transition diagram

5.6.5 RTCIceRole Enum

WebIDLenum RTCIceRole {
  "unknown",
  "controlling",
  "controlled"
};
RTCIceRole Enumeration description
Enum value Description
unknown An agent whose role as defined by [RFC5245], Section 3, has not yet been determined.
controlling A controlling agent as defined by [RFC5245], Section 3.
controlled A controlled agent as defined by [RFC5245], Section 3.

5.6.6 RTCIceComponent Enum

WebIDLenum RTCIceComponent {
  "rtp",
  "rtcp"
};
RTCIceComponent Enumeration description
Enum value Description
rtp The ICE Transport is used for RTP (or RTCP multiplexing), as defined in [RFC5245], Section 4.1.1.1. Protocols multiplexed with RTP (e.g. data channel) share its component ID. This represents the component-id value 1 when encoded in candidate-attribute.
rtcp The ICE Transport is used for RTCP as defined by [RFC5245], Section 4.1.1.1. This represents the component-id value 2 when encoded in candidate-attribute.

5.7 RTCTrackEvent

The track event uses the RTCTrackEvent interface.

WebIDL[Exposed=Window]
interface RTCTrackEvent : Event {
  constructor(DOMString type, RTCTrackEventInit eventInitDict);
  readonly attribute RTCRtpReceiver receiver;
  readonly attribute MediaStreamTrack track;
  [SameObject] readonly attribute FrozenArray<MediaStream> streams;
  readonly attribute RTCRtpTransceiver transceiver;
};

Constructors

RTCTrackEvent.constructor()

Attributes

receiver of type RTCRtpReceiver, readonly

The receiver attribute represents the RTCRtpReceiver object associated with the event.

track of type MediaStreamTrack, readonly

The track attribute represents the MediaStreamTrack object that is associated with the RTCRtpReceiver identified by receiver.

streams of type FrozenArray<MediaStream>, readonly

The streams attribute returns an array of MediaStream objects representing the MediaStreams that this event's track is a part of.

transceiver of type RTCRtpTransceiver, readonly

The transceiver attribute represents the RTCRtpTransceiver object associated with the event.

WebIDLdictionary RTCTrackEventInit : EventInit {
  required RTCRtpReceiver receiver;
  required MediaStreamTrack track;
  sequence<MediaStream> streams = [];
  required RTCRtpTransceiver transceiver;
};

Dictionary RTCTrackEventInit Members

receiver of type RTCRtpReceiver, required

The receiver member represents the RTCRtpReceiver object associated with the event.

track of type MediaStreamTrack, required

The track member represents the MediaStreamTrack object that is associated with the RTCRtpReceiver identified by receiver.

streams of type sequence<MediaStream>, defaulting to []

The streams member is an array of MediaStream objects representing the MediaStreams that this event's track is a part of.

transceiver of type RTCRtpTransceiver, required

The transceiver attribute represents the RTCRtpTransceiver object associated with the event.

6. Peer-to-peer Data API

The Peer-to-peer Data API lets a web application send and receive generic application data peer-to-peer. The API for sending and receiving data models the behavior of Web Sockets.

6.1 RTCPeerConnection Interface Extensions

The Peer-to-peer data API extends the RTCPeerConnection interface as described below.

WebIDL          partial interface RTCPeerConnection {
  readonly attribute RTCSctpTransport? sctp;
  RTCDataChannel createDataChannel(USVString label,
                                   optional RTCDataChannelInit dataChannelDict = {});
  attribute EventHandler ondatachannel;
};

Attributes

sctp of type RTCSctpTransport, readonly, nullable

The SCTP transport over which SCTP data is sent and received. If SCTP has not been negotiated, the value is null. This attribute MUST return the RTCSctpTransport object stored in the [[SctpTransport]] internal slot.

ondatachannel of type EventHandler
The event type of this event handler is datachannel.

Methods

createDataChannel

Creates a new RTCDataChannel object with the given label. The RTCDataChannelInit dictionary can be used to configure properties of the underlying channel such as data reliability.

When the createDataChannel method is invoked, the user agent MUST run the following steps.

  1. Let connection be the RTCPeerConnection object on which the method is invoked.

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

  3. Create an RTCDataChannel, channel.

  4. Initialize channel.[[DataChannelLabel]] to the value of the first argument.

  5. If the UTF-8 representation of [[DataChannelLabel]] is longer than 65535 bytes, throw a TypeError.

  6. Let options be the second argument.

  7. Initialize channel.[[MaxPacketLifeTime]] to option.maxPacketLifeTime, if present, otherwise null.

  8. Initialize channel.[[MaxRetransmits]] to option.maxRetransmits, if present, otherwise null.

  9. Initialize channel.[[Ordered]] to option.ordered.

  10. Initialize channel.[[DataChannelProtocol]] to option.protocol.

  11. If the UTF-8 representation of [[DataChannelProtocol]] is longer than 65535 bytes, throw a TypeError.

  12. Initialize channel.[[Negotiated]] to option.negotiated.

  13. Initialize channel.[[DataChannelId]] to the value of option.id, if it is present and [[Negotiated]] is true, otherwise null.

    Note
    This means the id member will be ignored if the data channel is negotiated in-band; this is intentional. Data channels negotiated in-band should have IDs selected based on the DTLS role, as specified in [RFC8832].
  14. If [[Negotiated]] is true and [[DataChannelId]] is null, throw a TypeError.

  15. If both [[MaxPacketLifeTime]] and [[MaxRetransmits]] attributes are set (not null), throw a TypeError.

  16. If a setting, either [[MaxPacketLifeTime]] or [[MaxRetransmits]], has been set to indicate unreliable mode, and that value exceeds the maximum value supported by the user agent, the value MUST be set to the user agents maximum value.

  17. If [[DataChannelId]] is equal to 65535, which is greater than the maximum allowed ID of 65534 but still qualifies as an unsigned short, throw a TypeError.

  18. If the [[DataChannelId]] slot is null (due to no ID being passed into createDataChannel, or [[Negotiated]] being false), and the DTLS role of the SCTP transport has already been negotiated, then initialize [[DataChannelId]] to a value generated by the user agent, according to [RFC8832], and skip to the next step. If no available ID could be generated, or if the value of the [[DataChannelId]] slot is being used by an existing RTCDataChannel, throw an OperationError exception.

    Note
    If the [[DataChannelId]] slot is null after this step, it will be populated during the RTCSctpTransport connected procedure.
  19. Let transport be connection.[[SctpTransport]].

    If the [[DataChannelId]] slot is not null, transport is in the "connected" state and [[DataChannelId]] is greater or equal to transport.[[MaxChannels]], throw an OperationError.

  20. If channel is the first RTCDataChannel created on connection, update the negotiation-needed flag for connection.

  21. Append channel to connection.[[DataChannels]].

  22. Return channel and continue the following steps in parallel.

  23. Create channel's associated underlying data transport and configure it according to the relevant properties of channel.

6.1.1 RTCSctpTransport Interface

The RTCSctpTransport interface allows an application access to information about the SCTP data channels tied to a particular SCTP association.

6.1.1.1 Create an instance

To create an RTCSctpTransport with an initial state, initialState, run the following steps:

  1. Let transport be a new RTCSctpTransport object.

  2. Let transport have a [[SctpTransportState]] internal slot initialized to initialState.

  3. Let transport have a [[MaxMessageSize]] internal slot and run the steps labeled update the data max message size to initialize it.

  4. Let transport have a [[MaxChannels]] internal slot initialized to null.

  5. Return transport.

6.1.1.2 Update max message size

To update the data max message size of an RTCSctpTransport run the following steps:

  1. Let transport be the RTCSctpTransport object to be updated.

  2. Let remoteMaxMessageSize be the value of the max-message-size SDP attribute read from the remote description, as described in [RFC8841] (section 6), or 65536 if the attribute is missing.

  3. Let canSendSize be the number of bytes that this client can send (i.e. the size of the local send buffer) or 0 if the implementation can handle messages of any size.

  4. If both remoteMaxMessageSize and canSendSize are 0, set [[MaxMessageSize]] to the positive Infinity value.

  5. Else, if either remoteMaxMessageSize or canSendSize is 0, set [[MaxMessageSize]] to the larger of the two.

  6. Else, set [[MaxMessageSize]] to the smaller of remoteMaxMessageSize or canSendSize.

6.1.1.3 Connected procedure

Once an SCTP transport is connected, meaning the SCTP association of an RTCSctpTransport has been established, the user agent MUST queue a task that runs the following steps:

  1. Let transport be the RTCSctpTransport object.

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

  3. Set [[MaxChannels]] to the minimum of the negotiated amount of incoming and outgoing SCTP streams.

  4. For each of connection's RTCDataChannel:

    1. Let channel be the RTCDataChannel object.

    2. If channel.[[DataChannelId]] is null, initialize [[DataChannelId]] to the value generated by the underlying sctp data channel, according to [RFC8832].

    3. If channel.[[DataChannelId]] is greater or equal to transport.[[MaxChannels]], or the previous step failed to assign an id, close the channel due to a failure. Otherwise, announce the channel as open.

  5. Fire an event named statechange at transport.

    Note

    This event is fired before the open events fired by announcing the channel as open; the open events are fired from a separate queued task.

WebIDL[Exposed=Window]
interface RTCSctpTransport : EventTarget {
  readonly attribute RTCDtlsTransport transport;
  readonly attribute RTCSctpTransportState state;
  readonly attribute unrestricted double maxMessageSize;
  readonly attribute unsigned short? maxChannels;
  attribute EventHandler onstatechange;
};
Attributes
transport of type RTCDtlsTransport, readonly

The transport over which all SCTP packets for data channels will be sent and received.

state of type RTCSctpTransportState, readonly

The current state of the SCTP transport. On getting, this attribute MUST return the value of the [[SctpTransportState]] slot.

maxMessageSize of type unrestricted double, readonly

The maximum size of data that can be passed to RTCDataChannel's send() method. The attribute MUST, on getting, return the value of the [[MaxMessageSize]] slot.

maxChannels of type unsigned short , readonly, nullable

The maximum amount of RTCDataChannel's that can be used simultaneously. The attribute MUST, on getting, return the value of the [[MaxChannels]] slot.

Note
This attribute's value will be null until the SCTP transport goes into the "connected" state.
onstatechange of type EventHandler

The event type of this event handler is statechange.

6.1.2 RTCSctpTransportState Enum

RTCSctpTransportState indicates the state of the SCTP transport.

WebIDLenum RTCSctpTransportState {
  "connecting",
  "connected",
  "closed"
};
RTCSctpTransportState Enumeration description
Enum value Description
connecting

The RTCSctpTransport is in the process of negotiating an association. This is the initial state of the [[SctpTransportState]] slot when an RTCSctpTransport is created.

connected

When the negotiation of an association is completed, a task is queued to update the [[SctpTransportState]] slot to "connected".

closed

A task is queued to update the [[SctpTransportState]] slot to "closed" when:

  • a SHUTDOWN or ABORT chunk is received.
  • the SCTP association has been closed intentionally, such as by closing the peer connection or applying a remote description that rejects data or changes the SCTP port.
  • the underlying DTLS association has transitioned to "closed" state.

Note that the last transition is logical due to the fact that an SCTP association requires an established DTLS connection - [RFC8261] section 6.1 specifies that SCTP over DTLS is single-homed - and that no way of of switching to an alternate transport is defined in this API.

6.2 RTCDataChannel

The RTCDataChannel interface represents a bi-directional data channel between two peers. An RTCDataChannel is created via a factory method on an RTCPeerConnection object. The messages sent between the browsers are described in [RFC8831] and [RFC8832].

There are two ways to establish a connection with RTCDataChannel. The first way is to simply create an RTCDataChannel at one of the peers with the negotiated RTCDataChannelInit dictionary member unset or set to its default value false. This will announce the new channel in-band and trigger an RTCDataChannelEvent with the corresponding RTCDataChannel object at the other peer. The second way is to let the application negotiate the RTCDataChannel. To do this, create an RTCDataChannel object with the negotiated RTCDataChannelInit dictionary member set to true, and signal out-of-band (e.g. via a web server) to the other side that it SHOULD create a corresponding RTCDataChannel with the negotiated RTCDataChannelInit dictionary member set to true and the same id. This will connect the two separately created RTCDataChannel objects. The second way makes it possible to create channels with asymmetric properties and to create channels in a declarative way by specifying matching ids.

Each RTCDataChannel has an associated underlying data transport that is used to transport actual data to the other peer. In the case of SCTP data channels utilizing an RTCSctpTransport (which represents the state of the SCTP association), the underlying data transport is the SCTP stream pair. The transport properties of the underlying data transport, such as in order delivery settings and reliability mode, are configured by the peer as the channel is created. The properties of a channel cannot change after the channel has been created. The actual wire protocol between the peers is specified by the WebRTC DataChannel Protocol specification [RFC8831].

An RTCDataChannel can be configured to operate in different reliability modes. A reliable channel ensures that the data is delivered at the other peer through retransmissions. An unreliable channel is configured to either limit the number of retransmissions ( maxRetransmits ) or set a time during which transmissions (including retransmissions) are allowed ( maxPacketLifeTime ). These properties can not be used simultaneously and an attempt to do so will result in an error. Not setting any of these properties results in a reliable channel.

An RTCDataChannel, created with createDataChannel or dispatched via an RTCDataChannelEvent, MUST initially be in the "connecting" state. When the RTCDataChannel object's underlying data transport is ready, the user agent MUST announce the RTCDataChannel as open.

6.2.1 Creating a data channel

To create an RTCDataChannel, run the following steps:

  1. Let channel be a newly created RTCDataChannel object.

  2. Let channel have a [[ReadyState]] internal slot initialized to "connecting".

  3. Let channel have a [[BufferedAmount]] internal slot initialized to 0.

  4. Let channel have internal slots named [[DataChannelLabel]], [[Ordered]], [[MaxPacketLifeTime]], [[MaxRetransmits]], [[DataChannelProtocol]], [[Negotiated]], and [[DataChannelId]].

  5. Let channel have a [[IsTransferable]] internal slot initialized to true.
  6. Queue a task to run the following step:
    1. Set channel.[[IsTransferable]] to false.

    This task needs to run before any task enqueued by the receiving messages on a data channel algorithm for channel. This ensures that no message is lost during the transfer of a RTCDataChannel.

  7. Return channel.

6.2.2 Announcing a data channel as open

When the user agent is to announce an RTCDataChannel as open, the user agent MUST queue a task to run the following steps:

  1. If the associated RTCPeerConnection object's [[IsClosed]] slot is true, abort these steps.

  2. Let channel be the RTCDataChannel object to be announced.

  3. If channel.[[ReadyState]] is "closing" or "closed", abort these steps.

  4. Set channel.[[ReadyState]] to "open".

  5. Fire an event named open at channel.

6.2.3 Announcing a data channel instance

When an underlying data transport is to be announced (the other peer created a channel with negotiated unset or set to false), the user agent of the peer that did not initiate the creation process MUST queue a task to run the following steps:

  1. Let connection be the RTCPeerConnection object associated with the underlying data transport.

  2. If connection.[[IsClosed]] is true, abort these steps.

  3. Create an RTCDataChannel, channel.

  4. Let configuration be an information bundle received from the other peer as a part of the process to establish the underlying data transport described by the WebRTC DataChannel Protocol specification [RFC8832].

  5. Initialize channel.[[DataChannelLabel]], [[Ordered]], [[MaxPacketLifeTime]], [[MaxRetransmits]], [[DataChannelProtocol]], and [[DataChannelId]] internal slots to the corresponding values in configuration.

  6. Initialize channel.[[Negotiated]] to false.

  7. Append channel to connection.[[DataChannels]].

  8. Set channel.[[ReadyState]] to "open" (but do not fire the open event, yet).

    Note
    This allows to start sending messages inside of the datachannel event handler prior to the open event being fired.
  9. Fire an event named datachannel using the RTCDataChannelEvent interface with the channel attribute set to channel at connection.

  10. Announce the data channel as open.

Candidate Correction 38:Prevent GC of non-closed RTCDataChannels (PR #2902)

6.2.4 Closing procedure

6.2.4 Closing procedure

An RTCDataChannel object's underlying data transport may be torn down in a non-abrupt manner by running the closing procedure. When that happens the user agent MUST queue a task to run the following steps:

  1. Let channel be the RTCDataChannel object whose underlying data transport was closed.

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

  3. Remove channel from connection.[[DataChannels]].

  4. Unless the procedure was initiated by channel.close, set channel.[[ReadyState]] to "closing" and fire an event named closing at channel.

  5. Run the following steps in parallelin parallel:

    1. Finish sending all currently pending messages of the channel.

    2. Follow the closing procedure defined for the channel's underlying data transport :

      1. In the case of an SCTP-based transport, follow [RFC8831], section 6.7.

    3. Render Close the channel's data transport closed by following the associated procedure.

6.2.5 Announcing a data channel as closed

When an RTCDataChannel object's underlying data transport has been closed, the user agent MUST queue a task to run the following steps:

  1. Let channel be the RTCDataChannel object whose underlying data transport was closed.

  2. If channel.[[ReadyState]] is "closed", abort these steps.
  3. Set channel.[[ReadyState]] to "closed".

  4. Remove channel from connection.[[DataChannels]] if it is still there.

  5. If the transport was closed with an error, fire an event named error using the RTCErrorEvent interface with its errorDetail attribute set to "sctp-failure" at channel.

  6. Fire an event named close at channel.

6.2.6 Transfering data channel

The RTCDataChannel transfer steps, given value and dataHolder, are:

  1. If value.[[IsTransferable]] is false, throw a DataCloneError DOMException.

  2. Set dataHolder.[[ReadyState]] to value.[[ReadyState]].

  3. Set dataHolder.[[DataChannelLabel]] to value.[[DataChannelLabel]].

  4. Set dataHolder.[[Ordered]] to value.[[Ordered]].

  5. Set dataHolder.[[MaxPacketLifeTime]] to value..[[MaxPacketLifeTime]]

  6. Set dataHolder.[[MaxRetransmits]] to value.[[MaxRetransmits]].

  7. Set dataHolder.[[DataChannelProtocol]] to value.[[DataChannelProtocol]].

  8. Set dataHolder.[[Negotiated]] to value.[[Negotiated]].

  9. Set dataHolder.[[DataChannelId]] to value.[[DataChannelId]].

  10. Set dataHolder’s underlying data transport to value underlying data transport.

  11. Set value.[[IsTransferable]] to false.

  12. Set value.[[ReadyState]] to "closed".

The RTCDataChannel transfer-receiving steps, given dataHolder and channel, are:

  1. Initialize channel.[[ReadyState]] to dataHolder.[[ReadyState]].

  2. Initialize channel.[[DataChannelLabel]] to dataHolder.[[DataChannelLabel]].

  3. Initialize channel.[[Ordered]] to dataHolder.[[Ordered]].

  4. Initialize channel.[[MaxPacketLifeTime]] to dataHolder.[[MaxPacketLifeTime]].

  5. Initialize channel.[[MaxRetransmits]] to dataHolder.[[MaxRetransmits]].

  6. Initialize channel.[[DataChannelProtocol]] to dataHolder.[[DataChannelProtocol]].

  7. Initialize channel.[[Negotiated]] to dataHolder.[[Negotiated]].

  8. Initialize channel.[[DataChannelId]] to dataHolder.[[DataChannelId]].

  9. Initialize channel’s underlying data transport to dataHolder’s underlying data transport.

The above steps do not need to transfer [[BufferedAmount]] as its value will always be equal to 0. The reason is an RTCDataChannel can be transferred only if its send() algorithm was not called prior the transfer.

If the underlying data transport is closed at the time of the transfer-receiving steps, the RTCDataChannel object will be closed by running the announcing a data channel as closed algorithm immediately after the transfer-receiving steps.

6.2.7 Error on creating data channels

In some cases, the user agent may be unable to create an RTCDataChannel 's underlying data transport. For example, the data channel's id may be outside the range negotiated by the [RFC8831] implementations in the SCTP handshake. When the user agent determines that an RTCDataChannel's underlying data transport cannot be created, the user agent MUST queue a task to run the following steps:

  1. Let channel be the RTCDataChannel object for which the user agent could not create an underlying data transport.

  2. Set channel.[[ReadyState]] to "closed".

  3. Fire an event named error using the RTCErrorEvent interface with the errorDetail attribute set to "data-channel-failure" at channel.

  4. Fire an event named close at channel.

6.2.8 Receiving messages on a data channel

When an RTCDataChannel message has been received via the underlying data transport with type type and data rawData, the user agent MUST queue a task to run the following steps:

  1. Let channel be the RTCDataChannel object for which the user agent has received a message.

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

  3. If channel.[[ReadyState]] is not "open", abort these steps and discard rawData.

  4. Execute the sub step by switching on type and channel.binaryType:

    • If type indicates that rawData is a string:

      Let data be a DOMString that represents the result of decoding rawData as UTF-8.

    • If type indicates that rawData is binary and binaryType is "blob":

      Let data be a new Blob object containing rawData as its raw data source.

    • If type indicates that rawData is binary and binaryType is "arraybuffer":

      Let data be a new ArrayBuffer object containing rawData as its raw data source.

  5. Fire an event named message using the MessageEvent interface with its origin attribute initialized to the serialization of an origin of connection.[[DocumentOrigin]], and the data attribute initialized to data at channel.

WebIDL[Exposed=(Window,DedicatedWorker), Transferable]
interface RTCDataChannel : EventTarget {
  readonly attribute USVString label;
  readonly attribute boolean ordered;
  readonly attribute unsigned short? maxPacketLifeTime;
  readonly attribute unsigned short? maxRetransmits;
  readonly attribute USVString protocol;
  readonly attribute boolean negotiated;
  readonly attribute unsigned short? id;
  readonly attribute RTCDataChannelState readyState;
  readonly attribute unsigned long bufferedAmount;
  [EnforceRange] attribute unsigned long bufferedAmountLowThreshold;
  attribute EventHandler onopen;
  attribute EventHandler onbufferedamountlow;
  attribute EventHandler onerror;
  attribute EventHandler onclosing;
  attribute EventHandler onclose;
  undefined close();
  attribute EventHandler onmessage;
  attribute BinaryType binaryType;
  undefined send(USVString data);
  undefined send(Blob data);
  undefined send(ArrayBuffer data);
  undefined send(ArrayBufferView data);
};

Attributes

label of type USVString, readonly

The label attribute represents a label that can be used to distinguish this RTCDataChannel object from other RTCDataChannel objects. Scripts are allowed to create multiple RTCDataChannel objects with the same label. On getting, the attribute MUST return the value of the [[DataChannelLabel]] slot.

ordered of type boolean, readonly

The ordered attribute returns true if the RTCDataChannel is ordered, and false if out of order delivery is allowed. On getting, the attribute MUST return the value of the [[Ordered]] slot.

maxPacketLifeTime of type unsigned short, readonly, nullable

The maxPacketLifeTime attribute returns the length of the time window (in milliseconds) during which transmissions and retransmissions may occur in unreliable mode. On getting, the attribute MUST return the value of the [[MaxPacketLifeTime]] slot.

maxRetransmits of type unsigned short, readonly, nullable

The maxRetransmits attribute returns the maximum number of retransmissions that are attempted in unreliable mode. On getting, the attribute MUST return the value of the [[MaxRetransmits]] slot.

protocol of type USVString, readonly

The protocol attribute returns the name of the sub-protocol used with this RTCDataChannel. On getting, the attribute MUST return the value of the [[DataChannelProtocol]] slot.

negotiated of type boolean, readonly

The negotiated attribute returns true if this RTCDataChannel was negotiated by the application, or false otherwise. On getting, the attribute MUST return the value of the [[Negotiated]] slot.

id of type unsigned short, readonly, nullable

The id attribute returns the ID for this RTCDataChannel. The value is initially null, which is what will be returned if the ID was not provided at channel creation time, and the DTLS role of the SCTP transport has not yet been negotiated. Otherwise, it will return the ID that was either selected by the script or generated by the user agent according to [RFC8832]. After the ID is set to a non-null value, it will not change. On getting, the attribute MUST return the value of the [[DataChannelId]] slot.

readyState of type RTCDataChannelState, readonly

The readyState attribute represents the state of the RTCDataChannel object. On getting, the attribute MUST return the value of the [[ReadyState]] slot.

bufferedAmount of type unsigned long, readonly

The bufferedAmount attribute MUST, on getting, return the value of the [[BufferedAmount]] slot. The attribute exposes the number of bytes of application data (UTF-8 text and binary data) that have been queued using send(). Even though the data transmission can occur in parallel, the returned value MUST NOT be decreased before the current task yielded back to the event loop to prevent race conditions. The value does not include framing overhead incurred by the protocol, or buffering done by the operating system or network hardware. The value of the [[BufferedAmount]] slot will only increase with each call to the send() method as long as the [[ReadyState]] slot is "open"; however, the slot does not reset to zero once the channel closes. When the underlying data transport sends data from its queue, the user agent MUST queue a task that reduces [[BufferedAmount]] with the number of bytes that was sent.

bufferedAmountLowThreshold of type unsigned long

The bufferedAmountLowThreshold attribute sets the threshold at which the bufferedAmount is considered to be low. When the bufferedAmount decreases from above this threshold to equal or below it, the bufferedamountlow event fires. The bufferedAmountLowThreshold is initially zero on each new RTCDataChannel, but the application may change its value at any time.

onopen of type EventHandler
The event type of this event handler is open.
onbufferedamountlow of type EventHandler
The event type of this event handler is bufferedamountlow.
onerror of type EventHandler

The event type of this event handler is RTCErrorEvent. errorDetail contains "sctp-failure", sctpCauseCode contains the SCTP Cause Code value, and message contains the SCTP Cause-Specific-Information, possibly with additional text.

onclosing of type EventHandler

The event type of this event handler is closing.

onclose of type EventHandler

The event type of this event handler is close.

onmessage of type EventHandler

The event type of this event handler is message.

binaryType of type BinaryType

The binaryType attribute returns the value to which it was last set. When an RTCDataChannel object is created, the binaryType attribute MUST be initialized to the string "arraybuffer".

This attribute controls how binary data is exposed to scripts. See Web Socket's binaryType.

Methods

close()

Closes the RTCDataChannel. It may be called regardless of whether the RTCDataChannel object was created by this peer or the remote peer.

When the close method is called, the user agent MUST run the following steps:

  1. Let channel be the RTCDataChannel object which is about to be closed.

  2. If channel.[[ReadyState]] is "closing" or "closed", then abort these steps.

  3. Set channel.[[ReadyState]] to "closing".

  4. If the closing procedure has not started yet, start it.

send

Run the steps described by the send() algorithm with argument type string object.

send

Run the steps described by the send() algorithm with argument type Blob object.

send

Run the steps described by the send() algorithm with argument type ArrayBuffer object.

send

Run the steps described by the send() algorithm with argument type ArrayBufferView object.

The send() method is overloaded to handle different data argument types. When any version of the method is called, the user agent MUST run the following steps:

  1. Let channel be the RTCDataChannel object on which data is to be sent.

  2. Set channel.[[IsTransferable]] to false.

  3. If channel.[[ReadyState]] is not "open", throw an InvalidStateError.

  4. Execute the sub step that corresponds to the type of the methods argument:

    • string object:

      Let data be a byte buffer that represents the result of encoding the method's argument as UTF-8.

    • Blob object:

      Let data be the raw data represented by the Blob object.

      Note
      Although the actual retrieval of data from a Blob object can happen asynchronously, the user agent will make sure to queue the data on the channel's underlying data transport in the same order as the send method is called. The byte size of data needs to be known synchronously.
    • ArrayBuffer object:

      Let data be the data stored in the buffer described by the ArrayBuffer object.

    • ArrayBufferView object:

      Let data be the data stored in the section of the buffer described by the ArrayBuffer object that the ArrayBufferView object references.

    Note
    Any data argument type this method has not been overloaded with will result in a TypeError. This includes null and undefined.
  5. If the byte size of data exceeds the value of maxMessageSize on channel's associated RTCSctpTransport, throw a TypeError.

  6. Queue data for transmission on channel's underlying data transport. If queuing data is not possible because not enough buffer space is available, throw an OperationError.

    Note
    The actual transmission of data occurs in parallel. If sending data leads to an SCTP-level error, the application will be notified asynchronously through onerror.
  7. Increase the value of the [[BufferedAmount]] slot by the byte size of data.

WebIDLdictionary RTCDataChannelInit {
  boolean ordered = true;
  [EnforceRange] unsigned short maxPacketLifeTime;
  [EnforceRange] unsigned short maxRetransmits;
  USVString protocol = "";
  boolean negotiated = false;
  [EnforceRange] unsigned short id;
};

Dictionary RTCDataChannelInit Members

ordered of type boolean, defaulting to true

If set to false, data is allowed to be delivered out of order. The default value of true, guarantees that data will be delivered in order.

maxPacketLifeTime of type unsigned short

Limits the time (in milliseconds) during which the channel will transmit or retransmit data if not acknowledged. This value may be clamped if it exceeds the maximum value supported by the user agent.

maxRetransmits of type unsigned short

Limits the number of times a channel will retransmit data if not successfully delivered. This value may be clamped if it exceeds the maximum value supported by the user agent.

protocol of type USVString, defaulting to ""

Subprotocol name used for this channel.

negotiated of type boolean, defaulting to false

The default value of false tells the user agent to announce the channel in-band and instruct the other peer to dispatch a corresponding RTCDataChannel object. If set to true, it is up to the application to negotiate the channel and create an RTCDataChannel object with the same id at the other peer.

Note
If set to true, the application must also take care to not send a message until the other peer has created a data channel to receive it. Receiving a message on an SCTP stream with no associated data channel is undefined behavior, and it may be silently dropped. This will not be possible as long as both endpoints create their data channel before the first offer/answer exchange is complete.
id of type unsigned short

Sets the channel ID when negotiated is true. Ignored when negotiated is false.

WebIDLenum RTCDataChannelState {
  "connecting",
  "open",
  "closing",
  "closed"
};
RTCDataChannelState Enumeration description
Enum value Description
connecting

The user agent is attempting to establish the underlying data transport. This is the initial state of an RTCDataChannel object, whether created with createDataChannel, or dispatched as a part of an RTCDataChannelEvent.

open

The underlying data transport is established and communication is possible.

closing

The procedure to close down the underlying data transport has started.

closed

The underlying data transport has been closed or could not be established.

6.3 RTCDataChannelEvent

The datachannel event uses the RTCDataChannelEvent interface.

WebIDL[Exposed=Window]
interface RTCDataChannelEvent : Event {
  constructor(DOMString type, RTCDataChannelEventInit eventInitDict);
  readonly attribute RTCDataChannel channel;
};

Constructors

RTCDataChannelEvent.constructor()

Attributes

channel of type RTCDataChannel, readonly

The channel attribute represents the RTCDataChannel object associated with the event.

WebIDLdictionary RTCDataChannelEventInit : EventInit {
  required RTCDataChannel channel;
};

Dictionary RTCDataChannelEventInit Members

channel of type RTCDataChannel, required

The RTCDataChannel object to be announced by the event.

6.4 Garbage Collection

An RTCDataChannel object MUST not be garbage collected if its

7. Peer-to-peer DTMF

This section describes an interface on RTCRtpSender to send DTMF (phone keypad) values across an RTCPeerConnection. Details of how DTMF is sent to the other peer are described in [RFC7874].

7.1 RTCRtpSender Interface Extensions

The Peer-to-peer DTMF API extends the RTCRtpSender interface as described below.

WebIDL          partial interface RTCRtpSender {
  readonly attribute RTCDTMFSender? dtmf;
};

Attributes

dtmf of type RTCDTMFSender, readonly, nullable

On getting, the dtmf attribute returns the value of the [[Dtmf]] internal slot, which represents a RTCDTMFSender which can be used to send DTMF, or null if unset. The [[Dtmf]] internal slot is set when the kind of an RTCRtpSender's [[SenderTrack]] is "audio".

7.2 RTCDTMFSender

To create an RTCDTMFSender, the user agent MUST run the following steps:

  1. Let dtmf be a newly created RTCDTMFSender object.

  2. Let dtmf have a [[Duration]] internal slot.

  3. Let dtmf have a [[InterToneGap]] internal slot.

  4. Let dtmf have a [[ToneBuffer]] internal slot.

WebIDL[Exposed=Window]
interface RTCDTMFSender : EventTarget {
  undefined insertDTMF(DOMString tones, optional unsigned long duration = 100, optional unsigned long interToneGap = 70);
  attribute EventHandler ontonechange;
  readonly attribute boolean canInsertDTMF;
  readonly attribute DOMString toneBuffer;
};

Attributes

ontonechange of type EventHandler

The event type of this event handler is tonechange.

canInsertDTMF of type boolean, readonly

Whether the RTCDTMFSender dtmfSender is capable of sending DTMF. On getting, the user agent MUST return the result of running determine if DTMF can be sent for dtmfSender.

toneBuffer of type DOMString, readonly

The toneBuffer attribute MUST return a list of the tones remaining to be played out. For the syntax, content, and interpretation of this list, see insertDTMF.

Methods

insertDTMF

An RTCDTMFSender object's insertDTMF method is used to send DTMF tones.

The tones parameter is treated as a series of characters. The characters 0 through 9, A through D, #, and * generate the associated DTMF tones. The characters a to d MUST be normalized to uppercase on entry and are equivalent to A to D. As noted in [RTCWEB-AUDIO] Section 3, support for the characters 0 through 9, A through D, #, and * are required. The character ',' MUST be supported, and indicates a delay of 2 seconds before processing the next character in the tones parameter. All other characters (and only those other characters) MUST be considered unrecognized.

The duration parameter indicates the duration in ms to use for each character passed in the tones parameters. The duration cannot be more than 6000 ms or less than 40 ms. The default duration is 100 ms for each tone.

The interToneGap parameter indicates the gap between tones in ms. The user agent clamps it to at least 30 ms and at most 6000 ms. The default value is 70 ms.

The browser MAY increase the duration and interToneGap times to cause the times that DTMF start and stop to align with the boundaries of RTP packets but it MUST not increase either of them by more than the duration of a single RTP audio packet.

When the insertDTMF() method is invoked, the user agent MUST run the following steps:

  1. Let sender be the RTCRtpSender used to send DTMF.
  2. Let transceiver be the RTCRtpTransceiver object associated with sender.

  3. Let dtmf be the RTCDTMFSender associated with sender.
  4. If determine if DTMF can be sent for dtmf returns false, throw an InvalidStateError.
  5. Let tones be the method's first argument.
  6. Let duration be the method's second argument.
  7. Let interToneGap be the method's third argument.
  8. If tones contains any unrecognized characters, throw an InvalidCharacterError.
  9. Set the object's [[ToneBuffer]] slot to tones.
  10. Set dtmf.[[Duration]] to the value of duration.
  11. Set dtmf.[[InterToneGap]] to the value of interToneGap.
  12. If the value of duration is less than 40 ms, set dtmf.[[Duration]] to 40 ms.
  13. If the value of duration parameter is greater than 6000 ms, set dtmf.[[Duration]] to 6000 ms.
  14. If the value of interToneGap is less than 30 ms, set dtmf.[[InterToneGap]] to 30 ms.
  15. If the value of interToneGap is greater than 6000 ms, set dtmf.[[InterToneGap]] to 6000 ms.
  16. If [[ToneBuffer]] slot is an empty string, abort these steps.
  17. If a task to run the DTMF playout task steps is scheduled to be run, abort these steps; otherwise queue a task that runs the following DTMF playout task steps:
    1. If transceiver.[[CurrentDirection]]If determine if DTMF can be sent is neither "sendrecv" nor "sendonly"for dtmf returns false, abort these steps.
    2. If the [[ToneBuffer]] slot contains the empty string, fire an event named tonechange using the RTCDTMFToneChangeEvent interface with the tone attribute set to an empty string at the RTCDTMFSender object and abort these steps.
    3. Remove the first character from the [[ToneBuffer]] slot and let that character be tone.
    4. If tone is "," delay sending tones for 2000 ms on the associated RTP media stream, and queue a task to be executed in 2000 ms from now that runs the DTMF playout task steps.
    5. If tone is not "," start playout of tone for [[Duration]] ms on the associated RTP media stream, using the appropriate codec, then queue a task to be executed in [[Duration]] + [[InterToneGap]] ms from now that runs the DTMF playout task steps.
    6. Fire an event named tonechange using the RTCDTMFToneChangeEvent interface with the tone attribute set to tone at the RTCDTMFSender object.

Since insertDTMF replaces the tone buffer, in order to add to the DTMF tones being played, it is necessary to call insertDTMF with a string containing both the remaining tones (stored in the [[ToneBuffer]] slot) and the new tones appended together. Calling insertDTMF with an empty tones parameter can be used to cancel all tones queued to play after the currently playing tone.

7.3 canInsertDTMF algorithm

To determine if DTMF can be sent for an RTCDTMFSender instance dtmfSender, the user agent MUST run the following steps:

  1. Let sender be the RTCRtpSender associated with dtmfSender.
  2. Let transceiver be the RTCRtpTransceiver associated with sender.
  3. Let connection be the RTCPeerConnection associated with transceiver.
  4. If connection's RTCPeerConnectionState is not "connected" return false.
  5. If transceiver.[[Stopping]] is true return false.
  6. If sender.[[SenderTrack]] is null return false.
  7. If transceiver.[[CurrentDirection]] is neither "sendrecv" nor "sendonly" return false.
  8. If sender.[[SendEncodings]][0].active is false return false.
  9. If no codec with mimetype "audio/telephone-event" has been negotiated for sending with this sender, return false.
  10. Otherwise, return true.

7.4 RTCDTMFToneChangeEvent

The tonechange event uses the RTCDTMFToneChangeEvent interface.

WebIDL[Exposed=Window]
interface RTCDTMFToneChangeEvent : Event {
  constructor(DOMString type, optional RTCDTMFToneChangeEventInit eventInitDict = {});
  readonly attribute DOMString tone;
};

Constructors

RTCDTMFToneChangeEvent.constructor()

Attributes

tone of type DOMString, readonly

The tone attribute contains the character for the tone (including ",") that has just begun playout (see insertDTMF ). If the value is the empty string, it indicates that the [[ToneBuffer]] slot is an empty string and that the previous tones have completed playback.

WebIDL          dictionary RTCDTMFToneChangeEventInit : EventInit {
  DOMString tone = "";
};

Dictionary RTCDTMFToneChangeEventInit Members

tone of type DOMString, defaulting to ""

The tone attribute contains the character for the tone (including ",") that has just begun playout (see insertDTMF ). If the value is the empty string, it indicates that the [[ToneBuffer]] slot is an empty string and that the previous tones have completed playback.

8. Statistics Model

8.1 Introduction

The basic statistics model is that the browser maintains a set of statistics for monitored objects, in the form of stats objects.

A group of related objects may be referenced by a selector. The selector may, for example, be a MediaStreamTrack. For a track to be a valid selector, it MUST be a MediaStreamTrack that is sent or received by the RTCPeerConnection object on which the stats request was issued. The calling Web application provides the selector to the getStats() method and the browser emits (in the JavaScript) a set of statistics that are relevant to the selector, according to the stats selection algorithm. Note that that algorithm takes the sender or receiver of a selector.

The statistics returned in stats objects are designed in such a way that repeated queries can be linked by the RTCStats id dictionary member. Thus, a Web application can make measurements over a given time period by requesting measurements at the beginning and end of that period.

With a few exceptions, monitored objects, once created, exist for the duration of their associated RTCPeerConnection. This ensures statistics from them are available in the result from getStats() even past the associated peer connection being closed.

Only a few monitored objects have shorter lifetimes. Statistics from these objects are no longer available in subsequent getStats() results. The object descriptions in [WEBRTC-STATS] describe when these monitored objects are deleted.

8.2 RTCPeerConnection Interface Extensions

The Statistics API extends the RTCPeerConnection interface as described below.

WebIDL          partial interface RTCPeerConnection {
  Promise<RTCStatsReport> getStats(optional MediaStreamTrack? selector = null);
};

Methods

getStats

Gathers stats for the given selector and reports the result asynchronously.

When the getStats() method is invoked, the user agent MUST run the following steps:

  1. Let selectorArg be the method's first argument.

  2. Let connection be the RTCPeerConnection object on which the method was invoked.

  3. If selectorArg is null, let selector be null.

  4. If selectorArg is a MediaStreamTrack let selector be an RTCRtpSender or RTCRtpReceiver on connection which track attribute matches selectorArg. If no such sender or receiver exists, or if more than one sender or receiver fit this criteria, return a promise rejected with a newly created InvalidAccessError.

  5. Let p be a new promise.

  6. Run the following steps in parallel:

    1. Gather the stats indicated by selector according to the stats selection algorithm.

    2. Queue a global task on the networking task source given the current realm's global object as global to resolve p with the resulting RTCStatsReport object, containing the gathered stats.

  7. Return p.

8.3 RTCStatsReport Object

The getStats() method delivers a successful result in the form of an RTCStatsReport object. An RTCStatsReport object is a map between strings that identify the inspected objects (id attribute in RTCStats instances), and their corresponding RTCStats-derived dictionaries.

An RTCStatsReport may be composed of several RTCStats-derived dictionaries, each reporting stats for one underlying object that the implementation thinks is relevant for the selector. One achieves the total for the selector by summing over all the stats of a certain type; for instance, if an RTCRtpSender uses multiple SSRCs to carry its track over the network, the RTCStatsReport may contain one RTCStats-derived dictionary per SSRC (which can be distinguished by the value of the ssrc stats attribute).

WebIDL[Exposed=Window]
interface RTCStatsReport {
  readonly maplike<DOMString, object>;
};

Use these to retrieve the various dictionaries descended from RTCStats that this stats report is composed of. The set of supported property names [WEBIDL] is defined as the ids of all the RTCStats-derived dictionaries that have been generated for this stats report.

8.4 RTCStats Dictionary

An RTCStats dictionary represents the stats object constructed by inspecting a specific monitored object. The RTCStats dictionary is a base type that specifies as set of default attributes, such as timestamp and type. Specific stats are added by extending the RTCStats dictionary.

Note that while stats names are standardized, any given implementation may be using experimental values or values not yet known to the Web application. Thus, applications MUST be prepared to deal with unknown stats.

Statistics need to be synchronized with each other in order to yield reasonable values in computation; for instance, if bytesSent and packetsSent are both reported, they both need to be reported over the same interval, so that "average packet size" can be computed as "bytes / packets" - if the intervals are different, this will yield errors. Thus implementations MUST return synchronized values for all stats in an RTCStats-derived dictionary.

WebIDLdictionary RTCStats {
  required DOMHighResTimeStamp timestamp;
  required RTCStatsType type;
  required DOMString id;
};

Dictionary RTCStats Members

timestamp of type DOMHighResTimeStamp
Candidate Correction 50:Use Performance.timeOrigin + Performance.now() for stats timestamps (PR #3005)

The timestamp, of type Timestamps are expressed with DOMHighResTimeStamp, associated with this object. The time is relative to the UNIX epoch (Jan 1[HIGHRES-TIME], 1970,and are defined as Performance.timeOrigin UTC)+ Performance.now() at the time the information is collected. For statistics that came from a remote source (e.g., from received RTCP packets), timestamp represents the time at which the information arrived at the local endpoint. The remote timestamp can be found in an additional field in an RTCStats-derived dictionary, if applicable.

type of type RTCStatsType

The type of this object.

The type attribute MUST be initialized to the name of the most specific type this RTCStats dictionary represents.

id of type DOMString

A unique id that is associated with the object that was inspected to produce this RTCStats object. Two RTCStats objects, extracted from two different RTCStatsReport objects, MUST have the same id if they were produced by inspecting the same underlying object.

Stats ids MUST NOT be predictable by an application. This prevents applications from depending on a particular user agent's way of generating ids, since this prevents an application from getting stats objects by their id unless they have already read the id of that specific stats object.

User agents are free to pick any format for the id as long as it meets the requirements above.

Note

A user agent can turn a predictably generated string into an unpredictable string using a hash function, as long as it uses a salt that is unique to the peer connection. This allows an implementation to have predictable ids internally, which may make it easier to guarantee that stats objects have stable ids across getStats() calls.

The set of valid values for RTCStatsType, and the dictionaries derived from RTCStats that they indicate, are documented in [WEBRTC-STATS].

8.5 The stats selection algorithm

The stats selection algorithm is as follows:

  1. Let result be an empty RTCStatsReport.
  2. If selector is null, gather stats for the whole connection, add them to result, return result, and abort these steps.
  3. If selector is an RTCRtpSender, gather stats for and add the following objects to result:
  4. If selector is an RTCRtpReceiver, gather stats for and add the following objects to result:
  5. Return result.

8.6 Mandatory To Implement Stats

The stats listed in [WEBRTC-STATS] are intended to cover a wide range of use cases. Not all of them have to be implemented by every WebRTC implementation.

An implementation MUST support generating statistics of the following types when the corresponding objects exist on a RTCPeerConnection, with the fields that are listed when they are valid for that object in addition to the generic fields defined in the RTCStats dictionary:

RTCStatsType Dictionary Fields
"codec" RTCCodecStats payloadType, mimeType, clockRate, channels, sdpFmtpLine
"inbound-rtp" RTCRtpStreamStats ssrc, kind, transportId, codecId
RTCReceivedRtpStreamStats packetsReceived, packetsLost, jitter,
RTCInboundRtpStreamStats trackIdentifier, remoteId, framesDecoded, framesDropped nackCount, framesReceived, bytesReceived, totalAudioEnergy, totalSamplesDuration packetsDiscarded,
"outbound-rtp" RTCRtpStreamStats ssrc, kind, transportId, codecId
RTCSentRtpStreamStats packetsSent, bytesSent
RTCOutboundRtpStreamStats remoteId, framesEncoded, nackCount, framesSent
"remote-inbound-rtp" RTCRtpStreamStats ssrc, kind, transportId, codecId
RTCReceivedRtpStreamStats packetsReceived, packetsLost, jitter
RTCRemoteInboundRtpStreamStats localId, roundTripTime
"remote-outbound-rtp" RTCRtpStreamStats ssrc, kind, transportId, codecId
RTCSentRtpStreamStats packetsSent, bytesSent
RTCRemoteOutboundRtpStreamStats localId, remoteTimestamp
"media-source" RTCMediaSourceStats trackIdentifier, kind
RTCAudioSourceStats totalAudioEnergy, totalSamplesDuration (for audio tracks attached to senders)
RTCVideoSourceStats width, height, framesPerSecond (for video tracks attached to senders)
"peer-connection" RTCPeerConnectionStats dataChannelsOpened, dataChannelsClosed
"data-channel" RTCDataChannelStats label , protocol, dataChannelIdentifier, state, messagesSent, bytesSent, messagesReceived, bytesReceived
"transport" RTCTransportStats bytesSent, bytesReceived, selectedCandidatePairId, localCertificateId, remoteCertificateId
"candidate-pair" RTCIceCandidatePairStats transportId, localCandidateId, remoteCandidateId, state, nominated, bytesSent, bytesReceived, totalRoundTripTime, responsesReceived, currentRoundTripTime
"local-candidate" RTCIceCandidateStats address, port, protocol, candidateType, url
"remote-candidate"
"certificate" RTCCertificateStats fingerprint, fingerprintAlgorithm, base64Certificate, issuerCertificateId

An implementation MAY support generating any other statistic defined in [WEBRTC-STATS], and MAY generate statistics that are not documented.

8.7 GetStats Example

Consider the case where the user is experiencing bad sound and the application wants to determine if the cause of it is packet loss. The following example code might be used:

async function gatherStats(pc) {
  try {
    const [sender] = pc.getSenders();
    const baselineReport = await sender.getStats();
    await new Promise(resolve => setTimeout(resolve, aBit)); // wait a bit
    const currentReport = await sender.getStats();

    // compare the elements from the current report with the baseline
    for (const now of currentReport.values()) {
      if (now.type != 'outbound-rtp') continue;

      // get the corresponding stats from the baseline report
      const base = baselineReport.get(now.id);
      if (!base) continue;

      const remoteNow = currentReport.get(now.remoteId);
      const remoteBase = baselineReport.get(base.remoteId);

      const packetsSent = now.packetsSent - base.packetsSent;
      const packetsReceived = remoteNow.packetsReceived -
                              remoteBase.packetsReceived;

      const fractionLost = (packetsSent - packetsReceived) / packetsSent;
      if (fractionLost > 0.3) {
        // if fractionLost is > 0.3, we have probably found the culprit
      }
    }
  } catch (err) {
    console.error(err);
  }
}

9. Media Stream API Extensions for Network Use

9.1 Introduction

The MediaStreamTrack interface, as defined in the [GETUSERMEDIA] specification, typically represents a stream of data of audio or video. One or more MediaStreamTracks can be collected in a MediaStream (strictly speaking, a MediaStream as defined in [GETUSERMEDIA] may contain zero or more MediaStreamTrack objects).

A MediaStreamTrack may be extended to represent a media flow that either comes from or is sent to a remote peer (and not just the local camera, for instance). The extensions required to enable this capability on the MediaStreamTrack object will be described in this section. How the media is transmitted to the peer is described in [RFC8834], [RFC7874], and [RFC8835].

A MediaStreamTrack sent to another peer will appear as one and only one MediaStreamTrack to the recipient. A peer is defined as a user agent that supports this specification. In addition, the sending side application can indicate what MediaStream object(s) the MediaStreamTrack is a member of. The corresponding MediaStream object(s) on the receiver side will be created (if not already present) and populated accordingly.

As also described earlier in this document, the objects RTCRtpSender and RTCRtpReceiver can be used by the application to get more fine grained control over the transmission and reception of MediaStreamTracks.

Channels are the smallest unit considered in the Media Capture and Streams specification. Channels are intended to be encoded together for transmission as, for instance, an RTP payload type. All of the channels that a codec needs to encode jointly MUST be in the same MediaStreamTrack and the codecs SHOULD be able to encode, or discard, all the channels in the track.

The concepts of an input and output to a given MediaStreamTrack apply in the case of MediaStreamTrack objects transmitted over the network as well. A MediaStreamTrack created by an RTCPeerConnection object (as described previously in this document) will take as input the data received from a remote peer. Similarly, a MediaStreamTrack from a local source, for instance a camera via [GETUSERMEDIA], will have an output that represents what is transmitted to a remote peer if the object is used with an RTCPeerConnection object.

The concept of duplicating MediaStream and MediaStreamTrack objects as described in [GETUSERMEDIA] is also applicable here. This feature can be used, for instance, in a video-conferencing scenario to display the local video from the user's camera and microphone in a local monitor, while only transmitting the audio to the remote peer (e.g. in response to the user using a "video mute" feature). Combining different MediaStreamTrack objects into new MediaStream objects is useful in certain situations.

Note

In this document, we only specify aspects of the following objects that are relevant when used along with an RTCPeerConnection. Please refer to the original definitions of the objects in the [GETUSERMEDIA] document for general information on using MediaStream and MediaStreamTrack.

9.2 MediaStream

9.2.1 id

The id attribute specified in MediaStream returns an id that is unique to this stream, so that streams can be recognized at the remote end of the RTCPeerConnection API.

When a MediaStream is created to represent a stream obtained from a remote peer, the id attribute is initialized from information provided by the remote source.

Note

The id of a MediaStream object is unique to the source of the stream, but that does not mean it is not possible to end up with duplicates. For example, the tracks of a locally generated stream could be sent from one user agent to a remote peer using RTCPeerConnection and then sent back to the original user agent in the same manner, in which case the original user agent will have multiple streams with the same id (the locally-generated one and the one received from the remote peer).

9.3 MediaStreamTrack

A MediaStreamTrack object's reference to its MediaStream in the non-local media source case (an RTP source, as is the case for each MediaStreamTrack associated with an RTCRtpReceiver) is always strong.

Whenever an RTCRtpReceiver receives data on an RTP source whose corresponding MediaStreamTrack is muted, but not ended, and the [[Receptive]] slot of the RTCRtpTransceiver object the RTCRtpReceiver is a member of is true, it MUST queue a task to set the muted state of the corresponding MediaStreamTrack to false.

When one of the SSRCs for RTP source media streams received by an RTCRtpReceiver is removed either due to reception of a BYE or via timeout, it MUST queue a task to set the muted state of the corresponding MediaStreamTrack to true. Note that setRemoteDescription can also lead to the setting of the muted state of the track to the value true.

The procedures add a track, remove a track and set a track's muted state are specified in [GETUSERMEDIA].

When a MediaStreamTrack track produced by an RTCRtpReceiver receiver has ended [GETUSERMEDIA] (such as via a call to receiver.track.stop), the user agent MAY choose to free resources allocated for the incoming stream, by for instance turning off the decoder of receiver.

9.3.1 MediaTrackSupportedConstraints, MediaTrackCapabilities, MediaTrackConstraints and MediaTrackSettings

The concept of constraints and constrainable properties, including MediaTrackConstraints (MediaStreamTrack.getConstraints(), MediaStreamTrack.applyConstraints()), and MediaTrackSettings (MediaStreamTrack.getSettings()) are outlined in [GETUSERMEDIA]. However, the constrainable properties of tracks sourced from a peer connection are different than those sourced by getUserMedia(); the constraints and settings applicable to MediaStreamTracks sourced from a remote source are defined here. The settings of a remote track represent the latest frame received.

MediaStreamTrack.getCapabilities() MUST always return the empty set and MediaStreamTrack.applyConstraints() MUST always reject with OverconstrainedError on remote tracks for constraints defined here.

The following constrainable properties are defined to apply to video MediaStreamTracks sourced from a remote source:

Property Name Values Notes
width ConstrainULong As a setting, this is the width, in pixels, of the latest frame received.
height ConstrainULong As a setting, this is the height, in pixels, of the latest frame received.
frameRate ConstrainDouble As a setting, this is an estimate of the frame rate based on recently received frames.
aspectRatio ConstrainDouble As a setting, this is the aspect ratio of the latest frame; this is the width in pixels divided by height in pixels as a double rounded to the tenth decimal place.

This document does not define any constrainable properties to apply to audio MediaStreamTracks sourced from a remote source.

10. Examples and Call Flows

This section is non-normative.

10.1 Simple Peer-to-peer Example

When two peers decide they are going to set up a connection to each other, they both go through these steps. The STUN/TURN server configuration describes a server they can use to get things like their public IP address or to set up NAT traversal. They also have to send data for the signaling channel to each other using the same out-of-band mechanism they used to establish that they were going to communicate in the first place.

const signaling = new SignalingChannel(); // handles JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// send any ice candidates to the other peer
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// let the "negotiationneeded" event trigger offer generation
pc.onnegotiationneeded = async () => {
  try {
    await pc.setLocalDescription();
    // send the offer to the other peer
    signaling.send({description: pc.localDescription});
  } catch (err) {
    console.error(err);
  }
};

pc.ontrack = ({track, streams}) => {
  // once media for a remote track arrives, show it in the remote video element
  track.onunmute = () => {
    // don't set srcObject again if it is already set.
    if (remoteView.srcObject) return;
    remoteView.srcObject = streams[0];
  };
};

// call start() to initiate
function start() {
  addCameraMic();
}

// add camera and microphone to connection
async function addCameraMic() {
  try {
    // get a local stream, show it in a self-view and add it to be sent
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    for (const track of stream.getTracks()) {
      pc.addTrack(track, stream);
    }
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({data: {description, candidate}}) => {
  try {
    if (description) {
      await pc.setRemoteDescription(description);
      // if we got an offer, we need to reply with an answer
      if (description.type == 'offer') {
        if (!selfView.srcObject) {
          // blocks negotiation on permission (not recommended in production code)
          await addCameraMic();
        }
        await pc.setLocalDescription();
        signaling.send({description: pc.localDescription});
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

10.2 Advanced Peer-to-peer Example with Warm-up

When two peers decide they are going to set up a connection to each other and want to have the ICE, DTLS, and media connections "warmed up" such that they are ready to send and receive media immediately, they both go through these steps.

const signaling = new SignalingChannel(); // handles JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
let pc;
let audio;
let video;
let started = false;

// Call warmup() before media is ready, to warm-up ICE, DTLS, and media.
async function warmup(isAnswerer) {
  pc = new RTCPeerConnection(configuration);
  if (!isAnswerer) {
    audio = pc.addTransceiver('audio');
    video = pc.addTransceiver('video');
  }

  // send any ice candidates to the other peer
  pc.onicecandidate = ({candidate}) => signaling.send({candidate});

  // let the "negotiationneeded" event trigger offer generation
  pc.onnegotiationneeded = async () => {
    try {
      await pc.setLocalDescription();
      // send the offer to the other peer
      signaling.send({description: pc.localDescription});
    } catch (err) {
      console.error(err);
    }
  };

  pc.ontrack = async ({track, transceiver}) => {
    try {
      // once media for the remote track arrives, show it in the video element
      event.track.onunmute = () => {
        // don't set srcObject again if it is already set.
        if (!remoteView.srcObject) {
          remoteView.srcObject = new MediaStream();
        }
        remoteView.srcObject.addTrack(track);
      }

      if (isAnswerer) {
        if (track.kind == 'audio') {
          audio = transceiver;
        } else if (track.kind == 'video') {
          video = transceiver;
        }
        if (started) await addCameraMicWarmedUp();
      }
    } catch (err) {
      console.error(err);
    }
  };

  try {
    // get a local stream, show it in a self-view and add it to be sent
    selfView.srcObject = await navigator.mediaDevices.getUserMedia(constraints);
    if (started) await addCameraMicWarmedUp();
  } catch (err) {
    console.error(err);
  }
}

// call start() after warmup() to begin transmitting media from both ends
function start() {
  signaling.send({start: true});
  signaling.onmessage({data: {start: true}});
}

// add camera and microphone to already warmed-up connection
async function addCameraMicWarmedUp() {
  const stream = selfView.srcObject;
  if (audio && video && stream) {
    await Promise.all([
      audio.sender.replaceTrack(stream.getAudioTracks()[0]),
      video.sender.replaceTrack(stream.getVideoTracks()[0]),
    ]);
  }
}

signaling.onmessage = async ({data: {start, description, candidate}}) => {
  if (!pc) warmup(true);

  try {
    if (start) {
      started = true;
      await addCameraMicWarmedUp();
    } else if (description) {
      await pc.setRemoteDescription(description);
      // if we got an offer, we need to reply with an answer
      if (description.type == 'offer') {
        await pc.setLocalDescription();
        signaling.send({description: pc.localDescription});
      }
    } else {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

10.3 Simulcast Example

A client wants to send multiple RTP encodings (simulcast) to a server.

const signaling = new SignalingChannel(); // handles JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {'iceServers': [{'urls': 'stun:stun.example.org'}]};
let pc;

// call start() to initiate
async function start() {
  pc = new RTCPeerConnection(configuration);

  // let the "negotiationneeded" event trigger offer generation
  pc.onnegotiationneeded = async () => {
    try {
      await pc.setLocalDescription();
      // send the offer to the other peer
      signaling.send({description: pc.localDescription});
    } catch (err) {
      console.error(err);
    }
  };

  try {
    // get a local stream, show it in a self-view and add it to be sent
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    selfView.srcObject = stream;
    pc.addTransceiver(stream.getAudioTracks()[0], {direction: 'sendonly'});
    pc.addTransceiver(stream.getVideoTracks()[0], {
      direction: 'sendonly',
      sendEncodings: [
        {rid: 'q', scaleResolutionDownBy: 4.0}
        {rid: 'h', scaleResolutionDownBy: 2.0},
        {rid: 'f'},
      ]
    });
  } catch (err) {
    console.error(err);
  }
}

signaling.onmessage = async ({data: {description, candidate}}) => {
  try {
    if (description) {
      await pc.setRemoteDescription(description);
      // if we got an offer, we need to reply with an answer
      if (description.type == 'offer') {
        await pc.setLocalDescription();
        signaling.send({description: pc.localDescription});
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

10.4 Peer-to-peer Data Example

This example shows how to create an RTCDataChannel object and perform the offer/answer exchange required to connect the channel to the other peer. The RTCDataChannel is used in the context of a simple chat application using an input field for user input.

const signaling = new SignalingChannel(); // handles JSON.stringify/parse
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
let pc, channel;

// call start() to initiate
function start() {
  pc = new RTCPeerConnection(configuration);

  // send any ice candidates to the other peer
  pc.onicecandidate = ({candidate}) => signaling.send({candidate});

  // let the "negotiationneeded" event trigger offer generation
  pc.onnegotiationneeded = async () => {
    try {
      await pc.setLocalDescription();
      // send the offer to the other peer
      signaling.send({description: pc.localDescription});
    } catch (err) {
      console.error(err);
    }
  };

  // create data channel and setup chat using "negotiated" pattern
  channel = pc.createDataChannel('chat', {negotiated: true, id: 0});
  channel.onopen = () => input.disabled = false;
  channel.onmessage = ({data}) => showChatMessage(data);

  input.onkeydown = ({key}) => {
    if (key != 'Enter') return;
    channel.send(input.value);
  }
}

signaling.onmessage = async ({data: {description, candidate}}) => {
  if (!pc) start();

  try {
    if (description) {
      await pc.setRemoteDescription(description);
      // if we got an offer, we need to reply with an answer
      if (description.type == 'offer') {
        await pc.setLocalDescription();
        signaling.send({description: pc.localDescription});
      }
    } else if (candidate) {
      await pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
};

10.5 Call Flow Browser to Browser

This shows an example of one possible call flow between two browsers. This does not show the procedure to get access to local media or every callback that gets fired but instead tries to reduce it down to only show the key events and messages.

A message sequence chart detailing a call flow between two browsers

10.6 DTMF Example

Examples assume that sender is an RTCRtpSender.

Sending the DTMF signal "1234" with 500 ms duration per tone:

if (sender.dtmf.canInsertDTMF) {
  const duration = 500;
  sender.dtmf.insertDTMF('1234', duration);
} else {
  console.log('DTMF function not available');
}

Send the DTMF signal "123" and abort after sending "2".

async function sendDTMF() {
  if (sender.dtmf.canInsertDTMF) {
    sender.dtmf.insertDTMF('123');
    await new Promise(r => sender.dtmf.ontonechange = e => e.tone == '2' && r());
    // empty the buffer to not play any tone after "2"
    sender.dtmf.insertDTMF('');
  } else {
    console.log('DTMF function not available');
  }
}

Send the DTMF signal "1234", and light up the active key using lightKey(key) while the tone is playing (assuming that lightKey("") will darken all the keys):

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

if (sender.dtmf.canInsertDTMF) {
  const duration = 500; // ms
  sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '1234', duration);
  sender.dtmf.ontonechange = async ({tone}) => {
    if (!tone) return;
    lightKey(tone); // light up the key when playout starts
    await wait(duration);
    lightKey(''); // turn off the light after tone duration
  };
} else {
  console.log('DTMF function not available');
}

It is always safe to append to the tone buffer. This example appends before any tone playout has started as well as during playout.

if (sender.dtmf.canInsertDTMF) {
  sender.dtmf.insertDTMF('123');
  // append more tones to the tone buffer before playout has begun
  sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '456');

  sender.dtmf.ontonechange = ({tone}) => {
    // append more tones when playout has begun
    if (tone != '1') return;
    sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '789');
  };
} else {
  console.log('DTMF function not available');
}

Send a 1-second "1" tone followed by a 2-second "2" tone:

if (sender.dtmf.canInsertDTMF) {
  sender.dtmf.ontonechange = ({tone}) => {
    if (tone == '1') {
      sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '2', 2000);
    }
  };
  sender.dtmf.insertDTMF(sender.dtmf.toneBuffer + '1', 1000);
} else {
  console.log('DTMF function not available');
}

10.7 Perfect Negotiation Example

Perfect negotiation is a recommended pattern to manage negotiation transparently, abstracting this asymmetric task away from the rest of an application. This pattern has advantages over one side always being the offerer, as it lets applications operate on both peer connection objects simultaneously without risk of glare (an offer coming in outside of "stable" state). The rest of the application may use any and all modification methods and attributes, without worrying about signaling state races.

It designates different roles to the two peers, with behavior to resolve signaling collisions between them:

  1. The polite peer uses rollback to avoid collision with an incoming offer.

  2. The impolite peer ignores an incoming offer when this would collide with its own.

Together, they manage signaling for the rest of the application in a manner that doesn't deadlock. The example assumes a polite boolean variable indicating the designated role:

const signaling = new SignalingChannel(); // handles JSON.stringify/parse
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);

// call start() anytime on either end to add camera and microphone to connection
async function start() {
  try {
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    for (const track of stream.getTracks()) {
      pc.addTrack(track, stream);
    }
    selfView.srcObject = stream;
  } catch (err) {
    console.error(err);
  }
}

pc.ontrack = ({track, streams}) => {
  // once media for a remote track arrives, show it in the remote video element
  track.onunmute = () => {
    // don't set srcObject again if it is already set.
    if (remoteView.srcObject) return;
    remoteView.srcObject = streams[0];
  };
};

// - The perfect negotiation logic, separated from the rest of the application ---

// keep track of some negotiation state to prevent races and errors
let makingOffer = false;
let ignoreOffer = false;
let isSettingRemoteAnswerPending = false;

// send any ice candidates to the other peer
pc.onicecandidate = ({candidate}) => signaling.send({candidate});

// let the "negotiationneeded" event trigger offer generation
pc.onnegotiationneeded = async () => {
  try {
    makingOffer = true;
    await pc.setLocalDescription();
    signaling.send({description: pc.localDescription});
  } catch (err) {
     console.error(err);
  } finally {
    makingOffer = false;
  }
};

signaling.onmessage = async ({data: {description, candidate}}) => {
  try {
    if (description) {
      // An offer may come in while we are busy processing SRD(answer).
      // In this case, we will be in "stable" by the time the offer is processed
      // so it is safe to chain it on our Operations Chain now.
      const readyForOffer =
          !makingOffer &&
          (pc.signalingState == "stable" || isSettingRemoteAnswerPending);
      const offerCollision = description.type == "offer" && !readyForOffer;

      ignoreOffer = !polite && offerCollision;
      if (ignoreOffer) {
        return;
      }
      isSettingRemoteAnswerPending = description.type == "answer";
      await pc.setRemoteDescription(description); // SRD rolls back as needed
      isSettingRemoteAnswerPending = false;
      if (description.type == "offer") {
        await pc.setLocalDescription();
        signaling.send({description: pc.localDescription});
      }
    } else if (candidate) {
      try {
        await pc.addIceCandidate(candidate);
      } catch (err) {
        if (!ignoreOffer) throw err; // Suppress ignored offer's candidates
      }
    }
  } catch (err) {
    console.error(err);
  }
}

Note that this is timing sensitive, and deliberately uses versions of setLocalDescription (without arguments) and setRemoteDescription (with implicit rollback) to avoid races with other signaling messages being serviced.

The ignoreOffer variable is needed, because the RTCPeerConnection object on the impolite side is never told about ignored offers. We must therefore suppress errors from incoming candidates belonging to such offers.

11. Error Handling

Some operations throw or fire RTCError. This is an extension of DOMException that carries additional WebRTC-specific information.

11.1 RTCError Interface

WebIDL[Exposed=Window]
interface RTCError : DOMException {
  constructor(RTCErrorInit init, optional DOMString message = "");
  readonly attribute RTCErrorDetailType errorDetail;
  readonly attribute long? sdpLineNumber;
  readonly attribute long? sctpCauseCode;
  readonly attribute unsigned long? receivedAlert;
  readonly attribute unsigned long? sentAlert;
};

11.1.1 Constructors

constructor()

Run the following steps:

  1. Let init be the constructor's first argument.

  2. Let message be the constructor's second argument.

  3. Let e be a new RTCError object.

  4. Invoke the DOMException constructor of e with the message argument set to message and the name argument set to "OperationError".

    Note

    This name does not have a mapping to a legacy code so e.code will return 0.

  5. Set all RTCError attributes of e to the value of the corresponding attribute in init if it is present, otherwise set it to null.

  6. Return e.

11.1.2 Attributes

errorDetail of type RTCErrorDetailType, readonly

The WebRTC-specific error code for the type of error that occurred.

sdpLineNumber of type long, readonly, nullable

If errorDetail is "sdp-syntax-error" this is the line number where the error was detected (the first line has line number 1).

sctpCauseCode of type long, readonly, nullable

If errorDetail is "sctp-failure" this is the SCTP cause code of the failed SCTP negotiation.

receivedAlert of type unsigned long, readonly, nullable

If errorDetail is "dtls-failure" and a fatal DTLS alert was received, this is the value of the DTLS alert received.

sentAlert of type unsigned long, readonly, nullable

If errorDetail is "dtls-failure" and a fatal DTLS alert was sent, this is the value of the DTLS alert sent.

(Feature at Risk) Issue 1

All attributes defined in RTCError are marked at risk due to lack of implementation (errorDetail, sdpLineNumber, sctpCauseCode, receivedAlert and sentAlert). This does not include attributes inherited from DOMException.

11.1.3 RTCErrorInit Dictionary

WebIDLdictionary RTCErrorInit {
  required RTCErrorDetailType errorDetail;
  long sdpLineNumber;
  long sctpCauseCode;
  unsigned long receivedAlert;
  unsigned long sentAlert;
};

The errorDetail, sdpLineNumber, sctpCauseCode, receivedAlert and sentAlert members of RTCErrorInit have the same definitions as the attributes of the same name of RTCError.

11.2 RTCErrorDetailType Enum

WebIDLenum RTCErrorDetailType {
  "data-channel-failure",
  "dtls-failure",
  "fingerprint-failure",
  "sctp-failure",
  "sdp-syntax-error",
  "hardware-encoder-not-available",
  "hardware-encoder-error"
};
RTCErrorDetailType Enumeration description
Enum value Description
data-channel-failure The data channel has failed.
dtls-failure The DTLS negotiation has failed or the connection has been terminated with a fatal error. The message contains information relating to the nature of error. If a fatal DTLS alert was received, the receivedAlert attribute is set to the value of the DTLS alert received. If a fatal DTLS alert was sent, the sentAlert attribute is set to the value of the DTLS alert sent.
fingerprint-failure The RTCDtlsTransport's remote certificate did not match any of the fingerprints provided in the SDP. If the remote peer cannot match the local certificate against the provided fingerprints, this error is not generated. Instead a "bad_certificate" (42) DTLS alert might be received from the remote peer, resulting in a "dtls-failure".
sctp-failure The SCTP negotiation has failed or the connection has been terminated with a fatal error. The sctpCauseCode attribute is set to the SCTP cause code.
sdp-syntax-error The SDP syntax is not valid. The sdpLineNumber attribute is set to the line number in the SDP where the syntax error was detected.
hardware-encoder-not-available The hardware encoder resources required for the requested operation are not available.
hardware-encoder-error The hardware encoder does not support the provided parameters.

11.3 RTCErrorEvent Interface

The RTCErrorEvent interface is defined for cases when an RTCError is raised as an event:

WebIDL[Exposed=Window]
interface RTCErrorEvent : Event {
  constructor(DOMString type, RTCErrorEventInit eventInitDict);
  [SameObject] readonly attribute RTCError error;
};

11.3.1 Constructors

constructor()

Constructs a new RTCErrorEvent.

11.3.2 Attributes

error of type RTCError, readonly

The RTCError describing the error that triggered the event.

11.4 RTCErrorEventInit Dictionary

WebIDL          dictionary RTCErrorEventInit : EventInit {
  required RTCError error;
};

11.4.1 Dictionary RTCErrorEventInit Members

error of type RTCError

The RTCError describing the error associated with the event (if any).

12. Event summary

This section is non-normative.

The following events fire on RTCDataChannel objects:

Event name Interface Fired when...
open Event The RTCDataChannel object's underlying data transport has been established (or re-established).
message MessageEvent [html] A message was successfully received.
bufferedamountlow Event The RTCDataChannel object's bufferedAmount decreases from above its bufferedAmountLowThreshold to less than or equal to its bufferedAmountLowThreshold.
error RTCErrorEvent An error occurred on the data channel.
closing Event The RTCDataChannel object transitions to the "closing" state
close Event The RTCDataChannel object's underlying data transport has been closed.

The following events fire on RTCPeerConnection objects:

Event name Interface Fired when...
track RTCTrackEvent New incoming media has been negotiated for a specific RTCRtpReceiver, and that receiver's track has been added to any associated remote MediaStreams.
negotiationneeded Event The browser wishes to inform the application that session negotiation needs to be done (i.e. a createOffer call followed by setLocalDescription).
signalingstatechange Event The connection's [[SignalingState]] has changed. This state change is the result of either setLocalDescription or setRemoteDescription being invoked.
iceconnectionstatechange Event The RTCPeerConnection's [[IceConnectionState]] has changed.
icegatheringstatechange Event The RTCPeerConnection's [[IceGatheringState]] has changed.
icecandidate RTCPeerConnectionIceEvent A new RTCIceCandidate is made available to the script.
connectionstatechange Event The RTCPeerConnection.connectionState has changed.
icecandidateerror RTCPeerConnectionIceErrorEvent A failure occured when gathering ICE candidates.
datachannel RTCDataChannelEvent A new RTCDataChannel is dispatched to the script in response to the other peer creating a channel.

The following events fire on RTCDTMFSender objects:

Event name Interface Fired when...
tonechange RTCDTMFToneChangeEvent The RTCDTMFSender object has either just begun playout of a tone (returned as the tone attribute) or just ended the playout of tones in the toneBuffer (returned as an empty value in the tone attribute).

The following events fire on RTCIceTransport objects:

Event name Interface Fired when...
statechange Event The RTCIceTransport state changes.
gatheringstatechange Event The RTCIceTransport gathering state changes.
selectedcandidatepairchange Event The RTCIceTransport's selected candidate pair changes.

The following events fire on RTCDtlsTransport objects:

Event name Interface Fired when...
statechange Event The RTCDtlsTransport state changes.
error RTCErrorEvent An error occurred on the RTCDtlsTransport (either "dtls-failure" or "fingerprint-failure").

The following events fire on RTCSctpTransport objects:

Event name Interface Fired when...
statechange Event The RTCSctpTransport state changes.

13. Privacy and Security Considerations

This section is non-normative.

This section is non-normative; it specifies no new behaviour, but instead summarizes information already present in other parts of the specification. The overall security considerations of the general set of APIs and protocols used in WebRTC are described in [RFC8827].

13.1 Impact on same origin policy

This document extends the Web platform with the ability to set up real-time, direct communication between browsers and other devices, including other browsers.

This means that data and media can be shared between applications running in different browsers, or between an application running in the same browser and something that is not a browser, something that is an extension to the usual barriers in the Web model against sending data between entities with different origins.

The WebRTC specification provides no user prompts or chrome indicators for communication; it assumes that once the Web page has been allowed to access media, it is free to share that media with other entities as it chooses. Peer-to-peer exchanges of data view WebRTC datachannels can thus occur without any user explicit consent or involvement, similarly as a server-mediated exchange (e.g. via Web Sockets) could occur without user involvement.

13.2 Revealing IP addresses

Even without WebRTC, the Web server providing a Web application will know the public IP address to which the application is delivered. Setting up communications exposes additional information about the browser’s network context to the web application, and may include the set of (possibly private) IP addresses available to the browser for WebRTC use. Some of this information has to be passed to the corresponding party to enable the establishment of a communication session.

Revealing IP addresses can leak location and means of connection; this can be sensitive. Depending on the network environment, it can also increase the fingerprinting surface and create persistent cross-origin state that cannot easily be cleared by the user.

A connection will always reveal the IP addresses proposed for communication to the corresponding party. The application can limit this exposure by choosing not to use certain addresses using the settings exposed by the RTCIceTransportPolicy dictionary, and by using relays (for instance TURN servers) rather than direct connections between participants. One will normally assume that the IP address of TURN servers is not sensitive information. These choices can for instance be made by the application based on whether the user has indicated consent to start a media connection with the other party.

Mitigating the exposure of IP addresses to the application itself requires limiting the IP addresses that can be used, which will impact the ability to communicate on the most direct path between endpoints. Browsers are encouraged to provide appropriate controls for deciding which IP addresses are made available to applications, based on the security posture desired by the user. The choice of which addresses to expose is controlled by local policy (see [RFC8828] for details).

13.3 Impact on local network

Since the browser is an active platform executing in a trusted network environment (inside the firewall), it is important to limit the damage that the browser can do to other elements on the local network, and it is important to protect data from interception, manipulation and modification by untrusted participants.

Mitigations include:

These measures are specified in the relevant IETF documents.

13.4 Confidentiality of Communications

The fact that communication is taking place cannot be hidden from adversaries that can observe the network, so this has to be regarded as public information.

Communication certificates may be opaquely shared using postMessage(message, options) in anticipation of future needs. User agents are strongly encouraged to isolate the private keying material these objects hold a handle to, from the processes that have access to the RTCCertificate objects, to reduce memory attack surface.

13.5 Persistent information exposed by WebRTC

As described above, the list of IP addresses exposed by the WebRTC API can be used as a persistent cross-origin state.

Beyond IP addresses, the WebRTC API exposes information about the underlying media system via the RTCRtpSender.getCapabilities and RTCRtpReceiver.getCapabilities methods, including detailed and ordered information about the codecs that the system is able to produce and consume. A subset of that information is likely to be represented in the SDP session descriptions generated, exposed and transmitted during session negotiation. That information is in most cases persistent across time and origins, and increases the fingerprint surface of a given device.

When establishing DTLS connections, the WebRTC API can generate certificates that can be persisted by the application (e.g. in IndexedDB). These certificates are not shared across origins, and get cleared when persistent storage is cleared for the origin.

13.6 Setting SDP from remote endpoints

setRemoteDescription guards against malformed and invalid SDP by throwing exceptions, but makes no attempt to guard against SDP that might be unexpected by the application. Setting the remote description can cause significant resources to be allocated (including image buffers and network ports), media to start flowing (which may have privacy and bandwidth implications) among other things. An application that does not guard against malicious SDP could be at risk of resource deprivation, unintentionally allowing incoming media or at risk of not having certain events fire like ontrack if the other endpoint does not negotiate sending. Applications need to be on guard against malevolent SDP.

14. Accessibility Considerations

This section is non-normative.

The WebRTC 1.0 specification exposes an API to control protocols (defined within the IETF) necessary to establish real-time audio, video and data exchange.

The Telecommunications Device for the Deaf (TDD/TTY) enables individuals who are hearing or speech impaired (among others) to communicate over telephone lines. Real-Time Text, defined in [RFC4103], utilizes T.140 encapsulated in RTP to enable the transition from TDD/TTY devices to IP-based communications, including emergency communication with Public Safety Access Points (PSAP).

Since Real-Time Text requires the ability to send and receive data in near real time, it can be best supported via the WebRTC 1.0 data channel API. As defined by the IETF, the data channel protocol utilizes the SCTP/DTLS/UDP protocol stack, which supports both reliable and unreliable data channels. The IETF chose to standardize SCTP/DTLS/UDP over proposals for an RTP data channel which relied on SRTP key management and were focused on unreliable communications.

Since the IETF chose a different approach than the RTP data channel as part of the WebRTC suite of protocols, as of the time of this publication there is no standardized way for the WebRTC APIs to directly support Real-Time Text as defined at IETF and implemented in U.S. (FCC) regulations. The WebRTC working Group will evaluate whether the developing IETF protocols in this space warrant direct exposure in the browser APIs and is looking for input from the relevant user communities on this potential gap.

Within the IETF MMUSIC Working Group, work is ongoing to enable Real-time text to be sent over the WebRTC data channel, allowing gateways to be deployed to translate between the SCTP data channel protocol and RFC 4103 Real-Time Text. This work, once completed, is expected to enable a unified and interoperable approach for integrating real-time text in WebRTC user-agents (including browsers) - through a gateway or otherwise.

At the time of this publication, gateways that enable effective RTT support in WebRTC clients can be developed e.g. through a custom WebRTC data channel. This is deemed sufficient until such time as future standardized gateways are enabled via IETF protocols such as the SCTP data channel protocol and RFC 4103 Real-Time Text. This will need to be defined at IETF in conjunction with related work at W3C groups to effectively and consistently standardise RTT support internationally.

A. Candidate Amendments

Since its publication as a W3C Recommendation in January 2021, the following candidate amendments have been integrated in this document.

B. Acknowledgements

The editors wish to thank the Working Group chairs and Team Contact, Harald Alvestrand, Stefan Håkansson, Erik Lagerway and Dominique Hazaël-Massieux, for their support. Substantial text in this specification was provided by many people including Martin Thomson, Harald Alvestrand, Justin Uberti, Eric Rescorla, Peter Thatcher, Jan-Ivar Bruaroey and Peter Saint-Andre. Dan Burnett would like to acknowledge the significant support received from Voxeo and Aspect during the development of this specification.

The RTCRtpSender and RTCRtpReceiver objects were initially described in the W3C ORTC CG, and have been adapted for use in this specification.

C. References

Candidate Correction 46:Replace RFC8829 reference with RFC9429 (PR #2966)

B.1 Normative references

C.1 Normative references

[DOM]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT-6.0]
ECMA-262 6th Edition, The ECMAScript 2015 Language Specification. Allen Wirfs-Brock. Ecma International. June 2015. Standard. URL: http://www.ecma-international.org/ecma-262/6.0/index.html
[Fetch]
Fetch Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://fetch.spec.whatwg.org/
[FILEAPI]
File API. Marijn Kruisselbrink; Arun Ranganathan. W3C. 11 September 20194 December 2024. W3C Working Draft. URL: https://www.w3.org/TR/FileAPI/
[FIPS-180-4]
FIPS PUB 180-4 180-4: Secure Hash StandardStandard (SHS). U.S. Department of Commerce/National Institute of Standards and Technology. August 2015. National Standard. URL: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
[GETUSERMEDIA]
Media Capture and Streams. Cullen Jennings; Bernard Aboba; Jan-Ivar Bruaroey; Henrik Boström; youenn fablet; Daniel Burnett; Adam Bergkvist; Anant Narayanan. W3C. 21 January 202119 December 2024. W3C Candidate RecommendationCRD. URL: https://www.w3.org/TR/mediacapture-streams/
[hr-time]
High Resolution Time Level 2Time. Ilya GrigorikYoav Weiss. W3C. 21 7 November 20192024. W3C RecommendationWorking Draft. URL: https://www.w3.org/TR/hr-time-2/org/TR/hr-time-3/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[IANA-HASH-FUNCTION]
Hash Function Textual Names. IANA. URL: https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml
[IANA-RTP-2]
RTP Payload Format media types. IANA. URL: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-2
[INFRA]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119https://www.rfc-editor.org/rfc/rfc2119
[RFC3550]
RTP: A Transport Protocol for Real-Time Applications. H. Schulzrinne; S. Casner; R. Frederick; V. Jacobson. IETF. July 2003. Internet Standard. URL: https://tools.ietf.org/html/rfc3550https://www.rfc-editor.org/rfc/rfc3550
[RFC3890]
A Transport Independent Bandwidth Modifier for the Session Description Protocol (SDP). M. Westerlund. IETF. September 2004. Proposed Standard. URL: https://tools.ietf.org/html/rfc3890https://www.rfc-editor.org/rfc/rfc3890
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax. T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: https://tools.ietf.org/html/rfc3986
[RFC4566]
SDP: Session Description Protocol. M. Handley; V. Jacobson; C. Perkins. IETF. July 2006. Proposed Standard. URL: https://tools.ietf.org/html/rfc4566https://www.rfc-editor.org/rfc/rfc4566
[RFC4572]
Connection-Oriented Media Transport over the Transport Layer Security (TLS) Protocol in the Session Description Protocol (SDP). J. Lennox. IETF. July 2006. Proposed Standard. URL: https://tools.ietf.org/html/rfc4572https://www.rfc-editor.org/rfc/rfc4572
[RFC5245]
Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols. J. Rosenberg. IETF. April 2010. Proposed Standard. URL: https://tools.ietf.org/html/rfc5245https://www.rfc-editor.org/rfc/rfc5245
[RFC5246]
The Transport Layer Security (TLS) Protocol Version 1.2. T. Dierks; E. Rescorla. IETF. August 2008. Proposed Standard. URL: https://tools.ietf.org/html/rfc5246https://www.rfc-editor.org/rfc/rfc5246
[RFC5285]
A General Mechanism for RTP Header Extensions. D. Singer; H. Desineni. IETF. July 2008. Proposed Standard. URL: https://tools.ietf.org/html/rfc5285https://www.rfc-editor.org/rfc/rfc5285
[RFC5389]
Session Traversal Utilities for NAT (STUN). J. Rosenberg; R. Mahy; P. Matthews; D. Wing. IETF. October 2008. Proposed Standard. URL: https://tools.ietf.org/html/rfc5389https://www.rfc-editor.org/rfc/rfc5389
[RFC5506]
Support for Reduced-Size Real-Time Transport Control Protocol (RTCP): Opportunities and Consequences. I. Johansson; M. Westerlund. IETF. April 2009. Proposed Standard. URL: https://tools.ietf.org/html/rfc5506https://www.rfc-editor.org/rfc/rfc5506
[RFC5888]
The Session Description Protocol (SDP) Grouping Framework. G. Camarillo; H. Schulzrinne. IETF. June 2010. Proposed Standard. URL: https://tools.ietf.org/html/rfc5888https://www.rfc-editor.org/rfc/rfc5888
[RFC6464]
A Real-time Transport Protocol (RTP) Header Extension for Client-to-Mixer Audio Level Indication. J. Lennox, Ed.; E. Ivov; E. Marocco. IETF. December 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6464https://www.rfc-editor.org/rfc/rfc6464
[RFC6465]
A Real-time Transport Protocol (RTP) Header Extension for Mixer-to-Client Audio Level Indication. E. Ivov, Ed.; E. Marocco, Ed.; J. Lennox. IETF. December 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6465https://www.rfc-editor.org/rfc/rfc6465
[RFC6544]
TCP Candidates with Interactive Connectivity Establishment (ICE). J. Rosenberg; A. Keranen; B. B. Lowekamp; A. B. Roach. IETF. March 2012. Proposed Standard. URL: https://tools.ietf.org/html/rfc6544https://www.rfc-editor.org/rfc/rfc6544
[RFC7064]
URI Scheme for the Session Traversal Utilities for NAT (STUN) Protocol. S. Nandakumar; G. Salgueiro; P. Jones; M. Petit-Huguenin. IETF. November 2013. Proposed Standard. URL: https://tools.ietf.org/html/rfc7064https://www.rfc-editor.org/rfc/rfc7064
[RFC7065]
Traversal Using Relays around NAT (TURN) Uniform Resource Identifiers. M. Petit-Huguenin; S. Nandakumar; G. Salgueiro; P. Jones. IETF. November 2013. Proposed Standard. URL: https://tools.ietf.org/html/rfc7065https://www.rfc-editor.org/rfc/rfc7065
[RFC7656]
A Taxonomy of Semantics and Mechanisms for Real-Time Transport Protocol (RTP) Sources. J. Lennox; K. Gross; S. Nandakumar; G. Salgueiro; B. Burman, Ed.. IETF. November 2015. Informational. URL: https://tools.ietf.org/html/rfc7656https://www.rfc-editor.org/rfc/rfc7656
[RFC7675]
Session Traversal Utilities for NAT (STUN) Usage for Consent Freshness. M. Perumal; D. Wing; R. Ravindranath; T. Reddy; M. Thomson. IETF. October 2015. Proposed Standard. URL: https://tools.ietf.org/html/rfc7675https://www.rfc-editor.org/rfc/rfc7675
[RFC7874]
WebRTC Audio Codec and Processing Requirements. JM. Valin; C. Bran. IETF. May 2016. Proposed Standard. URL: https://tools.ietf.org/html/rfc7874https://www.rfc-editor.org/rfc/rfc7874
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://tools.ietf.org/html/rfc8174https://www.rfc-editor.org/rfc/rfc8174
[RFC8261]
Datagram Transport Layer Security (DTLS) Encapsulation of SCTP Packets. M. Tuexen; R. Stewart; R. Jesup; S. Loreto. IETF. November 2017. Proposed Standard. URL: https://tools.ietf.org/html/rfc8261https://www.rfc-editor.org/rfc/rfc8261
[RFC8445]
Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal. A. Keranen; C. Holmberg; J. Rosenberg. IETF. July 2018. Proposed Standard. URL: https://tools.ietf.org/html/rfc8445https://www.rfc-editor.org/rfc/rfc8445
[RFC8656]
Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN). T. Reddy, Ed.; A. Johnston, Ed.; P. Matthews; J. Rosenberg. IETF. February 2020. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8656
[RFC8826]
Security Considerations for WebRTCfor WebRTC. E. Rescorla. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8826https://www.rfc-editor.org/rfc/rfc8826
[RFC8829]
JavaScript Session Establishment Protocol (JSEP). J. Uberti; C. Jennings; E. Rescorla, Ed.. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8829
[RFC8831]
WebRTC Data Channels. R. Jesup; S. Loreto; M. Tüxen. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8831https://www.rfc-editor.org/rfc/rfc8831
[RFC8832]
WebRTC Data Channel Establishment Protocol. R. Jesup; S. Loreto; M. Tüxen. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8832https://www.rfc-editor.org/rfc/rfc8832
[RFC8834]
Media Transport and Use of RTP in WebRTC. C. Perkins; M. Westerlund; J. Ott. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8834https://www.rfc-editor.org/rfc/rfc8834
[RFC8835]
Transports for WebRTC. H. Alvestrand. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8835https://www.rfc-editor.org/rfc/rfc8835
[RFC8838]
Trickle ICE: Incremental Provisioning of Candidates for the Interactive Connectivity Establishment (ICE) Protocol. E. Ivov; J. Uberti; P. Saint-Andre. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8838https://www.rfc-editor.org/rfc/rfc8838
[RFC8841]
Session Description Protocol (SDP) Offer/Answer Procedures for Stream Control Transmission Protocol (SCTP) over Datagram Transport Layer Security (DTLS) Transport. C. Holmberg; R. Shpount; S. Loreto; G. Camarillo. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8841https://www.rfc-editor.org/rfc/rfc8841
[RFC8843]
Negotiating Media Multiplexing Using the Session Description Protocol (SDP). C. Holmberg; H. Alvestrand; C. Jennings. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8843https://www.rfc-editor.org/rfc/rfc8843
[RFC8851]
RTP Payload Format Restrictions. A.B. Roach, Ed.. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8851https://www.rfc-editor.org/rfc/rfc8851
[RFC8853]
Using Simulcast in Session Description Protocol (SDP) and RTP Sessions. B. Burman; M. Westerlund; S. Nandakumar; M. Zanaty. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8853https://www.rfc-editor.org/rfc/rfc8853
[RFC8863]
Interactive Connectivity Establishment Patiently Awaiting Connectivity (ICE PAC). C. Holmberg; J. Uberti. IETF. January 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8863
[RFC9429]
JavaScript Session Establishment Protocol (JSEP). J. Uberti; C. Jennings; E. Rescorla, Ed. IETF. April 2024. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9429
[SDP]
An Offer/Answer Model with Session Description Protocol (SDP). J. Rosenberg; H. Schulzrinne. IETF. June 2002. Proposed Standard. URL: https://tools.ietf.org/html/rfc3264https://www.rfc-editor.org/rfc/rfc3264
[STUN-PARAMETERS]
STUN Error Codes. IETF. IANA. April 2011. IANA Parameter Assignment. URL: https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml#stun-parameters-6
[WebCryptoAPI]
Web Cryptography API. Mark Watson. W3C. 26 January 2017. W3C Recommendation. URL: https://www.w3.org/TR/WebCryptoAPI/
[WEBIDL]
Web IDL. Boris Zbarsky. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBRTC-STATS]
Identifiers for WebRTC's Statistics API. Harald Alvestrand; Varun Singh; Henrik Boström. W3C. 20 January 20216 March 2025. W3C Candidate RecommendationCRD. URL: https://www.w3.org/TR/webrtc-stats/
[X509V3]
ITU-T Recommendation X.509 version 3 (1997). "Information Technology - Open Systems Interconnection - The Directory Authentication Framework"  ISO/IEC 9594-8:1997.. ITU.
[X690]
Recommendation X.690 — Information Technology — ASN.1 Encoding Rules — Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER), and Distinguished Encoding Rules (DER). ITU. URL: https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf

C.2 Informative references

[API-DESIGN-PRINCIPLES]
Web Platform Design Principles. Martin Thomson; Jeffrey Yasskin. W3C. 6 March 2025. W3C Working Group Note. URL: https://www.w3.org/TR/design-principles/
[INDEXEDDB]
Indexed Database API. Nikunj Mehta; Jonas Sicking; Eliot Graff; Andrei Popescu; Jeremy Orlow; Joshua Bell. W3C. 8 January 2015. W3C Recommendation. URL: https://www.w3.org/TR/IndexedDB/
[RFC4103]
RTP Payload for Text Conversation. G. Hellstrom; P. Jones. IETF. June 2005. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4103
[RFC6236]
Negotiation of Generic Image Attributes in the Session Description Protocol (SDP). I. Johansson; K. Jung. IETF. May 2011. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6236
[RFC7728]
RTP Stream Pause and Resume. B. Burman; A. Akram; R. Even; M. Westerlund. IETF. February 2016. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7728
[RFC8825]
Overview: Real-Time Protocols for Browser-Based Applications. H. Alvestrand. IETF. January 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8825
[RFC8827]
WebRTC Security Architecture. E. Rescorla. IETF. January 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8827
[RFC8828]
WebRTC IP Address Handling Requirements. J. Uberti; G. Shieh. IETF. January 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8828