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] … 메시지 주제 … (아카이브)
참여하기
메일링 리스트

또한 참고: 번역본.


개요

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

이 문서의 상태

이 섹션은 이 문서가 출판될 당시의 상태를 설명합니다. 현재 W3C 출판물 목록 및 이 기술 보고서의 최신 개정판은 W3C 기술 보고서 색인에서 확인할 수 있습니다: https://www.w3.org/TR/.

이 문서에는 후보 수정사항이 포함되어 있습니다.

관련 테스트 스위트는 API의 권고안 최초 출판 시점에서 구현 보고서를 작성하는 데 사용되었습니다. 해당 테스트 스위트는 이후 제안 및 후보 수정사항을 통합하도록 업데이트되었으며, 이러한 수정사항의 구현 현황에 초점을 두고 업데이트된 구현 보고서가 작성되었습니다. 이 보고서는 제안된 수정사항 중 이중 구현된 기능을 선정하여, 이번 권고안 버전에 완전히 통합하였습니다.

이 문서는 웹 실시간 통신 작업 그룹에서 권고안 절차를 통해 권고안으로 출판되었습니다. 이전 권고안 이후, 실질적인 변경과 새로운 기능을 도입하는 후보 수정사항을 포함합니다.

W3C는 이 명세를 웹 표준으로 폭넓게 도입할 것을 권장합니다.

W3C 권고안은 광범위한 합의 구축 후, W3C와 회원사가 승인한 명세이며, 작업 그룹 구성원들이 로열티 없는 라이선스 제공을 약속합니다. 향후 권고안 업데이트에는 새로운 기능이 통합될 수 있습니다.

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

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

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 제작되었습니다. W3C공개 특허 공개 목록을 그룹 산출물과 관련하여 유지합니다. 해당 페이지에는 특허 공개 안내도 포함되어 있습니다. 특정 특허가 필수 청구항을 포함한다고 믿는 개인은 W3C 특허 정책 6절에 따라 정보를 공개해야 합니다.

이 문서는 2023년 11월 3일 W3C 절차 문서에 의해 관리됩니다.

1. 소개

이 섹션은 비규범적입니다.

HTML에서 피어 투 피어 통신과 화상 회의는 다음과 같은 여러 측면을 포함하며, 이 명세서에서 다룹니다:

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

2. 적합성

비규범적 섹션뿐만 아니라, 이 명세서의 모든 저작 지침, 다이어그램, 예제, 참고 사항은 비규범적입니다. 그 외 모든 내용은 규범적입니다.

이 문서에서 MAY, MUST, MUST NOT, SHOULD라는 핵심 용어는 BCP 14 [RFC2119] [RFC8174] 에서 설명된 대로, 대문자로 표시된 경우에만 해석되어야 합니다.

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

알고리즘이나 특정 단계로 표현된 적합성 요구사항은 최종 결과가 동일하다면 어떤 방식으로든 구현할 수 있습니다. (특히, 이 명세서에 정의된 알고리즘은 이해하기 쉽게 작성된 것이며, 성능을 위해 작성된 것은 아닙니다.)

이 명세서에서 정의된 API를 ECMAScript로 구현하는 경우 MUST Web IDL 명세서 [WEBIDL]에 정의된 ECMAScript 바인딩을 일관되게 구현해야 하며, 이 명세서도 그 명세서와 용어를 사용합니다.

3. 용어

콜백 인터페이스인 EventHandler는 [HTML]에서 정의됩니다.

작업 큐에 추가, 네트워킹 작업 소스의 개념은 [HTML]에서 정의됩니다.

이벤트 발생의 개념은 [DOM]에서 정의됩니다.

이벤트, 이벤트 핸들러, 이벤트 핸들러 이벤트 타입 용어는 [HTML]에서 정의됩니다.

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

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

MediaStream, MediaStreamTrack, MediaStreamConstraints 용어는 [GETUSERMEDIA]에서 정의됩니다. 참고로 MediaStream은 본 문서의 9.2 MediaStream에서 확장되며, MediaStreamTrack9.3 MediaStreamTrack에서 확장됩니다.

Blob 용어는 [FILEAPI]에서 정의됩니다.

미디어 설명은 [RFC4566]에서 정의됩니다.

미디어 전송은 [RFC7656]에서 정의됩니다.

generation 용어는 [RFC8838] 섹션 2에서 정의됩니다.

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

예외를 언급할 때, throw, created 용어는 [WEBIDL]에서 정의됩니다.

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

"throw" 용어는 [INFRA]에서 명시된 대로 사용됩니다. 이는 현재 처리 단계를 종료합니다.

이행됨, 거부됨, 해결됨, 종결됨 용어는 프라미스(Promise) 맥락에서 [ECMASCRIPT-6.0]에서 정의됩니다.

AlgorithmIdentifier 용어는 [WebCryptoAPI]에서 정의됩니다.

참고

자바스크립트 API의 일반 원칙이 적용됩니다. 여기에는 run-to-completion 및 [API-DESIGN-PRINCIPLES]에 정의된 no-data-races 원칙이 포함됩니다. 즉, 태스크가 실행되는 동안 외부 이벤트는 자바스크립트 애플리케이션에 보이는 것에 영향을 주지 않습니다. 예를 들어, 데이터 채널에서 "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>, 기본값은 []입니다.

ICE에서 사용할 수 있는 서버(STUN 및 TURN 서버 등)를 설명하는 객체 배열입니다. 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 또는 sequence<DOMString>) urls;
  DOMString username;
  DOMString credential;
};
RTCIceServer 사전 멤버
urls 타입 (DOMString 또는 sequence<DOMString>), 필수

[RFC7064] 및 [RFC7065] 또는 기타 URI 타입에 정의된 STUN 또는 TURN 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] (section 4.1.1.)에서 설명된 대로, iceTransportPolicy 멤버가 RTCConfiguration에 지정된 경우, 애플리케이션에 허용된 후보를 제공하기 위한 ICE 후보 정책 [RFC9429] (section 3.5.3.)을 정의합니다. 브라우저는 이 후보들만 연결 확인에 사용합니다.

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

ICE 에이전트는 TURN 서버를 통과하는 후보 등 미디어 릴레이 후보만 사용합니다.

참고
이 값은 원격 엔드포인트가 사용자의 IP 주소를 알지 못하도록 할 때 사용할 수 있습니다. 예를 들어, "통화" 기반 애플리케이션에서는 상대방이 어떤 방식으로 동의하기 전까지 상대방의 IP 주소를 알 수 없도록 할 수 있습니다.
all

ICE 에이전트는 이 값이 지정된 경우 모든 후보 유형을 사용할 수 있습니다.

참고
구현체는 여전히 자체 후보 필터링 정책을 사용하여 애플리케이션에 노출되는 IP 주소를 제한할 수 있습니다. 이는 RTCIceCandidate.address 설명에도 명시되어 있습니다.

4.2.4 RTCBundlePolicy 열거형

[RFC9429] (section 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] (section 4.1.1.)에서 설명된 대로, RTCRtcpMuxPolicy는 비멀티플렉스 RTCP를 지원하기 위해 수집되는 ICE 후보에 영향을 줍니다. 이 명세에서 정의된 유일한 값은 "require"입니다.

WebIDLenum RTCRtcpMuxPolicy {
  "require"
};
RTCRtcpMuxPolicy 열거형 설명
열거형 값 설명
require RTP에 대해서만 ICE 후보를 수집하며 RTCP는 해당 RTP 후보에 멀티플렉스됩니다. 원격 엔드포인트가 rtcp-mux를 지원하지 않으면 세션 협상이 실패합니다.

4.2.6 오퍼/응답 옵션

이 사전들은 오퍼/응답 생성 과정을 제어하는 데 사용할 수 있는 옵션을 설명합니다.

WebIDLdictionary RTCOfferAnswerOptions {};
RTCOfferAnswerOptions 사전 멤버
WebIDLdictionary RTCOfferOptions : RTCOfferAnswerOptions {
  boolean iceRestart = false;
};
RTCOfferOptions 사전 멤버
iceRestart 타입 boolean, 기본값은 false

이 사전 멤버의 값이 true이거나, 관련 RTCPeerConnection 객체의 [[LocalIceCredentialsToReplace]] 슬롯이 비어 있지 않으면, 생성된 설명에는 현재 자격 증명과 다른 ICE 자격 증명이 포함됩니다 (이는 currentLocalDescription 속성의 SDP에서 확인할 수 있습니다). 생성된 설명을 적용하면 [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입니다.
signaling state transition diagram
그림 1 비규범적 시그널링 상태 전이 다이어그램. 메서드 호출 축약.

전이 예시 세트:

발신자 전이:
수신자 전이:

4.3.2 RTCIceGatheringState 열거형

WebIDLenum RTCIceGatheringState {
  "new",
  "gathering",
  "complete"
};
RTCIceGatheringState 열거형 설명
열거형 값 설명
new RTCIceTransport 중 하나 이상이 "new" 상태이고, 어떤 transport도 "gathering" 상태가 아니거나 transport가 없는 경우입니다.
gathering RTCIceTransport 중 하나 이상이 "gathering" 상태인 경우입니다.
complete 하나 이상의 RTCIceTransport가 존재하며, 모든 RTCIceTransport가 "complete" 상태인 경우입니다.

고려되는 transport 집합은 현재 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" 상태이거나 transport가 없는 경우입니다.
connected 이전 상태가 적용되지 않으며, [[IceConnectionState]] 값이 "connected" 이고, 모든 RTCDtlsTransport가 "connected" 또는 "closed" 상태인 경우입니다.
connecting 이전 상태가 적용되지 않은 경우입니다.
참고

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

고려되는 transport 집합은 현재 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이 아닐 때 해당됩니다.

RTCIceTransport가 시그널링의 결과로 폐기되거나(RTCP mux 또는 번들링 등), 시그널링의 결과로 생성될 수 있다는 점에 유의하세요(새 미디어 설명 추가 등). 이 경우 상태가 바로 다른 상태로 진행될 수 있습니다.

4.4 RTCPeerConnection 인터페이스

[RFC9429] 명세 전체는 RTCPeerConnection이 어떻게 동작하는지에 대한 세부 사항을 설명합니다. [RFC9429]의 특정 하위 섹션에 대한 참조가 적절히 제공됩니다.

4.4.1 동작

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

configuration.iceServers에는 ICE에서 사용하는 서버를 찾고 접근하기 위한 정보가 포함됩니다. 애플리케이션은 각 타입별로 여러 서버를 제공할 수 있으며, TURN 서버는 서버 리플렉시브 후보를 수집하는 목적으로 STUN 서버로도 사용할 수 있습니다(MAY).

RTCPeerConnection 객체는 [[SignalingState]], 그리고 집계된 상태인 [[ConnectionState]], [[IceGatheringState]], 그리고 [[IceConnectionState]] 를 가집니다. 이들은 객체가 생성될 때 초기화됩니다.

RTCPeerConnection의 ICE 프로토콜 구현은 ICE 에이전트 [RFC5245]로 표현됩니다. RTCPeerConnection의 특정 메서드는 ICE 에이전트와의 상호작용을 포함합니다. 즉, addIceCandidate, setConfiguration, setLocalDescription, setRemoteDescription 그리고 close입니다. 이러한 상호작용은 본 문서와 [RFC9429]의 해당 섹션에서 설명됩니다. ICE 에이전트는 또한 RTCIceTransport의 내부 표현의 상태가 변경될 때 사용자 에이전트에 신호를 제공합니다. 이에 대한 설명은 5.6 RTCIceTransport 인터페이스에서 다룹니다.

이 섹션에 나열된 작업의 태스크 소스는 네트워킹 태스크 소스입니다.

참고

SDP 협상의 상태는 내부 변수 [[SignalingState]], [[CurrentLocalDescription]], [[CurrentRemoteDescription]], [[PendingLocalDescription]], [[PendingRemoteDescription]] 로 표현됩니다. 이 변수들은 setLocalDescriptionsetRemoteDescription 동작에서만 설정되며, addIceCandidate 동작 및 후보 공개 절차에서 변경됩니다. 각 경우마다, 다섯 변수의 모든 수정은 이벤트를 발생시키거나 콜백을 호출하기 전에 완료되므로, 변경 사항이 한 시점에 모두 반영됩니다.

언로딩 문서 정리 단계 중 하나로 다음 단계를 실행합니다:

  1. windowdocument관련 글로벌 객체로 둔다.

  2. windowRTCPeerConnection 객체 connection관련 글로벌 객체와 같은 경우, connection에 대해 연결 닫기connection과 값 true로 실행한다.

4.4.1.1 생성자

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

  1. 아래 열거된 단계 중 명시되지 않은 이유로 실패하면, 예외를 던진다 UnknownErrormessage 속성에 적절한 설명을 설정한다.

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

  3. connection[[DocumentOrigin]] 내부 슬롯을 추가하고, 관련 설정 객체origin 값으로 초기화한다.

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

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

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

    3. certificate를 저장한다.

  6. 그렇지 않으면, 하나 이상의 새로운 RTCCertificate 인스턴스를 이 RTCPeerConnection 인스턴스와 함께 생성하여 저장한다. 이는 비동기적으로 발생할 수 있으며, 이후 단계에서 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]] 내부 슬롯을 추가하고, operations chain 을 나타내며, 빈 리스트로 초기화한다.

  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]])을 가지며, 체인에서 한 번에 하나의 비동기 작업만 동시 실행되도록 보장합니다. 이전 호출의 반환된 promise가 아직 정산(settled)되지 않은 상태에서 후속 호출이 이루어지면, 이들은 체인에 추가되어 모든 이전 호출이 실행을 끝내고 promise가 정산(settled)된 이후에 실행됩니다.

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

  1. connectionRTCPeerConnection 객체로 둔다.

  2. connection.[[IsClosed]]true인 경우, 새로 거부된(rejected) promise를 반환하며 생성된 InvalidStateError를 포함한다.

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

  4. p를 새 promise로 둔다.

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

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

  7. operation이 반환한 promise가 성공(fulfillment)하거나 거절(rejection)될 때, 다음 단계를 실행한다:

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

    2. operation이 반환한 promise가 값으로 성공(fulfilled)되었다면, 성공으로 p를 해당 값으로 완료한다.

    3. operation이 반환한 promise가 값으로 거절(rejected)되었다면, 거절p를 해당 값으로 완료한다.

    4. p성공 또는 거절될 때, 다음 단계를 실행한다:

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

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

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

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

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

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

  8. p를 반환한다.

4.4.1.3 연결 상태 업데이트

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

  1. connection을 상태가 변경된 RTCPeerConnection 객체로 둔다.

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

  3. newStateRTCPeerConnectionState 열거형에서 설명된 대로 새로운 상태값을 도출한 값으로 둔다.

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

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

  6. connectionstatechange 이벤트connection에서 발생시킨다.

4.4.1.4 세션 설명 설정하기

로컬 세션 설명을 설정한다 descriptionRTCPeerConnection 객체 connection에 설정하려면, 세션 설명을 설정한다 descriptionconnection에 추가 값 false와 함께 설정한다.

원격 세션 설명을 설정한다 descriptionRTCPeerConnection 객체 connection에 설정하려면, 세션 설명을 설정한다 descriptionconnection에 추가 값 true와 함께 설정한다.

세션 설명을 설정한다 descriptionRTCPeerConnection 객체 connection에 설정할 때, remote 불리언 값이 주어지면 다음 단계를 실행한다:

  1. 새로운 프로미스인 p를 생성한다.

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

  3. jsepSetOfTransceiversconnectionset of transceivers 의 얕은 복사본으로 둔다.

  4. 병렬로(In parallel) description 을(를) 적용하는 과정을 [RFC9429] (섹션 5.5.섹션 5.6.) 에 기술된 대로 시작하되, 다음 추가 제한을 적용한다:

    1. 어떤 "RtpTransceivers" 가 존재하는지에 대한 단일 신뢰 원본(source of truth)으로 jsepSetOfTransceivers 를 사용하고, 각 트랜시버의 [[JsepMid]] 내부 슬롯을 그들의 "mid property" 로 사용한다.

    2. Candidate Correction 5:관리적으로 금지된 후보에 대한 ICE 수집 및 연결성 검사 금지 (PR #2708)

      remotefalse 이고 이것이 [RFC9429] (섹션 5.9.) 에 정의된 ICE 후보 수집 과정을 촉발시키는 경우, ICE AgentMUST NOT (절대로 수집해서는 안 된다) 관리적으로 금지될 administratively prohibited 후보들을 수집.

    3. Candidate Correction 5:관리적으로 금지된 후보에 대한 ICE 수집 및 연결성 검사 금지 (PR #2708)

      remotetrue 이고 이것이 [RFC9429] (섹션 5.10.) 에서의 ICE 연결성 검사를 촉발시키는 경우, ICE AgentMUST NOT (절대로 시도해서는 안 된다) 관리적으로 금지된 administratively prohibited 후보들에 연결을 시도하는 것을.

    4. remotetrue 이면, 안정(stable) 상태였던 것처럼 이후 오퍼에 대한 검사를 수행하여, 그 사이에 answer 가 적용된 것처럼 연속된(back-to-back) 오퍼들을 검증한다.

    5. description 을 적용하는 것이 트랜시버 transceiver 를 수정하게 만들고, transceiver.[[Sender]].[[SendEncodings]] 가 비어 있지 않고, description 을 처리함으로써 생성될 인코딩들과 동일하지 않다면, description 을 적용하는 과정은 실패한다. 이 명세는 원격에서 시작된 RID 재협상을 허용하지 않는다.

       
    6. description 을(를) 적용하는 과정이 어떤 이유로든 실패한 경우, 사용자 에이전트는 다음 단계를 실행하는 태스크를 큐에 넣어야 한다(MUST):

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

      2. 현재 connection.[[SignalingState]] 에 대해 description.typeRFC9429 (섹션 5.5., 섹션 5.6.) 에 설명된 대로 유효하지 않다면, reject p 를 새로 생성한 InvalidStateError 로 거절하고 이 단계들을 중단한다.

      3. description 의 내용이 유효한 SDP 문법이 아니면, reject pRTCError (여기서 errorDetail 은 "sdp-syntax-error" 로 설정하고, sdpLineNumber 속성은 문법 오류가 탐지된 SDP 내 줄 번호로 설정) 로 거절하고 이 단계들을 중단한다.

      4. remotetrue 이고, connectionRTCRtcpMuxPolicyrequire 이며, description 이 RTCP mux 를 사용하지 않는다면, reject p 를 새로 생성한 InvalidAccessError 로 거절하고 이 단계들을 중단한다.

      5. 위에서 설명한 대로 description 이 RID 재협상을 시도했다면, reject p 를 새로 생성한 InvalidAccessError 로 거절하고 이 단계들을 중단한다.

      6. description 의 내용이 유효하지 않다면, reject p 를 새로 생성한 InvalidAccessError 로 거절하고 이 단계들을 중단한다.

      7. 기타 모든 오류의 경우, reject p 를 새로 생성한 OperationError 로 거절한다.

    7. description 이(가) 성공적으로 적용되었다면, 사용자 에이전트는 다음 단계를 실행하는 태스크를 큐에 넣어야 한다 (MUST):

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

      2. remotetrue 이고 description 의 타입이 "offer" 인 경우, connection 에 대한 addTrack() 호출이 description 을 적용하는 과정 동안 하나라도 성공했다면, 이 단계들을 중단하고 추가 트랜시버를 포함하도록 그것들이 사전에 성공했었던 것처럼 과정을 처음부터 다시 시작한다.

      3. connection 에 연관된 setParameters 메서드로부터의 어떤 프로미스라도 settled 상태가 아니라면, 이 단계들을 중단하고 과정을 다시 시작한다.

      4. description 의 타입이 "offer" 이고 connection.[[SignalingState]] 가 "stable" 이면, connectionset of transceivers 에 있는 각 transceiver 에 대해 다음 단계를 수행한다:

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

        2. Candidate Correction 13:Rollback 시 sRD(simulcastOffer)에 의해 덮어쓴 ridless 인코딩 복원 (PR #2797)

          만약 transceiver.[[Sender]].[[SendEncodings]].length 가 1 이고 그 단일 인코딩이 containsrid 멤버를 포함하지 않는다면, 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" 로 설정하며, release early candidates 를 수행한다.

        2. description 의 타입이 "answer" 이면, 이는 offer-answer 협상 완료이다. connection.[[CurrentLocalDescription]]description 으로부터 구성된 새로운 RTCSessionDescription 객체로 설정하고, connection.[[CurrentRemoteDescription]]connection.[[PendingRemoteDescription]] 로 설정한다. 이어서 connection.[[PendingRemoteDescription]]connection.[[PendingLocalDescription]] 를 모두 null 로 설정한다. connection.[[LastCreatedOffer]]connection.[[LastCreatedAnswer]] 를 모두 "" 로 설정하고, connection.[[SignalingState]] 를 "stable" 로 설정한 뒤, release early candidates 를 수행한다. 마지막으로, connection.[[LocalIceCredentialsToReplace]] 안의 ICE 자격증명들 중 어떤 것도 description 에 존재하지 않는다면 connection.[[LocalIceCredentialsToReplace]] 를 빈 집합으로 설정한다.

        3. description 의 타입이 "pranswer" 이면, connection.[[PendingLocalDescription]]description 으로부터 구성된 새로운 RTCSessionDescription 객체로 설정하고, connection.[[SignalingState]] 를 "have-local-pranswer" 로 설정하며 release early candidates 를 수행한다.

      6. 그렇지 않으면 ( remotetrue 인 경우 ) 다음 중 하나를 수행한다:

        1. description 의 타입이 "offer" 이면, connection.[[PendingRemoteDescription]] 속성을 description 으로부터 구성된 새로운 RTCSessionDescription 객체로 설정하고 connection.[[SignalingState]] 를 "have-remote-offer" 로 설정한다.

        2. description 의 타입이 "answer" 이면, 이는 offer-answer 협상 완료이다. connection.[[CurrentRemoteDescription]]description 으로부터 구성된 새로운 RTCSessionDescription 객체로 설정하고 connection.[[CurrentLocalDescription]]connection.[[PendingLocalDescription]] 로 설정한다. connection.[[PendingRemoteDescription]]connection.[[PendingLocalDescription]] 를 모두 null 로 설정한다. connection.[[LastCreatedOffer]]connection.[[LastCreatedAnswer]]"" 로 설정하고, connection.[[SignalingState]] 를 "stable" 로 설정한다. 마지막으로 connection.[[LocalIceCredentialsToReplace]] 안의 ICE 자격증명 어느 것도 새로 설정된 connection.[[CurrentLocalDescription]] 에 존재하지 않는다면 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, removeList, errorList 를 빈 리스트로 둔다.

      9. description 의 타입이 "answer" 또는 "pranswer" 이면 다음 단계를 수행한다:

        1. description 이 [RFC8841] 10.3 및 10.4 절에 정의된 새로운 SCTP 연합 수립을 개시한다면, 초기 상태가 "connecting" 인 RTCSctpTransport 를 생성 하고 그 결과를 [[SctpTransport]] 슬롯에 할당한다. 그렇지 않고 SCTP 연합이 이미 수립되어 있으며 SDP 의 max-message-size 속성이 갱신되었다면, data max message size 를 갱신 한다 connection.[[SctpTransport]] 에 대해.

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

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

        1. remotefalse 이면 description 안의 각 media description 에 대해 다음 단계를 수행한다:

          Candidate Correction 26:createAnswer() 의 encodings 와 sLD(answer) 의 SendEncodings 정리 (PR #2801)
          1. media description 이 아직 어떤 RTCRtpTransceiver 객체와도 associated 되어 있지 않다면 다음 단계를 수행한다:

            1. transceiver 를 그 media description 을 생성하는 데 사용된 RTCRtpTransceiver 로 둔다.

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

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

            4. 만약 그 media description 이 [RFC8843] 에 따라 기존 media media transport 를 사용하는 것으로 표시되면, transport 를 그 전송의 RTP/RTCP 컴포넌트를 표현하는 RTCDtlsTransport 객체로 둔다.

            5. 그렇지 않으면 transport 를 새로 생성된 RTCDtlsTransport 객체(새로운 기반 RTCIceTransport 포함) 로 둔다.

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

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

          2. transceiver 를 그 media descriptionassociatedRTCRtpTransceiver 로 둔다.

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

          4. directionRTCRtpTransceiverDirection 값으로 두되 이는 media media description 에서의 방향을 나타낸다.

          5. direction 이 "sendrecv" 또는 "recvonly" 이면 transceiver.[[Receptive]]true 로, 아니면 false 로 설정한다.

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

            Note

            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. Set the associated remote streamstransceiver.[[Receiver]], 빈 리스트, 또 다른 빈 리스트, 그리고 removeList 를 인자로 하여 수행한다.

              2. process the removal of a remote remote track 를 그 media description, transceiver, 그리고 muteTracks 와 함께 수행한다.

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

        2. 그렇지 않으면 ( remotetrue ) description 안의 각 media description 에 대해 다음 단계를 수행한다:

          Candidate Correction 12:encoding.active 와 simulcast ~rid 상호작용 제거 (PR #2754)
          Candidate Correction 14:RTCTransceiver.direction 이 offer / answer 에서 로컬 선호 반영 (PR #2759)
          Candidate Correction 22:원격 offer 의 rid 프루닝을 클라이언트 answer 통해 허용 (PR #2758)
          Candidate Correction 37:rid 불일치로 sRD(offer) 실패시키지 않고 단일(unicast)로 응답 (PR #2794)
          Candidate Correction 25:proposedSendEncodings 내 중복 rid 제거 (PR #2800)
          Candidate Correction 27:쉼표로 구분된 rid 대안 무시 (PR #2813)
          1. description 의 타입이 "offer" 이고 media description 이 시뮬캐스트 수신 요청을 포함한다면, simulcast 속성에 지정된 rid 값의 순서를 사용하여 각 레이어에 대한 RTCRtpEncodingParameters 사전을 생성하고, 해당 rid valuevalue (쉼표로 구분된 대안이 존재하면 첫 번째 값만 사용) 에 따라 rid 멤버를 채운다. 그리고 sendEncodingsproposedSendEncodings 를 생성된 사전들을 담은 목록목록 으로 둔다. 그렇지 않으면 sendEncodingsproposedSendEncodings 를 빈 리스트로 둔다.

          2. proposedSendEncodings 에 있는 각 인코딩 encoding 을 역순으로 순회하며, encodingridproposedSendEncodings 내 다른 인코딩과 일치하면 proposedSendEncodings 에서 encoding 을 제거한다.

          3. supportedEncodings 를 구현이 지원할 수 있는 최대 인코딩 수로 둔다. sendEncodingsproposedSendEncodings 의 길이가 supportedEncodings 보다 크면 길이가 supportedEncodings 가 되도록 sendEncodingsproposedSendEncodings 를 잘라낸다.

          4. sendEncodingsproposedSendEncodings 이 비어 있지 않다면, 인코딩의 scaleResolutionDownBy2^(length of sendEncodingsproposedSendEncodings - encoding index - 1) 로 설정한다.

          5. [RFC8829RFC9429] (section 5.10.) 에 설명된 대로 기존의 RTCRtpTransceiver 객체 transceiver 를 찾아 그 media description 을 나타내도록 시도한다.

          6. 적절한 트랜시버가 발견되었고 (transceiver 설정됨) sendEncodingsproposedSendEncodings 이 비어 있지 않으면, transceiver.[[Sender]].[[SendEncodings]]sendEncodings 로 설정하고 transceiver.[[Sender]].[[LastReturnedParameters]]null 로 설정한다. 다음 단계를 수행한다:

            1. 만약 transceiver.[[Sender]].[[SendEncodings]] 길이가 1 이고, 그 단일 인코딩이 containsrid 멤버를 포함하지 않는다면 transceiver.[[Sender]].[[SendEncodings]]proposedSendEncodings 로 설정하고 transceiver.[[Sender]].[[LastReturnedParameters]]null 로 설정한다.

          7. 적절한 트랜시버가 발견되지 않았다면 (transceiver 미설정), 다음 단계를 수행한다:

            1. Create an RTCRtpSender, sender, 를 media media description 에서 sendEncodingsproposedSendEncodings 을 사용하여 생성한다.

            2. Create an RTCRtpReceiver, receiver, 를 media media description 에서 생성한다.

            3. Create an RTCRtpTransceiversender, receiver 및 "recvonly" 값을 가진 RTCRtpTransceiverDirection 으로 생성하고 결과를 transceiver 로 둔다.

            4. transceiverconnectionset of of transceivers 에 추가한다.

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

            1. description 이 simulcast 미지원/미요구를 나타내거나, 또는 description 이 이전에 협상된 모든 레이어를 누락한 경우, transceiver.[[Sender]].[[SendEncodings]] 의 사전 중 첫 번째를 제외한 모두를 제거하고 이 하위 단계들을 중단한다.

            2. descriptionrejects is missing 이전의 offered previously negotiated 레이어 중 하나라도 라면 누락했다면 해당 레이어에 해당하는 사전을 transceiver.[[Sender]].[[SendEncodings]] 에서 제거한다.

            3. [RFC8853] 에 따라 각 simulcast 레이어의 일시정지 상태를 표시된 대로 갱신하며 해당하는 사전의 active 멤버를 unpaused 인 경우 true, paused 인 경우 false 로 설정한다.

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

          10. directionRTCRtpTransceiverDirection 값으로 두되 이는 media media description 의 방향을 이 피어 관점에서 송수신 방향을 반대로 하여 표현한다. media description 이 거부되었다면 direction 을 "inactive" 로 설정한다.

          11. direction 이 "sendrecv" 또는 "recvonly" 이면, msids 를 그 media description 이 transceiver.[[Receiver]].[[ReceiverTrack]] 과 연관시키려 하는 MSID 들의 리스트로 둔다. 그렇지 않으면 빈 리스트로 둔다.

            Note
            media description 이 거부되었다면 msids 는 여기서 빈 리스트이다.
          12. Process remote trackstransceiver, direction, msids, addList, removeList, trackEventInits 와 함께 수행한다.

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

          14. description 의 타입이 "answer" 또는 "pranswer" 이면 다음 단계를 수행한다:

            1. transceiver.[[Sender]].[[SendCodecs]]description 이 송신용으로 협상하고 현재 에이전트가 송신 가능한 코덱들로 설정한다.

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

            3. transportRTCDtlsTransport 객체로 두되 이는 media media transport 의 RTP/RTCP 컴포넌트를 나타내며 transceiverassociated media description 에 따라 [RFC8843] 로 정해진다.

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

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

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

              Note
              여기 적용되는 [RFC8445] 규칙은:
              • [[IceRole]]unknown 이 아니면 수정하지 않는다.
              • description 이 로컬 offer 이면 controlling 로 설정한다.
              • description 이 원격 offer 이고 a=ice-lite 를 포함하면 [[IceRole]]controlling 으로 설정한다.
              • description 이 원격 offer 이고 a=ice-lite 를 포함하지 않으면 [[IceRole]]controlled 로 설정한다.
              이로써 첫 번째 offer 처리 후 [[IceRole]] 에 항상 값이 존재하게 된다.
          15. media description 이 거부되었고 transceiver.[[Stopped]]false 이면 stop the the RTCRtpTransceiver transceiver.

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

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

        2. connectionset of transceivers 에 있는 각 transceiver 에 대해 다음 단계를 수행한다:

          1. transceiverpendingDescription 설정 이전에 어떤 media description 과도 associated 되지 않았다면, 그것을 비연결 상태로 만들고 transceiver.[[JsepMid]]transceiver.[[Mid]]null 로 설정한다.

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

          3. Candidate Correction 13:Rollback 시 sRD(simulcastOffer)에 의해 덮어쓴 ridless 인코딩 복원 (PR #2797)

            만약 transceiver.[[Sender]].[[LastStableRidlessSendEncodings]]null 이 아니고, transceiver.[[Sender]].[[SendEncodings]] 에 있는 어떤 인코딩이라도 containsrid 멤버를 가진다면 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. msidsidtransceiver.[[Receiver]].[[LastStableStateAssociatedRemoteMediaStreams]] 안의 모든 MediaStream 객체들의 id 리스트 또는 없다면 빈 리스트로 둔다.

            2. 원격 트랙 처리(Process remote tracks)transceiver, transceiver.[[CurrentDirection]], msids, addList, removeListtrackEventInits 와 함께 수행한다.

          7. pendingDescription 이 설정될 때 transceiver 가 생성되었고, addTrack() 를 통해 트랙이 한 번도 연결된 적이 없다면 addTrack(), RTCRtpTransceiver 를 중지(stop the RTCRtpTransceiver) 하고 transceiverconnectiontransceivers 집합(set of transceivers) 에서 제거한다.

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

      12. description 의 타입이 "answer" 이면, 다음 단계를 수행한다:

        1. connectiontransceivers 집합(set of transceivers) 내의 각 transceiver 에 대해 다음 단계를 수행한다:

          1. transceiverstopped 상태이고, m= 섹션에 연결(associated) 되어 있으며, 그 m= 섹션이 connection.[[CurrentLocalDescription]] 또는 connection.[[CurrentRemoteDescription]] 에서 거부되었으면, 그 transceiverconnectiontransceivers 집합(set of transceivers) 에서 제거한다.

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

        1. 이전 단계에서 transceivers 집합(set of transceivers) 에서 제거된 모든 transceiver 에 대해, 그 전송 요소들( transceiver.[[Sender]].[[SenderTransport]] 또는 transceiver.[[Receiver]].[[ReceiverTransport]]) 이 아직 종료되지 않았고, 더 이상 중지되지 않은 다른 트랜시버에 의해 참조되지 않는다면, 해당 RTCDtlsTransport 와 연결된 RTCIceTransport 를 종료한다. 이는 큐에 넣어진 태스크에서 해당 객체들에 이벤트가 발생하도록 한다.

        2. Candidate Addition 49:RTCRtpEncodingParameters 에 codec 추가 (PR #2985)

          connectiontransceivers 집합(set of transceivers) 내 각 transceiver 에 대해:

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

          2. codecs 가 빈 리스트가 아니라면:

            1. transceiver.[[Sender]].[[SendEncodings]] 내의 각 encoding 에 대해, encoding.codeccodecs 의 어떤 항목과도 codec dictionary match 알고리즘 ( ignoreLevelstrue 로 설정 ) 을 사용했을 때 일치하지 않으면 remove encoding.codec.

        3. negotiation-needed 플래그를 지운다(Clear the negotiation-needed flag) 그리고 negotiation-needed 플래그를 갱신한다(update the negotiation-needed flag).

      14. 위에서 connection.[[SignalingState]] 가 변경되었다면, 이름이 signalingstatechange이벤트를 발생(fire an event) 시킨다 connection 에서.

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

      16. muteTracks 내의 각 track 에 대해 음소거 상태를 설정(set the muted state) 하여 그 값을 true 로 둔다.

      17. removeList 내의 각 stream / track 쌍에 대해 트랙 제거(remove the track) 를 수행하여 stream 에서 track 을 제거한다.

      18. addList 내의 각 stream / track 쌍에 대해 트랙 추가(add the track) 를 수행하여 streamtrack 을 추가한다.

      19. trackEventInits 내의 각 entry 에 대해 이름이 track이벤트를 발생(fire an event) 시키되 RTCTrackEvent 인터페이스를 사용하고 그 receiver 속성을 entry.receiver 로 초기화하고, track 속성을 entry.track 으로, streams 속성을 entry.streams 으로, 그리고 transceiver 속성을 entry.transceiver 로 초기화하여 connection 객체에서 발생시킨다.

      20. Resolve pundefined 로 해결한다.

  5. p 를 반환한다.

4.4.1.5 구성 설정하기

configuration으로 구성을 설정(set a configuration)하려면, 다음 단계를 수행한다:

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

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

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

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

    2. index를 0으로 둔다.

    3. indexconfiguration.certificates의 길이보다 작은 동안 다음을 수행한다:

      1. configuration.certificatesindex 위치 값이 표현하는 ECMAScript 객체가 oldConfig.certificates의 동일 index 위치 값이 표현하는 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" DOMExceptionthrow 한다.

    4. urls 안의 각 url에 대해, ICE 서버 URL 유효성 검사 알고리즘을 url에 대해 실행한다.

  7. ICE AgentICE 전송 설정configuration.iceTransportPolicy의 값으로 설정한다. [RFC9429] (섹션 4.1.18.)에 정의된 바와 같이, 새로운 ICE 전송 설정이 기존 설정을 변경하더라도 다음 수집 단계까지 아무 동작도 수행되지 않는다. 스크립트가 이를 즉시 반영하고 싶다면 ICE 재시작을 수행해야 한다.

  8. ICE Agent의 사전 수집된(프리패치된) ICE 후보군 풀 크기[RFC9429] (섹션 3.5.4.섹션 4.1.1.)에 정의된 대로 configuration.iceCandidatePoolSize 값으로 설정한다. 새로운 ICE 후보군 풀 크기가 기존 설정을 변경하면, 이는 즉시 새로운 풀 후보 수집 또는 기존 풀 후보 폐기로 이어질 수 있으며, 이는 [RFC9429] (섹션 4.1.18.)에 정의되어 있다.

  9. ICE AgentICE 서버 목록iceServers로 설정한다.

    [RFC9429] (섹션 4.1.18.)에 정의된 바와 같이, 새로운 서버 목록이 ICE Agent의 기존 ICE 서버 목록을 대체하더라도 다음 수집 단계까지 아무 동작도 수행되지 않는다. 스크립트가 즉시 반영되기를 원하면 ICE 재시작을 해야 한다. 그러나 ICE 후보군 풀 크기가 0이 아니면, 기존 풀 후보는 폐기되고 새 서버에서 새로운 후보가 수집된다.

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

ICE 서버 URL 유효성 검사 url을 수행하려면, 다음 단계를 실행한다:

후보 교정 33: ICE 서버 URL을 파싱하기 위해 url 규격 사용 (PR #2853, PR #2996, PR #2998)
  1. [RFC3986]에 정의된 일반 URI 구문을 사용하여 url을 파싱하고 scheme name을 얻는다. [RFC3986]에 정의된 구문에 따른 파싱이 실패하면 throw 하여 SyntaxError를 던진다. scheme name이 브라우저에서 구현되지 않았다면 throw 하여 NotSupportedError를 던진다. scheme nameturn 또는 turns이고 [RFC7065]에 정의된 구문으로 url을 파싱하는 것이 실패하면 throw 하여 SyntaxError를 던진다. scheme namestun 또는 stuns이고 [RFC7064]에 정의된 구문으로 url을 파싱하는 것이 실패하면 throw 하여 SyntaxError를 던진다.

  2. parsedURLparsingurl의 결과로 둔다.

  3. 다음 조건 중 하나라도 충족하면 throw 하여 "SyntaxError" DOMException을 던진다:

    • parsedURL이 failure인 경우
    • parsedURLscheme"stun", "stuns", "turn", "turns" 중 어느 것도 아닌 경우
    • parsedURLopaque path가 없는 경우
    • parsedURLopaque path에 하나 이상의 "/" 또는 "@"가 포함된 경우
    • parsedURLfragment가 null이 아닌 경우
    • parsedURLscheme"stun" 또는 "stuns"이고, parsedURLquery가 null이 아닌 경우
  4. parsedURLscheme이 사용자 에이전트에서 구현되지 않았다면 throw 하여 NotSupportedError를 던진다.

  5. "https://"parsedURLpath를 연결한 것을 parsing한 결과를 hostAndPortURL로 둔다.

  6. hostAndPortURL이 failure이면 throw 하여 "SyntaxError" DOMException을 던진다.

    hostAndPortURLpath, username, 또는 password가 null이 아니면 throw 하여 "SyntaxError" DOMException을 던진다.

    참고

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

  7. parsedURLquery가 null이 아니고, 그 값이 "transport=udp" 또는 "transport=tcp"와 다르면 throw 하여 "SyntaxError" DOMException을 던진다.

  8. scheme nameparsedURLschemeturn"turn" or turns또는 "turns"이고, server.username 또는 server.credentialare omitted존재하지 않는 경우, throw 하여 InvalidAccessError를 던진다.

  9. scheme nameturn 또는 turns이고 server.credentialType이 "password"이며, server.credentialDOMString이 아니면 throw 하여 InvalidAccessError를 던진다.

4.4.2 인터페이스 정의

이 절에 제시된 RTCPeerConnection 인터페이스는 본 명세 전반에 걸쳐 여러 partial 인터페이스에 의해 확장된다. 특히 RTP Media 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;

  // 레거시 인터페이스 확장
  // 이 절의 메서드 지원은 선택 사항이다.
  // 이러한 메서드가 지원되는 경우
  // 명세된 대로 구현되어야 한다
  // "Legacy Interface Extensions" 절에
  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, 읽기 전용, nullable

localDescription 속성은 반드시(MUST) [[PendingLocalDescription]]null이 아니면 그것을 반환하고, 그렇지 않으면 반드시(MUST) [[CurrentLocalDescription]]을 반환한다.

참고로 [[CurrentLocalDescription]].sdp[[PendingLocalDescription]].sdp는 대응하는 sdp 값(즉, SDP는 파싱 및 재포맷될 수 있고 ICE candidate가 추가될 수 있음)을 setLocalDescription 호출에 전달했을 때의 문자열과 반드시 같을 필요는 없다.

currentLocalDescription 타입 RTCSessionDescription, 읽기 전용, nullable

currentLocalDescription 속성은 반드시(MUST) [[CurrentLocalDescription]]을 반환한다.

이는 RTCPeerConnection이 마지막으로 stable 상태로 전이될 때 성공적으로 협상된 로컬 설명과, 제안(offer) 또는 응답(answer)이 생성된 이후 ICE Agent가 생성한 모든 로컬 candidate를 포함한 것을 나타낸다.

pendingLocalDescription 타입 RTCSessionDescription, 읽기 전용, nullable

pendingLocalDescription 속성은 반드시(MUST) [[PendingLocalDescription]]을 반환한다.

이는 협상 과정에 있는 로컬 설명과, 제안 또는 응답이 생성된 이후 ICE Agent가 생성한 로컬 candidate들을 나타낸다. RTCPeerConnection이 stable 상태이면 값은 null이다.

remoteDescription 타입 RTCSessionDescription, 읽기 전용, nullable

remoteDescription 속성은 반드시(MUST) [[PendingRemoteDescription]]null이 아니면 그것을 반환하고, 그렇지 않으면 반드시(MUST) [[CurrentRemoteDescription]]을 반환한다.

참고로 [[CurrentRemoteDescription]].sdp[[PendingRemoteDescription]].sdp는 대응하는 sdp 값을 setRemoteDescription 호출에 전달했을 때의 문자열과 반드시 동일할 필요는 없다(SDP는 파싱 및 재포맷될 수 있고 ICE candidate가 추가될 수 있음).

currentRemoteDescription 타입 RTCSessionDescription, 읽기 전용, nullable

currentRemoteDescription 속성은 반드시(MUST) [[CurrentRemoteDescription]]을 반환한다.

이는 RTCPeerConnection이 마지막으로 stable 상태로 전이될 때 성공적으로 협상된 최신 원격 설명과, 제안 또는 응답이 생성된 이후 addIceCandidate()를 통해 제공된 원격 candidate들을 포함한 것을 나타낸다.

pendingRemoteDescription 타입 RTCSessionDescription, 읽기 전용, nullable

pendingRemoteDescription 속성은 반드시(MUST) [[PendingRemoteDescription]]을 반환한다.

이는 협상 중인 원격 설명과, 제안 또는 응답이 생성된 후 addIceCandidate()를 통해 제공된 원격 candidate들을 포함한 것을 나타낸다. RTCPeerConnection이 stable 상태이면 값은 null이다.

signalingState 타입 RTCSignalingState, 읽기 전용

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

iceGatheringState 타입 RTCIceGatheringState, 읽기 전용

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

iceConnectionState 타입 RTCIceConnectionState, 읽기 전용

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

connectionState 타입 RTCPeerConnectionState, 읽기 전용

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

canTrickleIceCandidates 타입 boolean, 읽기 전용, nullable

canTrickleIceCandidates 속성은 원격 피어가 트리클 ICE candidate [RFC8838]를 받아들일 수 있는지 여부를 나타낸다. 값은 원격 설명이 트리클 ICE 지원을 표현했는지 여부에 기반하여 결정되며, 이는 [RFC9429] (section 4.1.17.)에 정의되어 있다. 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들의 설명, 이 구현이 지원하는 codec/RTP/RTCP 능력, ICE agent와 DTLS 연결의 매개변수를 포함)들을 담은 RFC 3264 offer가 들어 있는 SDP 블롭을 생성한다. options 매개변수를 제공하여 생성되는 offer에 대한 추가 제어를 할 수 있다.

시스템이 제한된 자원(예: 유한한 수의 디코더)을 가진 경우 createOffer는 시스템의 현재 상태를 반영하는 offer를 반환해야 하므로 setLocalDescription이 해당 자원을 획득하려 할 때 성공할 수 있다. 세션 기술들은 반환된 프로미스의 이행(fulfillment) 콜백이 끝날 때까지 최소한 오류 없이 setLocalDescription에 의해 사용 가능해야 한다.

SDP 생성은 [RFC9429]에 기술된 offer 생성 절차를 따라야 하며, 단 사용자 에이전트는 이 경우 RFC9429 목적상 stopping 상태의 트랜시버를 stopped로 간주해야 한다(MUST).

Offer로서 생성된 SDP에는 세션이 지원하거나 선호하는 모든 codec/RTP/RTCP 능력(Answer는 협상된 하위 집합만 포함) 전체가 들어간다. 세션이 이미 설정된 후 createOffer가 호출되면 createOffer는 현재 세션과 호환되는 offer를 생성하며, 지난 완전한 offer-answer 교환 이후의 변경(트랙 추가/제거 등)을 반영한다. 변경이 없으면, offer는 현재 로컬 설명의 능력과 함께 업데이트된 offer에서 협상될 수 있는 추가 능력을 포함한다.

생성된 SDP에는 또한 ICE agentusernameFragment, password 및 ICE 옵션([RFC5245] 섹션 14에 정의됨)이 포함되며, 이미 수집된 로컬 candidate가 포함될 수도 있다.

certificates 값은 configuration에서 애플리케이션이 RTCPeerConnection에 대해 구성한 인증서를 제공한다. 이 인증서들과 기본 인증서들은 인증서 지문 집합을 생성하는 데 사용되며, 이러한 지문은 SDP 구성에 사용된다.

SDP 생성 과정은 기기에서 일반적으로 지속적인 교차 출처 정보를 제공하는 기저 시스템의 일부 미디어 능력을 노출하므로 애플리케이션의 지문(fingerprinting) 표면을 증가시킨다. 개인정보 민감 맥락에서 브라우저는 공통 하위 능력만 일치하는 SDP 생성과 같은 완화책을 고려할 수 있다. (This is a fingerprinting vector.)

메서드가 호출되면, 사용자 에이전트는 다음 단계를 반드시(MUST) 수행한다:

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

  2. 만약 connection.[[IsClosed]]true이면, 새로 거부(rejected)된, 새로 생성된 InvalidStateError로 이행하는 프로미스를 반환한다.

  3. chain 결과( create an offerconnection으로 실행한 결과 )를 connectionoperations chain에 연결한 결과를 반환한다.

connection이 주어졌을 때 offer 생성(create an offer)을 수행하려면 다음 단계를 실행한다:

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

  2. p를 새로운 프로미스로 둔다.

  3. 병렬로(In parallel), offer 생성 병렬 단계connectionp와 함께 시작한다.

  4. p를 반환한다.

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

  1. connection이 인증서 집합으로 생성되지 않았고 아직 생성된 것이 없다면, 생성 완료를 기다린다.

  2. 제안자 시스템 상태(offerer's system state)를 점검하여 offer 생성에 필요한 현재 이용 가능한 자원을 [RFC9429] (섹션 4.1.8.)에 따라 결정한다.

  3. 이 점검이 어떤 이유로든 실패하면, 거부하여 p를 새로 생성된 OperationError로 거부하고 이 단계를 중단한다.

  4. connectionp를 사용하여 offer 생성 최종 단계를 실행하는 태스크를 큐에 넣는다.

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

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

  2. 만약 connection이 추가 점검이 필요한 방식으로 수정되었다면 (즉, 제안자 시스템 상태의 추가 점검 필요), 병렬로 offer 생성 병렬 단계connectionp와 함께 다시 시작하고 이 단계를 중단한다.

    참고
    예를 들어 오직 오디오 RTCRtpTransceiverconnection에 추가된 상태에서 createOffer가 호출되었는데, offer 생성 병렬 단계를 수행하는 동안 비디오 RTCRtpTransceiver가 추가되어 비디오 시스템 자원에 대한 추가 점검이 필요한 경우가 이에 해당한다.
  3. 이전 점검에서 얻은 정보, connection의 현재 상태 및 그 RTCRtpTransceiver들의 상태를 바탕으로 [RFC9429] (섹션 5.2.)에 따라 SDP offer sdpString을 생성한다.

    1. [RFC8843] (섹션 7)에 설명된 대로, 번들링( RTCBundlePolicy 참조 )이 사용되면 BUNDLE 그룹을 협상하기 위해 offerer가 태그된 m= 섹션을 선택해야 한다. 사용자 에이전트는 트랜시버 집합에서 첫 번째 중지되지 않은(non-stopped) 트랜시버에 대응하는 m= 섹션을 offerer 태그된 m= 섹션으로 반드시(MUST) 선택한다. 이는 원격 엔드포인트가 SDP를 파싱하지 않고도 어떤 트랜시버가 offerer 태그된 m= 섹션인지 예측 가능하게 한다.

    2. filteredCodecstransceiver.[[PreferredCodecs]]에 다음 필터를 적용한 결과로 둔다. 필터링은 codec 선호 순서를 변경해서는 안 된다 (MUST NOT):

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

      2. 만약 transceiver.direction이 "sendonly" 또는 "sendrecv"이면, kind에 대한 구현된 송신 코덱 목록에 포함되지 않은 코덱을 모두 제외한다. 이때 codec dictionary match 알고리즘을 ignoreLevelstrue로 설정하여 사용한다.

      3. 만약 transceiver.direction이 "recvonly" 또는 "sendrecv"이면, kind에 대한 구현된 수신 코덱 목록에 포함되지 않은 코덱을 모두 제외한다. 이때 codec dictionary match 알고리즘을 ignoreLevelstrue로 설정하여 사용한다.

      미디어 설명(media description)연관된(associated) 트랜시버 transceivercodec preferencesfilteredCodecs가 비어 있지 않으면 그 값이며, 그렇지 않으면 설정되지 않은(unset) 것으로 본다.

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

      참고

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

  4. offer를 새로 생성된 RTCSessionDescriptionInit 사전(dictionary)으로 두고, 그 type 멤버를 문자열 "offer"로, sdp 멤버를 sdpString으로 초기화한다.

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

  6. Resolve p with offer.

createAnswer

createAnswer 메서드는 원격 구성의 매개변수와 호환되며 세션에 대해 지원되는 구성을 담은 [SDP] answer를 생성한다. createOffer와 마찬가지로, 반환되는 SDP 블롭에는 이 RTCPeerConnection에 부착된 로컬 MediaStreamTrack들의 설명, 이 세션에 대해 협상된 codec/RTP/RTCP 옵션, 그리고 ICE Agent가 수집한 모든 candidate가 포함된다. options 매개변수는 생성되는 answer에 대한 추가 제어를 제공하기 위해 전달될 수 있다.

createOffer와 마찬가지로, 반환된 description은 시스템의 현재 상태를 반영하는 것이 권장된다(SHOULD). 세션 description은 반환된 promise의 fulfillment 콜백이 끝날 때까지 setLocalDescription에 의해 오류 없이 사용 가능해야 한다(MUST).

Answer로서, 생성된 SDP는 해당 offer와 함께 미디어 평면을 어떻게 설정해야 하는지 지정하는 특정 codec/RTP/RTCP 구성을 포함한다. SDP 생성은 [RFC9429]에 기술된 answer 생성 절차를 반드시(MUST) 따른다.

생성된 SDP에는 또한 ICE agentusernameFragment, password 및 ICE 옵션([RFC5245] 섹션 14에 정의됨)이 포함되며, 에이전트가 수집한 로컬 candidate가 포함될 수도 있다.

certificates 값은 configuration에서 RTCPeerConnection에 대해 애플리케이션이 구성한 인증서를 제공한다. 이 인증서들은 기본 인증서들과 함께 인증서 지문 집합을 생성하는 데 사용되며, 이러한 지문은 SDP 구성에 사용된다.

Answer는 [RFC9429] (section 4.1.10.1.)에 기술된 대로 type을 "pranswer"로 설정하여 임시(provisional)로 표시할 수 있다.

메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시(MUST) 수행한다:

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

  2. 만약 connection.[[IsClosed]]true이면, 새로 거부(rejected)된, 새로 생성된 InvalidStateError로 이행하는 promise를 반환한다.

  3. chaining 결과( creating an answerconnection으로 수행한 결과 )를 connectionoperations chain에 연결한 결과를 반환한다.

connection이 주어졌을 때 answer 생성(create an answer)을 수행하려면 다음 단계를 실행한다:

  1. 만약 connection.[[SignalingState]]가 "have-remote-offer"도 "have-local-pranswer"도 아니면, 새로 거부된 새로 생성된 InvalidStateError로 promise를 반환한다.

  2. p를 새로운 promise로 둔다.

  3. 병렬로(In parallel), answer 생성 병렬 단계connectionp와 함께 시작한다.

  4. p를 반환한다.

connection과 promise p가 주어졌을 때 answer 생성 병렬 단계는 다음과 같다:

  1. connection이 인증서 집합으로 생성되지 않았고 아직 생성되지 않았다면, 생성이 완료될 때까지 기다린다.

  2. answerer의 시스템 상태(answerer's system state)를 점검하여 answer 생성에 필요한 현재 이용 가능한 자원을 [RFC9429] (section 4.1.9.)에 따라 결정한다.

  3. 이 점검이 어떤 이유로든 실패하면 reject하여 p를 새로 생성된 OperationError로 거부하고 단계를 중단한다.

  4. p에 대해 answer 생성 최종 단계를 실행하는 태스크를 큐에 넣는다.

promise p가 주어졌을 때 answer 생성 최종 단계는 다음과 같다:

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

  2. 만약 connectionanswerer의 시스템 상태에 대한 추가 점검이 필요하도록 수정되었다면, 병렬로 answer 생성 병렬 단계connectionp와 함께 다시 시작하고 단계를 중단한다.

    Note
    예를 들어 createAnswer가 어떤 RTCRtpTransceiver의 direction이 "recvonly"일 때 호출되었지만, answer 생성 병렬 단계를 수행하는 동안 direction이 "sendrecv"로 변경되어 비디오 인코딩 자원 추가 점검이 필요한 경우가 이에 해당한다.
  3. 이전 점검에서 얻은 정보와 connection 및 그 RTCRtpTransceiver들의 현재 상태를 바탕으로 [RFC9429] (section 5.3.)에 따라 SDP answer sdpString을 생성한다.

    Candidate Correction 26:createAnswer()의 encodings 및 sLD(answer)에서 SendEncodings 가지치기. (PR #2801)
    Candidate Correction 27:RID의 쉼표 구분 대안을 무시. (PR #2813)
    1. m= 섹션의 연관된 트랜시버의 codec preferences는 아래 필터를 적용한 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에 포함되지 않은 코덱을 제외한다.

      필터링은 codec 선호 순서를 변경해서는 안 된다(MUST NOT).

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

    3. filteredCodecstransceiver.[[PreferredCodecs]]에 다음 필터를 적용한 결과로 둔다. 필터링은 codec 선호 순서를 변경해서는 안 된다(MUST NOT):

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

      2. 만약 transceiver.direction이 "sendonly" 또는 "sendrecv"이면, kind에 대한 list of implemented send codecs에 포함되지 않은 코덱을 제외한다. 이때 codec dictionary match 알고리즘을 ignoreLevelstrue로 설정하여 사용한다.

      3. 만약 transceiver.direction이 "recvonly" 또는 "sendrecv"이면, kind에 대한 list of implemented receive codecs에 포함되지 않은 코덱을 제외한다. 이때 codec dictionary match 알고리즘을 ignoreLevelstrue로 설정하여 사용한다.

      media descriptionassociated 트랜시버 transceivercodec preferencesfilteredCodecs가 비어 있지 않으면 그 값이며, 비어 있으면 설정되지 않은 것으로 본다.

    4. 이것이 simulcast 수신 제안에 대한 answer라면, simulcast 수신을 요청하는 각 미디어 섹션에 대해 다음 단계를 수행한다:

      1. a=simulcast 속성이 RID에 대해 쉼표로 구분된 대안을 포함한다면 첫 번째 것만 남기고 제거한다.

      2. a=simulcast 속성에 동일한 이름의 RID가 여러 개 있으면 첫 번째 것만 남기고 제거한다. RID 제한은 설정하지 않는다.

      3. Answer의 미디어 섹션에서 해당 트랜시버의 [[Sender]].[[SendEncodings]]에 존재하지 않는 RID는 제외한다.

      Note

      setRemoteDescription(offer)가 sender의 proposed envelope을 확립하면, sender의 [[SendEncodings]]는 "have-remote-offer"에서 갱신되어 롤백에 노출된다. 그러나 일단 sender에 대해 simulcast envelope이 확립되면, 이후 sender의 [[SendEncodings]] 가지치기는 이 answer가 setLocalDescription으로 설정될 때 발생한다.

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

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

  6. Resolve p with answer.

setLocalDescription

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

이 API는 로컬 미디어 상태를 변경한다. 애플리케이션이 한 미디어 포맷에서 호환되지 않는 다른 포맷으로 변경을 제안하려는 상황을 성공적으로 처리하기 위해, RTCPeerConnectionMUST (반드시) 최종 answer를 받을 때까지 현재 및 보류(pending) 로컬 description 둘 다의 사용을 동시에 지원할 수 있어야 하며 (예: 두 description 모두에 존재하는 코덱 지원), 그 시점에서 RTCPeerConnection은 보류 중인 로컬 description을 완전히 채택하거나, 원격 측이 변경을 거부한 경우 현재 description으로 롤백할 수 있다.

description 인수는 선택 사항이다. 생략된 경우 setLocalDescription은 필요에 따라 암묵적으로 offer를 생성하거나 answer를 생성한다. [RFC9429] (section 5.4.)에 언급된 바와 같이, SDP를 포함한 description이 전달되면 그 SDP는 createOffer 또는 createAnswer에서 반환되었을 때와 변경되어서는 안 된다.

메서드가 호출되면 사용자 에이전트는 다음 단계를 MUST (반드시) 수행한다:

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

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

  3. sdpdescription.sdp로 둔다.

  4. 다음 단계를 chain하여 connectionoperations chain에 연결한 결과를 반환한다:

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

    2. type이 "offer"이고 sdp가 빈 문자열이 아니며 connection.[[LastCreatedOffer]]와 동일하지 않으면, 새로 rejected된 새로 created InvalidModificationError로 프로미스를 반환하고 단계를 중단한다.

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

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

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

      2. sdp가 여전히 빈 문자열이거나 더 이상 connectionofferer 시스템 상태를 정확히 나타내지 않으면, poffer 생성 결과로 두고, reactingp에 대해 수행하여, 첫 번째 인수가 가리키는 로컬 세션 description을 설정하는 fulfillment 단계를 가진 결과를 반환한다.

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

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

      2. sdp가 여전히 빈 문자열이거나 더 이상 connectionanswerer 시스템 상태를 정확히 나타내지 않으면, panswer 생성 결과로 두고 reactingp에 대해 다음 fulfillment 단계로 수행한 결과를 반환한다:

        1. answer를 이 fulfillment 단계들의 첫 번째 인수로 둔다.

        2. {type, answer.sdp}가 가리키는 로컬 세션 description을 설정한 결과를 반환한다.

    6. {type, sdp}가 가리키는 로컬 세션 description을 설정한 결과를 반환한다.

Note

[RFC9429] (section 5.9.)에 언급된 바와 같이, 이 메서드를 호출하면 ICE Agent에 의한 ICE candidate 수집 절차가 트리거될 수 있다.

setRemoteDescription

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

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

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

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

  3. 다음 단계를 chaining하여 connectionoperations chain에 연결한 결과를 반환한다:

    1. 만약 description.type이 "offer"이고, [RFC9429] (section 5.5.section 5.6.)에 기술된 현재 connection.[[SignalingState]]에 대해 유효하지 않다면, 다음 하위 단계를 수행한다:

      1. pset the local session description (로컬 세션 description 설정) 알고리즘을 {type: "rollback"} 인자로 실행한 결과로 둔다.

      2. p에 대해 reacting을 수행하여 이행(fulfillment) 단계에서 원격 세션 description을 설정 하고 description을 적용한 결과를 반환하며, 이 단계를 중단한다.

    2. set the remote session description 알고리즘을 description에 대해 실행한 결과를 반환한다.

addIceCandidate

addIceCandidate 메서드는 원격 candidate를 ICE Agent에 제공한다. 이 메서드는 candidate 멤버에 빈 문자열을 전달하여 원격 candidate의 종료(end-of-candidates)를 알리는 데도 사용할 수 있다. 이 메서드가 사용하는 인수의 멤버는 candidate, sdpMid, sdpMLineIndex, 그리고 usernameFragment 뿐이며, 나머지는 무시된다. 메서드가 호출되면 사용자 에이전트는 다음 단계를 MUST 수행한다:

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

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

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

  4. 다음 단계를 chaining하여 connectionoperations chain에 연결한 결과를 반환한다:

    1. remoteDescriptionnull이면 새로 rejected된 새로 created InvalidStateError로 프로미스를 반환한다.

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

      1. 만약 candidate.sdpMidremoteDescription의 어떤 미디어 설명의 mid와도 같지 않다면, 새로 rejected된 새로 created OperationError로 프로미스를 반환한다.

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

      1. 만약 candidate.sdpMLineIndexremoteDescription의 미디어 설명 수보다 크거나 같다면, 새로 rejected된 새로 created OperationError로 프로미스를 반환한다.

    4. candidate.sdpMid 또는 candidate.sdpMLineIndex가 가리키는 remoteDescription의 미디어 설명에 연관된 트랜시버가 stopped이면 resolvedundefined 프로미스를 반환한다.

    5. candidate.usernameFragmentnull이 아니고 적용된 원격 미디어 description의 해당 항목들 중 어떤 username fragment와도 같지 않다면, 새로 rejected된 새로 created OperationError로 프로미스를 반환한다.

    6. p를 새로운 프로미스로 둔다.

    7. In parallel, candidate가 administratively prohibited (관리적으로 금지) 상태가 아니라면 [RFC9429] (section 4.1.19.)에 따라 ICE candidate candidate를 추가한다. ICE generation을 식별하기 위해 candidate.usernameFragment를 사용한다; 만약 usernameFragmentnull이면 가장 최근 ICE generation에 대해 candidate를 처리한다.

      만약 candidate.candidate가 빈 문자열이면 해당 candidate를 해당 media description 및 ICE candidate generation에 대한 end-of-candidates 표시로 처리한다. candidate.sdpMidcandidate.sdpMLineIndex가 모두 null이면 이 end-of-candidates 표시는 모든 media description에 적용된다.

      1. candidate를 성공적으로 추가할 수 없었다면 사용자 에이전트는 다음 단계를 실행하는 태스크를 MUST 큐에 넣는다:

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

        2. Reject p를 새로 created OperationError로 거부하고 단계를 중단한다.

      2. candidate가 성공적으로 적용되었거나 candidate가 administratively prohibited였다면, 사용자 에이전트는 다음 단계를 실행하는 태스크를 MUST 큐에 넣는다:

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

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

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

        4. Resolve pundefined로 이행시킨다.

    8. p를 반환한다.

candidate는 사용자 에이전트가 해당 주소로의 연결 시도를 허용하지 않기로 결정한 경우 administratively prohibited (관리적으로 금지됨)이다.

개인정보 보호상의 이유로, 주소/포트가 차단되었는지 여부에 대해 개발자에게 어떤 표시도 제공되지 않으며, 이는 해당 주소에서 응답이 없는 것과 정확히 동일하게 동작한다.

UA는 [Fetch] block bad port 목록에 있는 주소로의 연결을 MUST (반드시) 금지하고, 그 외 다른 주소에 대한 연결을 금지하도록 선택(MAY)할 수 있다.

iceTransportPolicy 멤버가 relayRTCConfiguration의 경우, mDNS candidate 및 DNS candidate처럼 외부 해석이 필요한 후보들은 MUST (반드시) 금지되어야 한다.

Note

WebIDL 처리로 인해 addIceCandidate(null) 호출은 기본(dictionary 기본값) 사전이 존재하는 호출로 해석되며, 위 알고리즘에서는 모든 미디어 설명과 ICE candidate generation에 대한 end-of-candidates 표시를 의미한다. 이는 레거시 이유로 의도된 동작이다.

restartIce

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

이 메서드가 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행한다:

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

  2. connection.[[LocalIceCredentialsToReplace]] 을 비우고, connection.[[CurrentLocalDescription]] 에 존재하는 모든 ICE 자격 증명(섹션 15.4 [RFC5245] 에 정의된 ice-ufrag 및 ice-pwd)과 connection.[[PendingLocalDescription]] 에 있는 모든 ICE 자격 증명을 추가한다.

  3. connection 에 대해 negotiation-needed 플래그를 갱신한다.

getConfiguration

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

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

setConfiguration

setConfiguration 메서드는 이 RTCPeerConnection 객체의 구성을 갱신한다. 여기에는 ICE Agent 구성 변경이 포함된다. [RFC9429] (section 3.5.1.)에 언급된 대로, ICE 구성이 새로운 gathering phase가 필요한 방식으로 변경되면 ICE 재시작이 필요하다.

setConfiguration 메서드가 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행한다:

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

  2. 만약 connection.[[IsClosed]]true 이라면, throw 하여 InvalidStateError 를 던진다.

  3. Set the configuration 단계를 configuration 으로 수행한다.

close

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

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

  2. close the connection 알고리즘을 connection 과 값 false 로 수행한다.

connectiondisappear 불리언이 주어졌을 때 close the connection 알고리즘은 다음과 같다:

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

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

  3. connection.[[SignalingState]] 를 "closed" 로 설정한다. 이벤트는 발생하지 않는다.

  4. CollectTransceivers 알고리즘을 실행한 결과를 transceivers 로 둔다. transceivers 안의 각 RTCRtpTransceiver transceiver 에 대해 다음을 수행한다:

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

    2. Stop the RTCRtpTransceiver 알고리즘을 transceiverdisappear 로 수행한다.

  5. connectionRTCDataChannel[[ReadyState]] 슬롯을 "closed" 로 설정한다.

    Note
    RTCDataChannel 은 즉시 종료되며 표준 종료 절차는 호출되지 않는다.
  6. 만약 connection.[[SctpTransport]]null 이 아니면, SCTP ABORT chunk 를 보내 기저 SCTP 연결을 종료하고 [[SctpTransportState]] 를 "closed" 로 설정한다.

  7. connectionRTCDtlsTransport[[DtlsTransportState]] 슬롯을 "closed" 로 설정한다.

  8. connectionICE Agent 를 파기(destroy)하여, 모든 활성 ICE 처리 과정을 즉시 종료하고 관련 자원(예: TURN permissions)을 해제한다.

  9. connectionRTCIceTransport[[IceTransportState]] 슬롯을 "closed" 로 설정한다.

  10. connection.[[IceConnectionState]] 를 "closed" 로 설정한다. 이벤트는 발생하지 않는다.

  11. connection.[[ConnectionState]] 를 "closed" 로 설정한다. 이벤트는 발생하지 않는다.

4.4.3 레거시 인터페이스 확장

참고
이들 메서드의 IDL 정의는 오버로드된 함수는 partial 인터페이스에서 정의될 수 없기 때문에 RTCPeerConnection 인터페이스의 본문 정의에 문서화되어 있다.

이 절의 메서드 지원은 선택 사항이다. 그러나 지원한다면 여기에 명시된 대로 구현하는 것이 필수이다.

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

createOffer 메서드가 호출되면 사용자 에이전트는 다음 단계를 MUST 수행한다:

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

  2. failureCallback 을 메서드 두 번째 인수가 가리키는 콜백으로 둔다.

  3. options 를 메서드 세 번째 인수가 가리키는 콜백(옵션 객체)으로 둔다.

  4. RTCPeerConnectioncreateOffer() 메서드를 options 단일 인수로 실행하고, 결과 프로미스를 p 로 둔다.

  5. p이행되어 값 offer 를 얻으면 successCallbackoffer 인수로 호출한다.

  6. p 가 이유 r거부되면 failureCallbackr 인수로 호출한다.

  7. undefined해결된 프로미스를 반환한다.

setLocalDescription

setLocalDescription 메서드가 호출되면 사용자 에이전트는 다음 단계를 MUST 수행한다:

  1. description 을 첫 번째 인수로 둔다.

  2. successCallback 을 두 번째 인수가 가리키는 콜백으로 둔다.

  3. failureCallback 을 세 번째 인수가 가리키는 콜백으로 둔다.

  4. RTCPeerConnectionsetLocalDescription 메서드를 description 단일 인수로 실행하고 결과 프로미스를 p 로 둔다.

  5. p이행되면 successCallbackundefined 인수로 호출한다.

  6. p 가 이유 r거부되면 failureCallbackr 인수로 호출한다.

  7. undefined해결된 프로미스를 반환한다.

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

createAnswer 메서드가 호출되면 사용자 에이전트는 다음 단계를 MUST 수행한다:

  1. successCallback 을 첫 번째 인수로 둔다.

  2. failureCallback 을 두 번째 인수가 가리키는 콜백으로 둔다.

  3. RTCPeerConnectioncreateAnswer() 메서드를 인수 없이 실행하고 결과 프로미스를 p 로 둔다.

  4. p이행되어 값 answer 를 얻으면 successCallbackanswer 인수로 호출한다.

  5. p 가 이유 r거부되면 failureCallbackr 인수로 호출한다.

  6. undefined해결된 프로미스를 반환한다.

setRemoteDescription

setRemoteDescription 메서드가 호출되면 사용자 에이전트는 다음 단계를 MUST 수행한다:

  1. description 을 첫 번째 인수로 둔다.

  2. successCallback 을 두 번째 인수가 가리키는 콜백으로 둔다.

  3. failureCallback 을 세 번째 인수가 가리키는 콜백으로 둔다.

  4. RTCPeerConnectionsetRemoteDescription 메서드를 description 단일 인수로 실행하고 결과 프로미스를 p 로 둔다.

  5. p이행되면 successCallbackundefined 인수로 호출한다.

  6. p 가 이유 r거부되면 failureCallbackr 인수로 호출한다.

  7. undefined해결된 프로미스를 반환한다.

addIceCandidate

addIceCandidate 메서드가 호출되면 사용자 에이전트는 다음 단계를 MUST 수행한다:

  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 에 추가된 미디어 외에도 offer 생성 방식을 영향 줄 수 있는 레거시 확장 집합을 설명한다. 개발자에게는 대신 RTCRtpTransceiver API 사용이 권장된다.

createOffer 가 본 절에 명시된 레거시 옵션 중 하나라도 포함하여 호출되면, 일반적인 createOffer 단계 대신 다음 단계를 수행한다:

  1. options 를 메서드의 첫 번째 인수로 둔다.

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

  3. options 내 각 offerToReceive<Kind> 멤버(종류 kind)에 대해 다음 단계를 수행한다:

    1. 사전 멤버 값이 false 인 경우,
      1. 트랜시버 종류 kind 의 중지되지 않은(non-stopped) "sendrecv" 트랜시버 각각에 대해 transceiver.[[Direction]] 을 "sendonly" 로 설정한다.

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

      (해당될 경우) 다음 옵션으로 계속한다.

    2. connection 이 "sendrecv" 또는 "recvonly" 상태의 중지되지 않은 트랜시버 종류 kind 트랜시버를 하나라도 갖는다면 다음 옵션으로 (있다면) 계속한다.

    3. transceiverconnection.addTransceiver(kind) 와 동등한 호출의 결과로 두되, 이 연산은 MUST NOT (해서는 안 된다) negotiation-needed 플래그를 갱신해서는 안 된다.

    4. 이전 연산이 오류를 던져 transceiver 가 설정되지 않았다면 이 단계를 중단한다.

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

  4. Offer를 생성하기 위해 createOffer 에 명시된 단계를 실행한다.

WebIDLpartial dictionary RTCOfferOptions {
  boolean offerToReceiveAudio;
  boolean offerToReceiveVideo;
};
속성
offerToReceiveAudio 타입 boolean

오디오 방향성에 대한 추가 제어를 제공한다. 예를 들어 오디오가 송신되지 않더라도 오디오 수신이 가능하도록 보장하는 데 사용할 수 있다.

offerToReceiveVideo 타입 boolean

비디오 방향성에 대한 추가 제어를 제공한다. 예를 들어 비디오가 송신되지 않더라도 비디오 수신이 가능하도록 보장하는 데 사용할 수 있다.

4.4.4 가비지 컬렉션

어떤 RTCPeerConnection 객체는 그 객체에서 이벤트 핸들러를 트리거할 수 있는 이벤트가 하나라도 존재하는 한 가비지 컬렉션되어서는 안 된다(MUST NOT). 객체의 [[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

"offer" 값의 RTCSdpType 은 해당 description 이 [SDP] offer 로 반드시(MUST) 처리되어야 함을 나타낸다.

pranswer

"pranswer" 값의 RTCSdpType 은 description 이 [SDP] answer 로 반드시(MUST) 처리되어야 하지만 최종 answer 는 아님을 나타낸다. SDP pranswer 로 사용되는 description 은 SDP offer 에 대한 응답이거나 이전에 전송된 SDP pranswer 의 갱신으로 적용될 수 있다.

answer

"answer" 값의 RTCSdpType 은 description 이 [SDP] 최종 answer 로 반드시(MUST) 처리되어야 하며 offer-answer 교환이 완료되었다고 반드시(MUST) 간주되어야 함을 나타낸다. SDP answer 로 사용되는 description 은 SDP offer 에 대한 응답이거나 이전에 전송된 SDP pranswer 의 갱신으로 적용될 수 있다.

rollback

"rollback" 값의 RTCSdpType 은 description 이 현재 SDP 협상을 취소하고 SDP [SDP] offer 를 이전 안정(stable) 상태였던 것으로 되돌리는 것으로 반드시(MUST) 처리되어야 함을 나타낸다. 이전 안정 상태에서의 로컬 또는 원격 SDP description 은 아직 성공적인 offer-answer 협상이 없었다면 null 일 수 있다. "answer" 또는 "pranswer" 는 롤백될 수 없다.

4.6.2 RTCSessionDescription 클래스

RTCSessionDescription 클래스는 RTCPeerConnection 이 로컬 및 원격 세션 description 을 노출하는 데 사용된다.

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

RTCSessionDescription() 생성자는 사전 인수 description 을 받아 그 내용을 사용해 새로운 RTCSessionDescription 객체를 초기화한다. 이 생성자는 더 이상 사용이 권장되지 않으며(Deprecated) 오직 레거시 호환성 목적만을 위해 존재한다.

속성
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
이 description 의 유형. 존재하지 않는 경우 setLocalDescriptionRTCPeerConnection[[SignalingState]] 를 기반으로 유형을 추론한다.
sdp 타입 DOMString
SDP [SDP] 의 문자열 표현; 만약 type 이 "rollback" 이면 이 멤버는 사용되지 않는다.

4.7 세션 협상 모델

RTCPeerConnection 의 상태에 대한 많은 변경은 원하는 효과를 얻기 위해 시그널링 채널을 통한 원격 측과의 통신을 필요로 한다. 애플리케이션은 negotiationneeded 이벤트를 수신함으로써 언제 시그널링을 수행해야 하는지 알 수 있다. 이 이벤트는 연결의 협상이 필요한 플래그(negotiation-needed flag) 상태에 따라 발생하며, 이는 [[NegotiationNeeded]] 내부 슬롯으로 표현된다.

4.7.1 협상 필요 상태 설정

이 절은 비규범적이다.

시그널링을 필요로 하는 연산이 RTCPeerConnection 에 대해 수행되면 그 연결은 협상이 필요함으로 표시된다. 이러한 연산의 예로는 RTCRtpTransceiver 를 추가하거나 중지하는 것, 혹은 첫 번째 RTCDataChannel 을 추가하는 것이 있다.

구현 내부의 변화 또한 연결이 협상 필요로 표시되는 결과를 낳을 수 있다.

협상이 필요한 플래그를 업데이트하는 정확한 절차는 아래에 명시되어 있음을 유의한다.

4.7.2 협상 필요 상태 해제

이 절은 비규범적이다.

협상이 필요한 플래그 는 "answer" 유형의 세션 설명이 성공적으로 설정(set)되고, 제공된 description 이 현재 존재하는 RTCRtpTransceiverRTCDataChannel 들의 상태와 일치할 때 해제된다. 구체적으로 이는 모든 stopped 가 아닌 트랜시버가 로컬 description 내에서 속성이 일치하는 연결(associated)된 섹션을 가지고 있고, 데이터 채널이 하나라도 생성되었다면 로컬 description 에 데이터 섹션이 존재함을 의미한다.

협상이 필요한 플래그를 업데이트하는 정확한 절차는 아래에 명시되어 있음을 유의한다.

4.7.3 협상 필요 플래그 업데이트

아래 과정은 본 문서의 다른 위치에서 참조되는 곳에서 발생한다. 또한 협상에 영향을 미치는 구현 내부 변화의 결과로 발생할 수도 있다. 그러한 변화가 발생하면 사용자 에이전트는 MUST 협상이 필요한 플래그를 업데이트해야 한다.

connection 에 대해 협상이 필요한 플래그를 업데이트하려면 다음 단계를 수행한다:

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

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

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

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

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

      Note

      협상이 필요한 플래그 는 상태가 "stable" 로 전이할 때 세션 설명 설정 단계의 일부로 업데이트된다.

    4. 협상이 필요한지 확인 결과가 false 이면 협상이 필요한 플래그를 해제하기 위해 connection.[[NegotiationNeeded]]false 로 설정하고 이 단계를 중단한다.

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

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

    7. 이벤트를 발행(Fire an event)하며 이름은 negotiationneeded 이고 대상은 connection 이다.

    Note

    태스크 큐잉은 흔히 여러 변경을 한 번에 connection 에 수행하는 상황에서 negotiationneeded 가 너무 일찍 발생하는 것을 방지한다.

    추가로, operations chain 이 비어 있을 때만 negotiationneeded 를 발생시키므로 협상 관련 메서드와 경합(race)하지 않는다.

connection 에 대해 협상이 필요한지 확인하려면 다음 검사를 수행한다:

  1. 앞단에서 설명된 대로 구현 특화 협상이 필요한 경우 true 를 반환한다.

  2. connection.[[LocalIceCredentialsToReplace]] 가 비어 있지 않으면 true 를 반환한다.

  3. descriptionconnection.[[CurrentLocalDescription]] 로 둔다.

  4. connection 이 하나라도 RTCDataChannel 을 생성했으며 description 의 어떤 m= 섹션도 아직 데이터용으로 협상되지 않았다면 true 를 반환한다.

  5. connection트랜시버 집합 내 각 transceiver 에 대해 다음 검사를 수행한다:

    1. transceiver.[[Stopping]]true 이고 transceiver.[[Stopped]]false 이면 true 를 반환한다.

    2. transceiverstopped 상태가 아니고 아직 description 의 m= 섹션과 연결(associated)되어 있지 않으면 true 를 반환한다.

    3. transceiverstopped 가 아니고 description 의 m= 섹션과 연결되어 있다면 다음 검사를 수행한다:

      1. transceiver.[[Direction]] 이 "sendrecv" 혹은 "sendonly" 이고, description 내 연결된 m= 섹션이 단일 a=msid 라인을 포함하지 않거나, 이 m= 섹션의 a=msid 라인들로부터 얻은 MSID 개수 또는 MSID 값 자체가 transceiver.sender.[[AssociatedMediaStreamIds]] 와 다르면 true 를 반환한다.

      2. description 이 "offer" 타입이고, 연결된 m= 섹션의 방향이 connection.[[CurrentLocalDescription]]connection.[[CurrentRemoteDescription]]transceiver.[[Direction]] 과 일치하지 않으면 true 를 반환한다. 이 단계에서 [[CurrentRemoteDescription]] 에서 찾은 방향과 비교할 때에는 상대 피어 관점을 나타내도록 방향을 반전해야 한다.

      3. description 이 "answer" 타입이고, description 내 연결된 m= 섹션의 방향이 transceiver.[[Direction]] 와 ( [RFC9429] (section 5.3.1.) 에 설명된 ) 제공된 방향과의 교집합 결과가 일치하지 않으면 true 를 반환한다.

    4. transceiverstopped 이고 m= 섹션과 연결되어 있지만, 그 연결된 m= 섹션이 아직 connection.[[CurrentLocalDescription]] 또는 connection.[[CurrentRemoteDescription]] 에서 거부(rejected)되지 않았다면 true 를 반환한다.

  6. 위의 모든 검사를 수행했고 true 가 반환되지 않았다면 더 협상할 사항이 없으므로 false 를 반환한다.

4.8 대화형 연결 설정(ICE)을 위한 인터페이스

4.8.1 RTCIceCandidate 인터페이스

이 인터페이스는 [RFC5245] 2절에 기술된 ICE candidate를 설명한다. candidate, sdpMid, sdpMLineIndex, 그리고 usernameFragment 를 제외한 나머지 속성들은 (잘 형성된 경우) candidateInitDictcandidate 멤버를 파싱하여 유도된다.

Candidate Addition 16:RTCIceCandidate.relayProtocol 추가 (PR #2763)
Candidate Addition 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 이라면 throwTypeError 를 던진다.
  2. RTCIceCandidate 생성 절차를 candidateInitDict 로 수행한 결과를 반환한다.

candidateInitDict 사전을 사용하여 RTCIceCandidate 생성을 하려면 다음 단계를 수행한다:

  1. iceCandidate 를 새로 만든 RTCIceCandidate 객체로 둔다.
  2. iceCandidate 의 다음 속성들에 대해 내부 슬롯을 만들고 null 로 초기화한다: foundation, component, priority, address, protocol, port, type, tcpType, relatedAddress, relatedPort.
  3. iceCandidate 의 다음 속성들에 대해 내부 슬롯을 만들고 candidateInitDict 에서 동명 필드 값으로 초기화한다: candidate, sdpMid, sdpMLineIndex, usernameFragment.
  4. candidatecandidate 사전 멤버( candidateInitDict )로 두고, candidate 가 빈 문자열이 아니면 다음을 수행한다:
    1. candidatecandidate-attribute 문법으로 파싱한다.
    2. candidate-attribute 파싱이 실패했다면 이 단계를 중단한다.
    3. 파싱 결과의 어떤 필드라도 iceCandidate 의 대응 속성에 대해 유효하지 않은 값을 나타내면 중단한다.
    4. 해당 필드 값을 iceCandidate 의 내부 슬롯에 설정한다.
  5. iceCandidate 를 반환한다.
Note

RTCIceCandidate 생성자는 candidateInitDict 사전 멤버에 대한 기본 파싱 및 타입 검사만 수행한다. candidate, sdpMid, sdpMLineIndex, usernameFragment 가 해당 세션 description 과 잘 형성되었는지에 대한 상세 검증은 RTCIceCandidate 객체를 addIceCandidate() 에 전달할 때 수행된다.

하위 호환성을 유지하기 위해 candidate 속성 파싱 오류는 무시된다. 그런 경우 candidate 속성은 candidateInitDict 에서 전달된 원본 문자열을 유지하지만, foundation, priority 등 파생 속성은 null 로 설정된다.

속성

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

candidate 타입 DOMString, 읽기 전용
이는 candidate-attribute (RFC5245 15.1절)을 담는다. 이 RTCIceCandidate 가 end-of-candidates 표시이거나 peer reflexive 원격 candidate 를 나타내면 candidate 는 빈 문자열이다.
sdpMid 타입 DOMString, 읽기 전용, nullable
null 이 아니면, 이 candidate 가 연결된 미디어 구성 요소에 대한 [RFC5888] 에 정의된 media stream "identification-tag" 값을 포함한다.
sdpMLineIndex 타입 unsigned short, 읽기 전용, nullable
null 이 아니면, 이 candidate 가 연결된 SDP 내 media description 의 (0부터 시작하는) 인덱스이다.
foundation 타입 DOMString, 읽기 전용, nullable
여러 RTCIceTransport 에 나타나는 candidate 를 ICE 가 상호 연관시키도록 하는 고유 식별자.
component 타입 RTCIceComponent, 읽기 전용, nullable
Candidate 에 할당된 네트워크 컴포넌트 ("rtp" 또는 "rtcp"). component-id 필드를 candidate-attribute 에서 디코딩한 문자열 표현에 대응한다.
priority 타입 unsigned long, 읽기 전용, nullable
Candidate 에 할당된 우선순위.
address 타입 DOMString, 읽기 전용, nullable

Candidate 의 주소 (IPv4, IPv6, FQDN 허용). 이는 connection-address 필드에 대응한다: candidate-attribute.

원격 candidate 는 예를 들어 [[SelectedCandidatePair]].remote 로 노출될 수 있다. 기본적으로 사용자 에이전트는 노출된 원격 candidate 의 address 속성을 null 로 유지해야 한다(MUST). 웹 애플리케이션이 addIceCandidate 를 통해 주소를 학습한 이후에는, 사용자 에이전트가 해당 새로 학습된 주소를 가진 원격 candidate 를 표현하는 어떤 RTCIceCandidate 에서도 address 값을 노출할 수 있다.

Note

ICE 로 수집되어 애플리케이션에 노출되는 candidate 의 주소들은 (예: 위치, 로컬 네트워크 토폴로지) WebRTC 미지원 브라우저보다 사용자 기기 및 사용자를 더 많이 노출할 수 있다.

이러한 주소는 항상 애플리케이션에 노출되고, 통신 상대에게도 노출될 수 있으며, (데이터 채널만 사용하는 경우나 수신 전용인 경우처럼) 특정 사용자 동의 없이도 노출될 수 있다.

이러한 주소들은 일시적 또는 지속적인 교차 출처 상태로 활용되어 기기 지문(fingerprinting) 표면을 확대할 수 있다. (이것은 지문 수집 벡터입니다.)

애플리케이션은 ICE AgenticeTransportPolicy 를 통해 relay candidate 만 보고하도록 강제함으로써 상대에게 주소 노출을 (일시적 혹은 영구적으로) 피할 수 있다.

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

protocol 타입 RTCIceProtocol, 읽기 전용, nullable
Candidate 의 프로토콜 ("udp"/"tcp") 로서 transport 필드에 대응한다: candidate-attribute.
port 타입 unsigned short, 읽기 전용, nullable
Candidate 의 포트.
type 타입 RTCIceCandidateType, 읽기 전용, nullable
Candidate 의 종류. 이는 candidate-types 필드에 대응한다: candidate-attribute.
tcpType 타입 RTCIceTcpCandidateType, 읽기 전용, nullable
protocol 이 "tcp" 인 경우 tcpType 는 TCP candidate 의 유형을 나타낸다. 그렇지 않다면 tcpTypenull 이다. 이는 tcp-type 필드에 대응한다: candidate-attribute.
relatedAddress 타입 DOMString, 읽기 전용, nullable
다른 candidate 에서 파생된 candidate (relay 또는 reflexive 등)의 경우 relatedAddress 는 파생 원본의 IP 주소이며, host candidate 의 경우 relatedAddressnull 이다. 이는 rel-address 필드에 대응한다: candidate-attribute.
relatedPort 타입 unsigned short, 읽기 전용, nullable
다른 candidate 에서 파생된 candidate 의 경우 relatedPort 는 파생 원본의 포트이며, host candidate 의 경우 relatedPortnull 이다. 이는 rel-port 필드에 대응한다: candidate-attribute.
usernameFragment 타입 DOMString, 읽기 전용, nullable
이는 [RFC5245] 15.4절에 정의된 ufrag 를 담는다.
Candidate Addition 16:RTCIceCandidate.relayProtocol 추가 (PR #2763)
relayProtocol 타입 RTCIceServerTransportProtocol, 읽기 전용, nullable
로컬 candidate 가 "relay" 타입이면 TURN 서버와 통신에 사용된 프로토콜이다. 그 외 모든 candidate 에 대해 null 이다.
Candidate Addition 23:RTCIceCandidate.url 추가 (PR #2773)
url 타입 DOMString, 읽기 전용, nullable
로컬 candidate 가 "srflx" 또는 "relay" 타입이면 candidate 를 획득한 ICE 서버의 URL 이며, 그 외 candidate 에 대해서는 null 이다.
메서드
toJSON()
toJSON() 연산을 호출할 때 다음 단계를 수행한다:
  1. json 을 새 RTCIceCandidateInit 사전으로 둔다.
  2. 속성 식별자 attr 를 « candidate, sdpMid, sdpMLineIndex, usernameFragment» 각각에 대해:
    1. value 를 이 RTCIceCandidate 객체로부터 attr 식별자로 지정된 속성의 내부 값을 얻은 결과로 둔다.
    2. json[attr]value 를 설정한다.
  3. json 을 반환한다.
WebIDLdictionary RTCIceCandidateInit {
  DOMString candidate = "";
  DOMString? sdpMid = null;
  unsigned short? sdpMLineIndex = null;
  DOMString? usernameFragment = null;
};
사전 RTCIceCandidateInit 멤버
candidate 타입 DOMString, 기본값 ""
candidate-attribute (RFC5245 15.1절)을 담는다. end-of-candidates 표시라면 candidate 는 빈 문자열이다.
sdpMid 타입 DOMString, nullable, 기본값 null
null 이 아니면, 이 candidate 가 연결된 미디어 구성 요소의 media stream "identification-tag" (RFC5888) 값을 담는다.
sdpMLineIndex 타입 unsigned short, nullable, 기본값 null
null 이 아니면, 이 candidate 가 연결된 SDP 내 media description 의 0부터 시작하는 인덱스이다.
usernameFragment 타입 DOMString, nullable, 기본값 null
null 이 아니면, [RFC5245] 15.4절의 ufrag 를 담는다.
4.8.1.1 candidate-attribute 문법

candidate-attribute 문법은 candidate 멤버를 파싱하는 데 사용되며, 이는 RTCIceCandidate() 생성자에서의 candidateInitDict 에 해당한다.

candidate-attribute 기본 문법은 RFC5245 15.1절에 정의되며, 추가로 브라우저는 ICE TCP 에 대한 문법 확장 (RFC6544 4.5절)을 MUST 지원한다.

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

4.8.1.2 RTCIceProtocol 열거형

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

WebIDLenum RTCIceProtocol {
  "udp",
  "tcp"
};
RTCIceProtocol 열거형 설명
열거 값 설명
udp [RFC5245] 에 기술된 UDP candidate.
tcp [RFC6544] 에 기술된 TCP candidate.
4.8.1.3 RTCIceTcpCandidateType 열거형

RTCIceTcpCandidateType 는 ICE TCP candidate 의 유형을 나타내며, [RFC6544] 에 정의되어 있다.

WebIDLenum RTCIceTcpCandidateType {
  "active",
  "passive",
  "so"
};
RTCIceTcpCandidateType 열거형 설명
열거 값 설명
active "active" TCP candidate 는 아웃바운드 연결을 시도하지만 수신 연결 요청은 받지 않는다.
passive "passive" TCP candidate 는 수신 연결을 받지만 스스로 연결을 시도하지 않는다.
so "so" candidate 는 상대와 동시에 연결을 개시하려고 시도한다.
Note

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

4.8.1.4 RTCIceCandidateType 열거형

RTCIceCandidateType 은 ICE candidate 종류를 나타내며 [RFC5245] 15.1절에 정의되어 있다.

WebIDLenum RTCIceCandidateType {
  "host",
  "srflx",
  "prflx",
  "relay"
};
RTCIceCandidateType 열거형 설명
열거 값 설명
host 호스트 candidate (RFC5245 4.1.1.1).
srflx 서버 reflexive candidate (RFC5245 4.1.1.2).
prflx peer reflexive candidate (RFC5245 4.1.1.2).
relay relay candidate (RFC5245 7.1.3.2.1).
Candidate Addition 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 이벤트는 RTCPeerConnectionRTCPeerConnectionIceEvent 인터페이스를 사용한다.

RTCPeerConnectionIceEvent 이벤트를 발행할 때 RTCIceCandidate 객체가 포함되면 MUSTsdpMidsdpMLineIndex 값을 모두 포함해야 한다. Candidate 가 "srflx" 또는 "relay" 타입이면 이벤트의 url 속성은 candidate 를 얻은 ICE 서버의 URL 로 MUST 설정된다.

Note
icecandidate 이벤트는 세 가지 서로 다른 표시 용도로 사용된다:
  • Candidate 가 수집됨. 이벤트의 candidate 멤버가 일반적으로 채워진다. 이는 원격 피어로 시그널링되어 addIceCandidate 로 전달되어야 한다.

  • RTCIceTransport 가 한 generation 의 candidate 수집을 완료하고, RFC8838 8.2절에 정의된 end-of-candidates 표시를 제공. 이는 candidate.candidate 가 빈 문자열로 설정된 것으로 표시된다. 이 객체는 원격 피어에 시그널링되고 addIceCandidate 로 전달되어 원격 피어에게 end-of-candidates 표시를 제공해야 한다.

  • 모든 RTCIceTransport 가 candidate 수집을 완료했고 RTCPeerConnectionRTCIceGatheringState 가 "complete" 로 전이. 이 경우 이벤트의 candidate 멤버가 null 로 설정된다. 이는 하위 호환성만을 위한 것이며 원격 피어에 시그널링할 필요는 없다. 이는 "complete" 상태의 icegatheringstatechange 이벤트와 동일하다.

WebIDL[Exposed=Window]
interface RTCPeerConnectionIceEvent : Event {
  constructor(DOMString type, optional RTCPeerConnectionIceEventInit eventInitDict = {});
  readonly attribute RTCIceCandidate? candidate;
  readonly attribute DOMString? url;
};
생성자
RTCPeerConnectionIceEvent.constructor()
속성
candidate 타입 RTCIceCandidate, 읽기 전용, nullable

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

Candidate 수집 종료를 나타내는 이벤트에서는 이 속성이 null 로 설정된다.

Note

다수의 미디어 컴포넌트가 있더라도 null candidate 를 포함한 이벤트는 한 번만 발생한다.

url 타입 DOMString, 읽기 전용, nullable

url 속성은 이 candidate 를 수집하는 데 사용된 STUN 또는 TURN 서버를 식별하는 STUN/TURN URL 이다. 후보가 STUN/TURN 서버로부터 수집된 것이 아니면 null.

Candidate Correction 23:RTCPeerConnectionIceEvent.url 사용 중단(deprecated) 표시 (PR #2773)

이 속성은 사용 중단되었으며 레거시 호환성만을 위해 존재한다. candidate 의 url 속성 사용을 권장한다.

WebIDLdictionary RTCPeerConnectionIceEventInit : EventInit {
  RTCIceCandidate? candidate;
  DOMString? url;
};
사전 RTCPeerConnectionIceEventInit 멤버
candidate 타입 RTCIceCandidate, nullable

candidate 속성 설명 참조.

url 타입 DOMString, nullable

Candidate 를 수집한 STUN 또는 TURN 서버를 식별하는 STUN/TURN URL.

4.8.3 RTCPeerConnectionIceErrorEvent

icecandidateerror 이벤트는 RTCPeerConnectionRTCPeerConnectionIceErrorEvent 인터페이스를 사용한다.

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, 읽기 전용, nullable

address 속성은 STUN/TURN 서버와 통신에 사용된 로컬 IP 주소.

다중 홈 환경에서는 여러 인터페이스가 서버에 사용될 수 있으며 이 속성은 어떤 인터페이스에서 실패가 발생했는지 식별하는 데 도움을 준다.

로컬 IP 주소가 로컬 candidate 로 이미 노출되지 않았다면 addressnull 로 설정된다.

port 타입 unsigned short, 읽기 전용, nullable

port 속성은 STUN/TURN 서버와 통신에 사용된 로컬 포트.

addressnull 이면 portnull.

url 타입 DOMString, 읽기 전용

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

errorCode 타입 unsigned short, 읽기 전용

errorCode 속성은 STUN/TURN 서버가 반환한 STUN 오류 코드 [STUN-PARAMETERS] 이다.

어떤 host candidate 도 서버에 도달할 수 없으면 errorCode 는 STUN 오류 코드 범위 밖의 701 로 설정된다. 이 오류는 "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, nullable

STUN 또는 TURN 서버와 통신하는 데 사용된 로컬 주소; 없으면 null.

port 타입 unsigned short, nullable

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 생성 시 제공하지 않으면 새로운 인증서 집합이 반드시(MUST) user agent 에 의해 생성되어야 한다. 그 집합은 반드시(MUST) P-256 곡선의 개인 키와 SHA-256 해시 서명을 가진 ECDSA 인증서를 포함해야 한다.

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

메서드

generateCertificate, static

generateCertificate 함수는 user agent 가 X.509 인증서 [X509V3] 와 대응하는 개인 키를 생성하도록 한다. 정보에 대한 핸들은 RTCCertificate 인터페이스 형태로 제공된다. 반환된 RTCCertificateRTCPeerConnection 이 설정하는 DTLS 세션에서 제공될 인증서를 제어하는 데 사용할 수 있다.

keygenAlgorithm 인수는 인증서에 연관된 개인 키가 어떻게 생성되는지 제어한다. keygenAlgorithm 인수는 WebCrypto [WebCryptoAPI] 의 AlgorithmIdentifier 타입을 사용한다.

다음 값들은 user agent반드시(MUST) 지원해야 한다: { name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" }, 그리고 { name: "ECDSA", namedCurve: "P-256" }.

Note

일반적으로 user agent 는 수용 가능한 값들의 작은(또는 고정된) 집합을 가진다고 예상된다.

이 과정에서 생성된 인증서는 서명을 포함한다. 이 서명의 유효성은 호환성 목적에서만 관련이 있다. 공개 키와 그로부터 생성되는 인증서 지문만이 RTCPeerConnection 에서 사용되지만, 인증서가 잘 형성되어 있으면 더 쉽게 수용될 가능성이 크다. 브라우저는 인증서를 서명하는 데 사용되는 알고리즘을 선택한다; 브라우저는 해시 알고리즘이 필요한 경우 SHA-256 [FIPS-180-4] 를 선택하는 것이 권장(SHOULD)된다.

결과 인증서에는 사용자나 user agent 에 연결될 수 있는 정보가 포함되어서는 안 된다(MUST NOT). 고유 이름(DN)과 일련 번호에 대한 무작위화된 값 사용이 권장(SHOULD)된다.

메서드가 호출될 때, user agent 는 반드시(MUST) 다음 단계를 수행한다:

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

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

    Note

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

  3. keygenAlgorithm 이 객체라면 다음 단계를 수행한다:

    1. certificateExpirationconverting 을 통해 ECMAScript 객체 keygenAlgorithmRTCCertificateExpiration 사전으로 변환한 결과로 둔다.

    2. 변환이 error 로 실패하면, error거절(rejected) 된 promise 를 반환한다.

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

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

      Note

      이는 인증서가 generateCertificate 호출 시점부터 최대 365일을 넘게 유효할 수 없음을 의미한다.

      user agent추가로(MAY) expires 값을 더 낮게 제한할 수 있다.

  4. normalizedKeygenAlgorithmnormalizing an algorithm (operation 이름 generateKeysupportedAlgorithms 값은 RTCPeerConnection 인증서 생산에 특화) 결과로 둔다.

  5. 위 정규화 단계가 error 로 실패하면 error거절(rejected) 된 promise 를 반환한다.

  6. normalizedKeygenAlgorithmuser agentRTCPeerConnection 에 대한 인증서를 생성하기 위해 사용할 수 없거나 사용하지 않을 알고리즘을 식별하면, NotSupportedError 타입의 DOMException 으로 거절(rejected) 된 promise 를 반환한다. 특히 normalizedKeygenAlgorithm 은 DTLS 연결 인증에 사용되는 서명을 생성할 수 있는 비대칭 알고리즘이어야 한다(MUST).

  7. p 를 새로운 promise 로 둔다.

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

    1. normalizedKeygenAlgorithm 이 지정한 generate key 연산을 keygenAlgorithm 을 사용해 수행한다.

    2. generatedKeyingMaterialgeneratedKeyCertificate 를 위 단계에서 생성된 개인 키 재료와 인증서로 둔다.

    3. certificate 를 새로운 RTCCertificate 객체로 둔다.

    4. certificate.[[Expires]] 를 현재 시간 + expires 값으로 설정한다.

    5. certificate.[[Origin]]relevant settings objectorigin 으로 설정한다.

    6. generatedKeyingMaterial 을 안전한 모듈에 저장하고 handle 을 그것에 대한 참조 식별자로 둔다.

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

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

    9. 현재 realm 의 global objectglobal 로 하여 networking task sourceglobal task 큐잉을 수행하고 resolvepcertificate 로 해결한다.

  9. p 를 반환한다.

4.9.1 RTCCertificateExpiration 사전(Dictionary)

RTCCertificateExpirationgenerateCertificate 에 의해 생성된 인증서에 만료 일자를 설정하는 데 사용된다.

WebIDLdictionary RTCCertificateExpiration {
  [EnforceRange] unsigned long long expires;
};
expires, of type unsigned long long

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

4.9.2 RTCCertificate 인터페이스

RTCCertificate 인터페이스는 WebRTC 통신을 인증하는 데 사용되는 인증서를 나타낸다. 표시되는 속성 외에도, 내부 슬롯에는 생성된 개인 키 재료에 대한 핸들([[KeyingMaterialHandle]]), 피어 인증에 RTCPeerConnection 이 사용하는 인증서([[Certificate]]), 그리고 객체를 생성한 origin([[Origin]]) 이 들어있다.

WebIDL[Exposed=Window, Serializable]
interface RTCCertificate {
  readonly attribute EpochTimeStamp expires;
  sequence<RTCDtlsFingerprint> getFingerprints();
};
속성
expires of type EpochTimeStamp, readonly

expires 속성은 인증서가 브라우저에 의해 더 이상 유효하지 않다고 간주되는 1970-01-01T00:00:00Z 기준 밀리초 단위 날짜·시간을 나타낸다. 이 시간이 지나면 해당 인증서를 사용한 RTCPeerConnection 구성 시도가 실패한다.

이 값이 인증서 자체의 notAfter 파라미터에 반영되지 않을 수도 있음을 유의한다.

메서드
getFingerprints

인증서 지문의 목록을 반환하며, 그 중 하나는 인증서 서명에 사용된 다이제스트 알고리즘으로 계산된다.

이 API 목적상 [[Certificate]] 슬롯은 구조화되지 않은 바이너리 데이터를 포함한다. 애플리케이션이 [[KeyingMaterialHandle]] 내부 슬롯이나 그가 참조하는 키 재료에 접근하는 메커니즘은 제공되지 않는다. 구현은 반드시(MUST) RTCCertificate 객체를 영구 저장소에 저장/복구하도록 지원해야 하며, 이때 [[KeyingMaterialHandle]] 이 참조하는 키 재료도 유지해야 한다. 구현은 민감한 키 재료를 동일 프로세스 메모리 공격으로부터 안전한 보안 모듈에 저장하는 것이 권장(SHOULD)된다. 이는 개인 키를 저장하고 사용할 수 있게 하지만 메모리 공격으로 쉽게 읽히지 않게 한다.

RTCCertificate 객체는 serializable objects [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]] 역직렬화로부터 얻은 개인 키 재료 핸들로 설정한다.
Note

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

5. RTP 미디어 API

RTP 미디어 API는 웹 애플리케이션이 MediaStreamTrack를 피어 투 피어 연결을 통해 송수신할 수 있게 합니다. 트랙이 RTCPeerConnection에 추가되면 시그널링이 발생하며, 이 시그널링이 원격 피어로 전달될 때, 원격 측에 해당하는 트랙이 생성됩니다.

참고

RTCPeerConnection에서 송신된 트랙과 다른 피어에서 수신된 트랙 간에는 정확한 1:1 대응 관계가 존재하지 않습니다. 예를 들어, 송신된 트랙의 ID는 수신된 트랙의 ID와 매핑되지 않습니다. 또한, replaceTrackRTCRtpSender가 송신하는 트랙을 변경하지만, 수신 측에서는 새로운 트랙이 생성되지 않습니다. 해당 RTCRtpReceiver는 오직 하나의 트랙만 가지며, 이 트랙은 여러 미디어 소스가 결합된 형태일 수 있습니다. addTransceiverreplaceTrack를 통해 동일한 트랙을 여러 번 송신할 수 있으며, 수신 측에서는 각기 별도의 트랙을 가진 여러 수신기로 인식됩니다. 따라서 한쪽의 RTCRtpSender와 반대쪽의 RTCRtpReceiver의 트랙 간의 1:1 관계로 이해하는 것이 더 정확합니다. 송신자와 수신자는 필요하다면 RTCRtpTransceivermid를 사용하여 매칭할 수 있습니다.

미디어를 송신할 때, 송신자는 미디어를 SDP로 협상된 환경, 인코더의 정렬 제약, CPU 과부하 감지 또는 대역폭 예측 등 다양한 요구 사항을 충족시키기 위해 리스케일 또는 리샘플링해야 할 수 있습니다.

[RFC9429] (section 3.6.)의 규칙에 따라, 비디오는 축소될 수 있습니다(MAY). 미디어는 입력 소스에 존재하지 않는 가짜 데이터를 생성하기 위해 확대되어서는 안 됩니다(MUST NOT), 미디어는 픽셀 수 제약을 충족하기 위한 경우를 제외하고는 크롭되어서는 안 됩니다(MUST NOT), 그리고 종횡비는 변경되어서는 안 됩니다(MUST NOT).

참고

WebRTC 워킹 그룹은 이 상황에 대해 더 복잡한 처리가 필요한지와 그 시점에 대한 구현 피드백을 받고 있습니다. 몇 가지 가능한 설계가 GitHub issue 1283에서 논의되었습니다.

비디오가 scaleResolutionDownBy에 따라 리스케일되는 경우, 결과 너비나 높이가 정수가 아닌 상황이 발생할 수 있습니다. 사용자 에이전트는 정수 부분보다 큰 영상은 scaleResolutionDownBy로부터 스케일된 너비와 높이의 정수 부분을 초과하는 비디오를 전송해서는 안 됩니다(MUST NOT). 단, 인코더의 최소 해상도를 존중해야 합니다. 스케일된 너비나 높이의 정수 부분이 0인 경우 무엇을 전송할지는 구현 정의입니다.

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

MediaStreamTrack의 인코딩 및 전송은 그 특성(width, height, frameRate 등 비디오 트랙의 경우, sampleSize, sampleRate, channelCount 등 오디오 트랙의 경우)이 원격 측에서 생성된 트랙에 어느 정도 유지되도록 권장됩니다(SHOULD). 하지만 상황에 따라 적용되지 않는 경우가 있을 수 있으며, 예를 들어 어느 한쪽의 리소스 제약이나 네트워크 제약, 혹은 RTCRtpSender 설정에 따라 구현이 다르게 동작하도록 지시될 수 있습니다.

RTCPeerConnection 객체는 RTCRtpTransceiver들의 집합을 포함합니다. 이는 페어링된 송신자와 수신자를 나타내며, 일부 공유 상태를 가집니다. 이 집합은 RTCPeerConnection 객체가 생성될 때 초기값으로 빈 집합이 됩니다. RTCRtpSenderRTCRtpReceiver는 항상 RTCRtpTransceiver가 생성될 때 동시에 만들어지며, 생애주기 동안 해당 트랜시버에 연결됩니다. RTCRtpTransceiver는 애플리케이션이 MediaStreamTrackRTCPeerConnectionaddTrack() 메서드로 추가할 때 암시적으로 생성되거나, addTransceiver 메서드를 명시적으로 사용할 때 생성됩니다. 또한 원격 설명을 적용할 때 새로운 미디어 설명이 포함되어 있으면 트랜시버가 생성됩니다. 추가로, 원격 설명이 원격 엔드포인트가 미디어를 송신함을 나타내는 경우 해당 MediaStreamTrackRTCRtpReceiver가 애플리케이션에 track 이벤트를 통해 노출됩니다.

RTCRtpTransceiver가 다른 엔드포인트와 미디어를 송수신하려면, 양쪽 엔드포인트가 동일한 미디어 설명연결(associated)RTCRtpTransceiver 객체를 갖도록 SDP로 협상해야 합니다.

오퍼를 생성할 때, 해당 측의 모든 트랜시버를 커버할 수 있도록 충분한 미디어 설명이 생성됩니다. 이 오퍼를 로컬 설명으로 설정하면, 연결되지 않은 트랜시버들이 오퍼의 미디어 설명과 연결됩니다.

오퍼가 원격 설명으로 설정되면, 아직 트랜시버와 연결되지 않은 미디어 설명은 새 트랜시버 또는 기존 트랜시버와 연결됩니다. 이 경우, addTrack() 메서드로 생성된 연결되지 않은 트랜시버만 연결될 수 있습니다. addTransceiver() 메서드로 생성된 연결되지 않은 트랜시버는, 원격 오퍼에 미디어 설명이 충분히 존재하더라도 연결되지 않습니다. 대신, addTrack()로 생성된 트랜시버가 충분하지 않은 경우 새 트랜시버가 생성되어 연결됩니다. 이로 인해 addTrack()로 생성된 트랜시버와 addTransceiver()로 생성된 트랜시버가 속성만 봐서는 구분할 수 없는 중요한 차이를 갖게 됩니다.

응답(answer)을 생성할 때는 오퍼에 존재했던 미디어 설명만 응답에 나열할 수 있습니다. 그 결과, 원격 오퍼를 설정할 때 연결되지 않았던 트랜시버는 로컬 응답을 설정한 후에도 연결되지 않은 상태로 남게 됩니다. 이를 해결하려면 응답자가 후속 오퍼를 생성해 추가 오퍼/응답 교환을 시작하거나, 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

현재 이 RTCPeerConnection 객체에 연결되어 있고 중지되지 않은 RTCRtpTransceiver 객체에 속한 RTP 송신자를 나타내는 RTCRtpSender 객체의 시퀀스를 반환합니다.

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

CollectSenders 알고리즘을 다음과 같이 정의합니다:

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

현재 이 RTCPeerConnection 객체에 연결되어 있고 중지되지 않은 RTCRtpTransceiver 객체에 속한 RTP 수신자를 나타내는 RTCRtpReceiver 객체의 시퀀스를 반환합니다.

getReceivers 메서드가 호출되면, 사용자 에이전트는 MUST 다음 단계를 수행합니다:

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

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

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

CollectTransceivers 알고리즘을 다음과 같이 정의합니다:

  1. transceivers를, 이 RTCPeerConnection 객체의 set of transceivers에 있는 모든 RTCRtpTransceiver 객체로 구성된, 삽입 순서를 따르는 새로운 시퀀스로 설정한다.
  2. transceivers를 반환한다.
addTrack

새로운 트랙을 RTCPeerConnection에 추가하고, 지정된 MediaStream들에 포함되어 있음을 나타냅니다.

addTrack 메서드가 호출되면, 사용자 에이전트는 MUST 다음 단계를 수행합니다:

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

  2. track을 메서드의 첫 번째 인자로 지정된 MediaStreamTrack 객체로 설정한다.

  3. kindtrack.kind로 설정한다.

  4. streams를 메서드의 나머지 인자들로부터 생성된 MediaStream 객체의 목록으로 설정하고, 인자가 하나만 전달된 경우 빈 목록으로 설정한다.

  5. connection.[[IsClosed]]true이면, 예외를 발생시키며, InvalidStateError를 던진다.

  6. sendersCollectSenders 알고리즘을 실행한 결과로 설정한다. 만약 track에 대한 RTCRtpSender가 이미 senders 안에 존재한다면, 예외를 발생시키며 InvalidAccessError를 던진다.

  7. 아래 단계는 기존 보낼 수 있는(sender) 객체를 재사용할 수 있는지 결정하는 방법을 설명합니다. 이렇게 하면 이후의 createOffercreateAnswer 호출이 해당 미디어 설명sendrecv 또는 sendonly로 표시하고, [RFC9429]의 (섹션 5.2.2.섹션 5.3.2.)에 정의된 대로 송신자의 스트림의 MSID를 추가하도록 만듭니다.

    만약 senders의 어떤 RTCRtpSender 객체가 다음 모든 기준을 만족한다면, sender를 그 객체로 설정하고, 그렇지 않다면 null로 설정한다:

  8. sendernull이 아니면, 해당 sender를 사용하기 위해 다음 단계를 수행한다:

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

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

    3. streams의 각 stream에 대해, 이미 없으면 stream.id[[AssociatedMediaStreamIds]]에 추가한다.

    4. transceiversender와 연관된 RTCRtpTransceiver로 설정한다.

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

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

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

    1. RTCRtpSender 생성track, kind, streams로 수행하고, 결과를 sender로 둔다.

    2. RTCRtpReceiver 생성kind로 수행하고, 결과를 receiver로 둔다.

    3. RTCRtpTransceiver 생성sender, receiverRTCRtpTransceiverDirection 값 "sendrecv"로 수행하고, 결과를 transceiver로 둔다.

    4. transceiverconnectionset of transceivers에 추가한다.

  10. 트랙은 애플리케이션이 접근할 수 없는 콘텐츠를 가질 수 있습니다. 이는 트랙을 CORS 교차 출처로 만드는 어떤 이유 때문일 수 있습니다. 이러한 트랙은 addTrack() 메서드에 제공될 수 있으며, 이에 대해 RTCRtpSender가 생성되지만, 콘텐츠는 MUST NOT 전송되어서는 안 됩니다. 그 대신 무음(오디오), 검은 프레임(비디오) 또는 동등한 부재 콘텐츠가 트랙 콘텐츠 대신 전송됩니다.

    이 속성은 시간이 지나면서 변경될 수 있다는 점에 유의하십시오.

  11. negotiation-needed 플래그를 업데이트하여 connection에 반영한다.

  12. sender를 반환한다.

removeTrack

sender로부터 미디어 송신을 중지합니다. RTCRtpSender는 여전히 getSenders에 표시됩니다. 이렇게 하면 이후의 createOffer 호출이 해당 트랜시버의 미디어 설명을 "recvonly" 또는 "inactive"로 표시하도록 만듭니다. 이는 [RFC9429] (섹션 5.2.2.)에 정의되어 있습니다.

다른 피어가 이 방법으로 트랙 송신을 중지하면, 해당 트랙은 처음에 track 이벤트에서 공개되었던 원격 MediaStream들에서 제거되고, MediaStreamTrack이 아직 mute 상태가 아니라면 트랙에 mute 이벤트가 발생합니다.

참고
removeTrack()과 동일한 효과는, 해당 트랜시버의 RTCRtpTransceiverdirection 속성을 설정하고, 송신자에서 RTCRtpSenderreplaceTrack(null)을 호출함으로써 얻을 수 있습니다. 한 가지 작은 차이점은 replaceTrack()은 비동기적이며, removeTrack()은 동기적이라는 점입니다.

removeTrack 메서드가 호출되면, 사용자 에이전트는 MUST 다음 단계를 수행합니다:

  1. senderremoveTrack의 인자로 설정한다.

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

  3. connection.[[IsClosed]]true이면, 예외를 발생시키며 InvalidStateError를 던진다.

  4. senderconnection에 의해 생성되지 않은 경우, 예외를 발생시키며 InvalidAccessError를 던진다.

  5. transceiversender에 대응하는 RTCRtpTransceiver 객체로 설정한다.

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

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

  8. 만약 sendersenders에 포함되어 있지 않다면(이는 해당 transceiver가 중단되었거나 세션 설명을 설정하는 과정에서 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. negotiation-needed 플래그를 업데이트하여 connection에 반영한다.

addTransceiver

새로운 RTCRtpTransceiver를 생성하여 set of transceivers에 추가합니다.

트랜시버를 추가하면 이후의 createOffer 호출이 해당 트랜시버에 대한 미디어 설명을 추가하도록 합니다. 이는 [RFC9429] (섹션 5.2.2.)에 정의되어 있습니다.

mid의 초기 값은 null입니다. 이후 세션 설명을 설정하면 null이 아닌 값으로 변경될 수 있습니다.

sendEncodings 인자는 제공할 시뮬캐스트 인코딩의 개수와, 선택적으로 그 RID와 인코딩 매개변수를 지정하는 데 사용할 수 있습니다.

이 메서드가 호출되면, 사용자 에이전트는 MUST 다음 단계를 수행합니다:

  1. init를 두 번째 인자로 설정한다.

  2. streamsinit.streams로 설정한다.

  3. sendEncodingsinit.sendEncodings로 설정한다.

  4. directioninit.direction으로 설정한다.

  5. 첫 번째 인자가 문자열이면, kind를 그 첫 번째 인자로 설정하고 다음 단계를 수행한다:

    1. kind"audio""video"도 아니면, 예외를 발생시키며 TypeError를 던진다.

    2. tracknull로 설정한다.

  6. 첫 번째 인자가 MediaStreamTrack이면, track을 그 첫 번째 인자로, kindtrackkind로 설정한다.

  7. connection.[[IsClosed]]true이면, 예외를 발생시키며 InvalidStateError를 던진다.

  8. 다음의 addTransceiver sendEncodings validation steps을 실행하여 sendEncodings을 검증한다. 여기서 각 RTCRtpEncodingParameters 사전은 "encoding"이다:

    1. sendEncodings 안의 각 rid 값이 [RFC8851]의 섹션 10에 지정된 문법을 준수하는지 확인한다. RID 중 하나라도 이 요구 사항을 충족하지 못하면, 예외를 발생시키고 TypeError를 던진다.

      다음 조건 중 하나라도 충족되면, 예외를 발생시키며 TypeError를 던진다:
      • 어떤 인코딩이 포함rid 멤버의 값이 [RFC8851]의 섹션 10에 지정된 문법 요구 사항을 준수하지 않는 경우.
      • 일부 인코딩만 포함rid 멤버가 있고, 나머지는 없는 경우.
      • 어떤 인코딩이 포함rid 멤버의 값이 sendEncodings의 다른 인코딩에 포함rid와 동일한 경우.
    2. 어떤 인코딩이 포함읽기 전용 매개변수rid를 제외하고 존재하면, 예외를 발생시키고 InvalidAccessError를 던진다.

    3. 후보 추가 49:RTCRtpEncodingParameters에 codec 추가 (PR #2985)

      어떤 인코딩이 포함codec 멤버의 값이 일치하지 않는 어떤 코덱도 RTCRtpSendergetCapabilities(kind).codecs에 존재하지 않으면, 예외를 발생시키고 OperationError를 던진다.

    4. 후보 추가 49:RTCRtpEncodingParameters에 codec 추가 (PR #2985)

      사용자 에이전트가 협상 없이 코덱 변경을 지원하지 않거나, 개별 인코딩에 대해 코덱 설정을 지원하지 않는 경우, 새롭게 생성된 OperationError거부된 프로미스를 반환한다.

    5. kind"audio"이면, 모든 인코딩에서 scaleResolutionDownBymaxFramerate 멤버가 포함되어 있으면 제거한다.

    6. 어떤 인코딩이 포함scaleResolutionDownBy 멤버의 값이 1.0보다 작으면, 예외를 발생시키고 RangeError를 던진다.

    7. sendEncodings에서 정의된 각 maxFramerate 멤버의 값이 0.0보다 큰지 확인한다. 값 중 하나라도 이 요구 사항을 충족하지 못하면, 예외를 발생시키고 RangeError를 던진다.

    8. maxN을 사용자 에이전트가 이 kind에 대해 지원할 수 있는 총 동시 인코딩의 최대 개수(최소 1)로 설정한다. 사용될 코덱이 아직 알려지지 않았으므로 낙관적인 숫자여야 한다.

    9. 어떤 인코딩이 포함scaleResolutionDownBy 멤버가 있다면, 해당 멤버가 없는 각 인코딩에 값이 1.0scaleResolutionDownBy 멤버를 추가한다.

    10. sendEncodings에 저장된 인코딩의 개수가 maxN을 초과하면, 길이가 maxN이 될 때까지 꼬리에서부터 sendEncodings을 잘라낸다.

    11. kind"video"이고, 어떤 인코딩도 포함scaleResolutionDownBy 멤버가 없다면, 각 인코딩에 scaleResolutionDownBy 멤버를 추가하고, 그 값을 2^(length of sendEncodings - encoding index - 1)로 설정한다. 이는 가장 작은 해상도부터 큰 해상도 순으로 구성되며, 마지막 인코딩에는 스케일링이 적용되지 않는다(예: 길이가 3이면 4:2:1).

    12. 현재 sendEncodings에 저장된 인코딩의 개수가 1이면, 단일 항목에서 rid 멤버를 제거한다.

      참고
      sendEncodings에 단일 기본 RTCRtpEncodingParameters를 제공하면, 시뮬캐스트가 사용되지 않더라도 이후에 setParameters를 사용하여 인코딩 매개변수를 설정할 수 있습니다.
  9. RTCRtpSender 생성track, kind, streams, sendEncodings로 수행하고 결과를 sender로 둔다.

    sendEncodings가 설정되면, 이후의 createOffer 호출은 [RFC9429] (섹션 5.2.2.섹션 5.2.1.)에 정의된 대로 여러 RTP 인코딩을 송신하도록 구성됩니다. setRemoteDescription[RFC9429] (섹션 3.7.)에 정의된 대로 여러 RTP 인코딩을 수신할 수 있는 해당 원격 설명과 함께 호출되면, RTCRtpSender는 여러 RTP 인코딩을 송신할 수 있으며, 트랜시버의 sendergetParameters()를 통해 검색된 매개변수는 협상된 인코딩을 반영하게 됩니다.

  10. RTCRtpReceiver 생성kind로 수행하고 결과를 receiver로 둔다.

  11. RTCRtpTransceiver 생성sender, receiver, direction으로 수행하고, 결과를 transceiver로 둔다.

  12. transceiverconnectionset of transceivers에 추가한다.

  13. negotiation-needed 플래그를 업데이트하여 connection에 반영한다.

  14. transceiver를 반환한다.

WebIDLdictionary RTCRtpTransceiverInit {
  RTCRtpTransceiverDirection direction = "sendrecv";
  sequence<MediaStream> streams = [];
  sequence<RTCRtpEncodingParameters> sendEncodings = [];
};

사전 RTCRtpTransceiverInit 멤버

direction 타입 RTCRtpTransceiverDirection, 기본값 "sendrecv"
RTCRtpTransceiver의 방향입니다.
streams 타입 sequence<MediaStream>

원격 RTCPeerConnection의 track 이벤트가 추가된 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 원격 MediaStreamTracks 처리

애플리케이션은 트랜시버의 direction을 "inactive"로 설정하여 양방향을 일시적으로 끄거나, "sendonly"로 설정하여 입력 방향만 거부함으로써, 들어오는 미디어 설명을 거부할 수 있습니다. m-line을 재사용 가능하도록 영구적으로 거부하려면, 애플리케이션은 RTCRtpTransceiverstop()을 호출하고, 이후 자체적으로 협상을 시작해야 합니다.

RTCRtpTransceiver transceiver, direction, msids, addList, removeList, trackEventInits가 주어졌을 때 process remote tracks를 수행하려면, 다음 단계를 실행합니다:

  1. 연관된 원격 스트림 설정transceiver.[[Receiver]], msids, addList, removeList로 수행합니다.

  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가 주어졌을 때 process the addition of a remote track을 수행하려면, 다음 단계를 실행합니다:

  1. receivertransceiver.[[Receiver]]로 둡니다.

  2. trackreceiver.[[ReceiverTrack]]로 둡니다.

  3. streamsreceiver.[[AssociatedRemoteMediaStreams]] 로 둡니다.

  4. receiver, track, streams, transceiver를 멤버로 하는 새로운 RTCTrackEventInit 사전을 생성하여 trackEventInits에 추가합니다.

RTCRtpTransceiver transceivermuteTracks가 주어졌을 때 process the removal of a remote track을 수행하려면, 다음 단계를 실행합니다:

  1. receivertransceiver.[[Receiver]]로 둡니다.

  2. trackreceiver.[[ReceiverTrack]]로 둡니다.

  3. track.mutedfalse이면, trackmuteTracks에 추가합니다.

RTCRtpReceiver receiver, msids, addList, removeList가 주어졌을 때 set the associated remote streams를 수행하려면, 다음 단계를 실행합니다:

  1. connectionRTCPeerConnection 객체(이는 receiver와 연관됨)로 둡니다.

  2. msids의 각 MSID에 대해, 해당 id로 이 connection에 대해 이전에 생성된 MediaStream 객체가 없다면, 그 idMediaStream 객체를 생성합니다.

  3. streams를, 이 connection에 대해 msids에 대응하는 id로 생성된 MediaStream 객체들의 목록으로 둡니다.

  4. trackreceiver.[[ReceiverTrack]]로 둡니다.

  5. receiver.[[AssociatedRemoteMediaStreams]]에 있는 각 streamstreams에 존재하지 않는 것에 대해, streamtrack을 쌍으로 하여 removeList에 추가합니다.

  6. streams에 있는 각 streamreceiver.[[AssociatedRemoteMediaStreams]]에 존재하지 않는 것에 대해, streamtrack을 쌍으로 하여 addList에 추가합니다.

  7. receiver.[[AssociatedRemoteMediaStreams]]streams로 설정합니다.

5.2 RTCRtpSender 인터페이스

RTCRtpSender 인터페이스는 애플리케이션이 특정 MediaStreamTrack을 원격 피어로 인코딩하고 전송하는 방식을 제어할 수 있게 합니다. setParametersRTCRtpSender 객체에서 호출되면, 인코딩이 적절히 변경됩니다.

RTCRtpSender 생성을 위해 MediaStreamTrack, track, 문자열 kind, MediaStream 객체들의 목록 streams, 그리고 선택적으로 RTCRtpEncodingParameters 객체들의 목록 sendEncodings을 사용하여 다음 단계를 실행합니다:

  1. sender를 새로운 RTCRtpSender 객체로 둡니다.

  2. sender[[SenderTrack]] 내부 슬롯을 추가하고, track으로 초기화합니다.

  3. sender[[SenderTransport]] 내부 슬롯을 추가하고 null로 초기화합니다.

  4. sender[[LastStableStateSenderTransport]] 내부 슬롯을 추가하고 null로 초기화합니다.

  5. sender[[Dtmf]] 내부 슬롯을 추가하고 null로 초기화합니다.

  6. kind"audio"인 경우, RTCDTMFSender를 생성하고 dtmf로 설정한 후, [[Dtmf]] 내부 슬롯을 dtmf로 설정합니다.

  7. sender[[AssociatedMediaStreamIds]] 내부 슬롯을 추가합니다. 이는 이 MediaStream 객체와 연관된 Id 목록을 나타냅니다. [[AssociatedMediaStreamIds]] 슬롯은 [RFC9429] (섹션 5.2.1.)에 설명된 대로 SDP에서 sender를 나타낼 때 사용됩니다.

  8. sender.[[AssociatedMediaStreamIds]]를 빈 집합으로 설정합니다.

  9. streams에 있는 각 stream에 대해, stream.id[[AssociatedMediaStreamIds]]에 추가합니다(이미 존재하지 않는 경우).

  10. sender[[SendEncodings]] 내부 슬롯을 추가합니다. 이는 RTCRtpEncodingParameters 사전 목록을 나타냅니다.

  11. sendEncodings가 이 알고리즘의 입력으로 주어지고 비어 있지 않은 경우, [[SendEncodings]] 슬롯을 sendEncodings로 설정합니다. 그렇지 않으면, 이를 새 RTCRtpEncodingParameters 사전을 포함하는 목록으로 설정하고, kind"video"인 경우, 이 사전에 scaleResolutionDownBy 멤버와 값 1.0를 추가합니다.

    참고

    RTCRtpEncodingParameters 사전에는 값이 기본적으로 trueactive 멤버가 포함되어 있습니다.

  12. Candidate Correction 13:Rollback restores ridless encoding trounced by sRD(simulcastOffer). (PR #2797)

    sender[[LastStableRidlessSendEncodings]] 내부 슬롯을 추가하고 null로 초기화합니다.

  13. sender[[SendCodecs]] 내부 슬롯을 추가합니다. 이는 RTCRtpCodecParameters 사전 목록을 나타내며, 빈 목록으로 초기화됩니다.

  14. sender[[LastReturnedParameters]] 내부 슬롯을 추가합니다. 이는 getParameterssetParameters 트랜잭션을 일치시키는 데 사용됩니다.

  15. 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();
};

속성

track 타입 MediaStreamTrack, 읽기 전용, nullable

track 속성은 이 RTCRtpSender 객체와 연결된 트랙입니다. track이 종료되었거나 트랙의 출력이 비활성화된 경우, 즉 트랙이 비활성화되었거나 음소거된 경우, RTCRtpSender반드시 검은 프레임(비디오)을 전송하며, 반드시 (오디오)를 전송하지 않아야 합니다. 비디오의 경우, RTCRtpSender는 1초에 한 번 검은 프레임을 전송해야 합니다. tracknull인 경우, RTCRtpSender는 전송하지 않습니다. 가져오기를 수행할 때, 이 속성은 반드시 [[SenderTrack]] 슬롯의 값을 반환해야 합니다.

transport 타입 RTCDtlsTransport, 읽기 전용, nullable

transport 속성은 track에서 RTP 패킷 형태로 미디어가 전송되는 전송 수단입니다. RTCDtlsTransport 객체가 생성되기 전에, transport 속성은 null로 설정됩니다. 번들링이 사용될 경우, 여러 RTCRtpSender 객체들이 하나의 transport를 공유하며, 동일한 전송 수단을 통해 RTP 및 RTCP를 전송하게 됩니다.

가져오기를 수행할 때, 이 속성은 반드시 [[SenderTransport]] 슬롯의 값을 반환해야 합니다.

메서드

getCapabilities, 정적

정적 RTCRtpSender.getCapabilities() 메서드는 주어진 종류의 미디어를 송신하기 위해 사용자 에이전트가 지원하는 기능의 유형을, 어떤 리소스, 포트, 기타 상태도 예약하지 않고 알아내는 방법을 제공합니다.

getCapabilities 메서드가 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:

  1. kind를 메서드의 첫 번째 인자로 둡니다.

  2. kind"video""audio"도 아니면 null을 반환합니다.

  3. 새로운 RTCRtpCapabilities 사전을 반환하되, 해당 사전의 codecs 멤버는 kind에 대한 구현된 송신 코덱 목록으로 초기화하고, headerExtensions 멤버는 kind에 대해 구현된 송신용 헤더 확장 목록으로 초기화합니다.

kind가 주어졌을 때, 구현된 송신 코덱 목록은 주어진 kind(비디오 또는 오디오)의 미디어 송신에 대해 사용자 에이전트가 지원하는 코덱을 가장 낙관적으로 표현한 RTCRtpCodec 사전들의 구현 정의 목록입니다.

kind가 주어졌을 때, 구현된 송신용 헤더 확장 목록은 주어진 kind(비디오 또는 오디오)의 미디어 송신에 대해 사용자 에이전트가 지원하는 헤더 확장을 가장 낙관적으로 표현한 RTCRtpHeaderExtensionCapability 사전들의 구현 정의 목록입니다.

이러한 기능은 장치에 대해 일반적으로 지속되는 교차 출처 정보를 제공하므로 애플리케이션의 지문 채취 표면을 증가시킵니다. 프라이버시에 민감한 상황에서, 사용자 에이전트는 MAY 공통 부분집합만 보고하는 등의 완화책을 고려할 수 있습니다. (This is a fingerprinting vector.)

참고

반환된 코덱 기능은 setCodecPreferences() 알고리즘과 그 입력에 대해 언제 InvalidModificationError를 던지는지에 영향을 주며, 또한 송신을 위해 협상된 코덱에 대해 createOffer()createAnswer() 가 드러내는 정보와도 일관되어야 하며, 이를 통해 프라이버시 완화가 효과적이도록 해야 합니다.

setParameters

setParameters 메서드는 track이 원격 피어로 어떻게 인코딩되고 전송되는지를 업데이트합니다.

setParameters 메서드가 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:

  1. parameters를 메서드의 첫 번째 인자로 둡니다.
  2. senderRTCRtpSender 객체(이 메서드가 호출된 대상)로 둡니다.
  3. transceiverRTCRtpTransceiver 객체(즉, sendertransceiver.[[Sender]]인 객체)로 둡니다.
  4. transceiver.[[Stopping]]true이면, 거부된 새롭게 생성된 InvalidStateError로 완료되는 프로미스를 반환합니다.
  5. sender.[[LastReturnedParameters]]null이면, 거부된 새롭게 생성된 InvalidStateError로 완료되는 프로미스를 반환합니다.
  6. 다음의 setParameters 검증 단계를 실행하여 parameters를 검증합니다:
    1. encodingsparameters.encodings로 둡니다.
    2. codecsparameters.codecs로 둡니다.
    3. Candidate Addition 49:코덱을 RTCRtpEncodingParameters에 추가 (PR #2985)

      choosableCodecscodecs로 둡니다.

    4. Candidate Addition 49:코덱을 RTCRtpEncodingParameters에 추가 (PR #2985)

      choosableCodecs가 빈 목록이면, choosableCodecs를 transceiver.[[PreferredCodecs]]로 설정하고, 구현된 송신 코덱 목록에 포함되지 않은 코덱은 제외합니다.

    5. Candidate Addition 49:코덱을 RTCRtpEncodingParameters에 추가 (PR #2985)

      choosableCodecs가 여전히 빈 목록이면, choosableCodecs를 트랜시버의 종류에 대한 구현된 송신 코덱 목록으로 설정합니다.

    6. Nsender.[[SendEncodings]]에 저장된 RTCRtpEncodingParameters 의 개수로 둡니다.
    7. 다음 조건 중 하나라도 충족되면, 새롭게 생성된 InvalidModificationError거부된 프로미스를 반환합니다:
      • encodings.lengthN과 다릅니다.
      • encodings의 순서가 변경되었습니다.
      • parameters 안에 읽기 전용 매개변수(예: RID)로 표시된 항목이 있고, 그 값이 sender.[[LastReturnedParameters]]의 해당 매개변수 값과 다릅니다. 이는 transactionId에도 적용됩니다.
      • Candidate Addition 49:코덱을 RTCRtpEncodingParameters에 추가 (PR #2985)
        encodings의 임의의 encoding포함하는 codec이 choosableCodecs에 없으면(단, ignoreLevelstrue로 설정한 코덱 사전 일치 알고리즘을 사용), 해당합니다.
    8. transceiver kind"audio"이면, encodings 중 해당 멤버들을 포함하는 모든 항목에서 scaleResolutionDownBymaxFramerate를 제거합니다.

    9. transceiver kind"video"이면, encodings의 각 인코딩 중 포함scaleResolutionDownBy가 없는 항목에는 해당 멤버를 값 1.0으로 추가합니다.

    10. transceiver kind"video"이고, encodings 중 임의의 인코딩이 값이 1.0보다 작은 scaleResolutionDownBy포함하면, 새롭게 생성된 RangeError거부된 프로미스를 반환합니다.

    11. encodings의 각 인코딩이 값이 0.0 이상인 maxFramerate를 갖는지 확인합니다. 값 중 하나라도 이 요구 사항을 만족하지 못하면, 새롭게 생성된 RangeError거부된 프로미스를 반환합니다.

    12. Candidate Addition 49:코덱을 RTCRtpEncodingParameters에 추가 (PR #2985)

      사용자 에이전트가 어떤 인코딩에 대해서도 코덱 설정을 지원하지 않거나, 서로 다른 인코딩에서 다른 코덱 값을 혼합하는 것을 지원하지 않으면, 새롭게 생성된 OperationError거부된 프로미스를 반환합니다.

  7. p를 새로운 프로미스로 둡니다.
  8. 병렬로, 미디어 스택을 구성하여 sender.[[SenderTrack]]을(를) 전송할 때 parameters를 사용하도록 합니다.
    1. 미디어 스택이 parameters로 성공적으로 구성되면, 다음 단계를 실행하는 작업을 큐에 추가합니다:
      1. sender.[[LastReturnedParameters]]null로 설정합니다.
      2. sender.[[SendEncodings]]parameters.encodings로 설정합니다.
      3. Resolve하여 pundefined로 이행시킵니다.
    2. 미디어 스택을 구성하는 동안 오류가 발생하면, 다음 단계를 실행하는 작업을 큐에 추가합니다:
      1. 하드웨어 리소스를 사용할 수 없어서 오류가 발생한 경우, reject하여 p를 새롭게 생성된 RTCError로 거부하고, 그 errorDetail을 "hardware-encoder-not-available" 로 설정한 뒤, 이 단계를 중단합니다.
      2. 하드웨어 인코더가 parameters를 지원하지 않아 오류가 발생한 경우, reject하여 p를 새롭게 생성된 RTCError로 거부하고, 그 errorDetail을 "hardware-encoder-error" 로 설정한 뒤, 이 단계를 중단합니다.
      3. 그 외 모든 오류의 경우, reject하여 p를 새롭게 생성된 OperationError로 거부합니다.
  9. p를 반환합니다.

setParameters는 SDP 재협상을 발생시키지 않으며, Offer/Answer로 협상된 범위(envelope) 내에서 미디어 스택이 송신하거나 수신하는 내용을 변경하는 데에만 사용될 수 있습니다. RTCRtpSendParameters 사전의 속성은 이를 가능하게 하지 않도록 설계되었으므로, 변경할 수 없는 cname 같은 속성은 읽기 전용입니다. 비트전송률과 같은 다른 항목은 maxBitrate와 같은 제한을 통해 제어되며, 사용자 에이전트는 다른 장소(예: SDP)에 지정된 비트전송률 제약을 만족시키는 동시에 maxBitrate에 의해 지정된 최대치를 초과하지 않도록 보장해야 합니다.

getParameters

getParameters() 메서드는 RTCRtpSender 객체가 track을 원격 RTCRtpReceiver로 어떻게 인코딩하고 전송하는지에 대한 현재 매개변수를 반환합니다.

getParameters가 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:

  1. sender를 getter가 호출된 RTCRtpSender 객체로 둡니다.

  2. sender.[[LastReturnedParameters]]null이 아니면, sender.[[LastReturnedParameters]]를 반환하고, 이후 단계를 중단합니다.

  3. result를 다음과 같이 구성한 새로운 RTCRtpSendParameters 사전으로 둡니다:

  4. sender.[[LastReturnedParameters]]result로 설정합니다.

  5. 작업을 큐에 추가하여 sender.[[LastReturnedParameters]]null로 설정합니다.

  6. result를 반환합니다.

getParameterssetParameters와 함께 사용하여 다음과 같은 방식으로 매개변수를 변경할 수 있습니다:

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);
  }
}

setParameters 호출이 완료된 후, 이어지는 getParameters 호출은 수정된 매개변수 집합을 반환합니다.

replaceTrack

현재 RTCRtpSendertrack을 제공된 다른 트랙(또는 null 트랙)으로, 재협상 없이 교체하려고 시도합니다.

replaceTrack 메서드가 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:

  1. senderRTCRtpSender 객체(이 메서드가 호출된 대상)로 둡니다.

  2. transceiverRTCRtpTransceiver 객체( sender와 연관된)로 둡니다.

  3. connectionRTCPeerConnection 객체( sender와 연관된)로 둡니다.

  4. withTrack을 이 메서드의 인자로 둡니다.

  5. withTrack이 non-null이고 withTrack.kindtransceivertransceiver kind와 다르면, 새롭게 생성된 TypeError거부된 프로미스를 반환합니다.

  6. connection작업 체인에 다음 단계를 연결한 결과를 반환합니다:

    1. transceiver.[[Stopping]]true이면, 새롭게 생성된 InvalidStateError거부된 프로미스를 반환합니다.

    2. p를 새로운 프로미스로 둡니다.

    3. sendingtransceiver.[[CurrentDirection]]이 "sendrecv" 또는 "sendonly"이면 true, 그렇지 않으면 false로 둡니다.

    4. 다음 단계를 병렬로 실행합니다:

      1. sendingtrue이고 withTracknull이면, sender가 송신을 중지하도록 합니다.

      2. sendingtrue이고 withTracknull이 아니면, 이미 협상된 범위를 위반하지 않고 sender가 withTrack을 즉시 보낼 수 있는지 결정하고, 불가능하다면:

        1. 현재 realm의 전역 객체global로 하여 네트워킹 작업 소스전역 작업을 큐에 추가해, 새롭게 생성된 InvalidModificationError거부하여 p를 완료합니다.
        2. 이 단계를 중단합니다.
      3. sendingtrue이고 withTracknull이 아니면, sender가 기존 트랙 대신 withTrack 전송으로 매끄럽게 전환하도록 합니다.

      4. 다음 단계를 실행하는 작업을 큐에 추가합니다:

        1. connection.[[IsClosed]]true이면, 이 단계를 중단합니다.

        2. sender.[[SenderTrack]]withTrack으로 설정합니다.

        3. 현재 realm의 전역 객체global로 하여 네트워킹 작업 소스전역 작업을 큐에 추가해, resolve하여 pundefined로 이행시킵니다.

    5. p를 반환합니다.

참고

해상도 및/또는 프레임 레이트 변경은 협상을 필요로 하지 않을 수 있습니다. 협상이 필요할 수 있는 사례는 다음과 같습니다:

  1. [RFC6236]에 설명된 대로, 협상된 imageattr 경계를 벗어나는 값으로 해상도를 변경하는 경우.
  2. 프레임 레이트를 변경하여 코덱의 블록 레이트를 초과하게 되는 경우.
  3. 비디오 트랙의 원시(raw) 대 사전 인코딩(pre-encoded) 형식 차이.
  4. 오디오 트랙의 채널 수가 다른 경우.
  5. 인코딩도 수행하는 소스(일반적으로 하드웨어 인코더)는 협상된 코덱을 생성하지 못할 수 있으며, 마찬가지로 소프트웨어 소스는 인코딩 소스에 대해 협상된 코덱을 구현하지 못할 수 있습니다.
setStreams

이 sender의 트랙과 연관될 MediaStream들을 설정합니다.

setStreams 메서드가 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:

  1. sender를 이 메서드가 호출된 RTCRtpSender 객체로 둡니다.

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

  3. connection.[[IsClosed]]true이면, 예외를 발생시키고 InvalidStateError를 던집니다.

  4. streams를 메서드의 인자들로부터 구성한 MediaStream 객체들의 목록으로 둡니다. 인자 없이 호출된 경우 빈 목록으로 둡니다.

  5. sender.[[AssociatedMediaStreamIds]]를 빈 집합으로 설정합니다.

  6. streams의 각 stream에 대해, stream.id가 이미 없으면 [[AssociatedMediaStreamIds]]에 추가합니다.

  7. negotiation-needed 플래그를 업데이트하여 connection에 반영합니다.

getStats

이 sender에 대해서만 통계를 수집하고, 결과를 비동기적으로 보고합니다.

getStats() 메서드가 호출되면, 사용자 에이전트는 다음 단계를 MUST 수행합니다:

  1. selector를 이 메서드가 호출된 RTCRtpSender 객체로 둡니다.

  2. p를 새로운 프로미스로 두고, 다음 단계를 병렬로 실행합니다:

    1. selector가 지시하는 통계를 통계 선택 알고리즘에 따라 수집합니다.

    2. 현재 realm의 전역 객체global로 하여 네트워킹 작업 소스전역 작업을 큐에 추가해, 수집된 통계를 포함하는 RTCStatsReport 객체로 resolve하여 p를 이행합니다.

  3. p를 반환합니다.

5.2.1 RTCRtpParameters 사전

WebIDLdictionary RTCRtpParameters {
  required sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
  required RTCRtcpParameters rtcp;
  required sequence<RTCRtpCodecParameters> codecs;
};
사전 RTCRtpParameters 멤버
headerExtensions 타입 sequence<RTCRtpHeaderExtensionParameters>, 필수

RTP 헤더 확장에 대한 매개변수를 포함하는 시퀀스입니다. 읽기 전용 매개변수.

rtcp 타입 RTCRtcpParameters, 필수

RTCP에 사용되는 매개변수입니다. 읽기 전용 매개변수.

codecs 타입 sequence<RTCRtpCodecParameters>, 필수

RTCRtpSender가 선택할 미디어 코덱과 RTX, RED 및 FEC 메커니즘에 대한 항목을 포함하는 시퀀스입니다. RTX를 통한 재전송이 활성화된 각 미디어 코덱에 대해, codecsmimeType 속성이 audio/rtx 또는 video/rtx를 나타내는 항목과 "apt" 및 "rtx-time" 매개변수를 제공하는 sdpFmtpLine 속성이 포함된 항목이 존재합니다. 읽기 전용 매개변수.

5.2.2 RTCRtpSendParameters 사전

WebIDLdictionary RTCRtpSendParameters : RTCRtpParameters {
  required DOMString transactionId;
  required sequence<RTCRtpEncodingParameters> encodings;
};
사전 RTCRtpSendParameters 멤버
transactionId 타입 DOMString, 필수

마지막으로 적용된 매개변수 집합에 대한 고유 식별자입니다. setParameters가 이전 getParameters를 기반으로만 호출되도록 보장하며, 중간에 변경 사항이 없음을 보장합니다. 읽기 전용 매개변수.

encodings 타입 sequence<RTCRtpEncodingParameters>, 필수

미디어 RTP 인코딩에 대한 매개변수를 포함하는 시퀀스입니다.

5.2.3 RTCRtpReceiveParameters 사전

WebIDLdictionary RTCRtpReceiveParameters : RTCRtpParameters {
};

5.2.4 RTCRtpCodingParameters 사전

WebIDLdictionary RTCRtpCodingParameters {
  DOMString rid;
};
사전 RTCRtpCodingParameters 멤버
rid 타입 DOMString

설정된 경우, 이 RTP 인코딩은 [RFC9429] (섹션 5.2.1.)에서 정의된 RID 헤더 확장과 함께 전송됩니다. RID는 setParameters를 통해 수정할 수 없습니다. 송신 측에서 addTransceiver에서만 설정하거나 수정할 수 있습니다. 읽기 전용 매개변수.

5.2.5 RTCRtpEncodingParameters 사전

WebIDLdictionary RTCRtpEncodingParameters : RTCRtpCodingParameters {
  boolean active = true;
  RTCRtpCodec codec;
  unsigned long maxBitrate;
  double maxFramerate;
  double scaleResolutionDownBy;
};
사전 RTCRtpEncodingParameters 멤버
active 타입 boolean, 기본값 true

이 인코딩이 적극적으로 전송되고 있음을 나타냅니다. false로 설정하면 이 인코딩은 더 이상 전송되지 않습니다. true로 설정하면 이 인코딩이 전송됩니다. 값을 false로 설정해도 SSRC가 제거되지 않으므로 RTCP BYE는 전송되지 않습니다.

Candidate Addition 49:RTCRtpEncodingParameters에 codec 추가 (PR #2985)
codec 타입 RTCRtpCodec

이 인코딩의 RTP 스트림에 사용되는 코덱을 선택하는 선택적 값입니다. 값이 없으면 사용자 에이전트는 송신을 위해 협상된 모든 코덱을 사용할 수 있습니다.

codec이 설정되고 [[SendCodecs]]가 협상되었을 때, 사용자 에이전트는 [[SendCodecs]]에서 codec과 일치하는 첫 번째 항목을 송신을 위해 사용하도록 codec dictionary match 알고리즘에 따라 ignoreLevelstrue로 설정하여 사용 SHOULD 합니다.

maxBitrate 타입 unsigned long

존재하는 경우, 이 인코딩을 송신하는 데 사용할 수 있는 최대 비트전송률을 나타냅니다. 사용자 에이전트는 maxBitrate 값을 초과하지 않는 한, 인코딩 간에 대역폭을 자유롭게 할당할 수 있습니다. 인코딩은 또한 여기에서 지정된 최대값 아래에서 다른 제한(예: 전송당 또는 세션당 대역폭 제한)에 의해 추가로 제한될 수 있습니다. maxBitrate는 [RFC3890] 섹션 6.2.2에서 정의된 전송 독립 애플리케이션 특정 최대(TIAS) 대역폭과 동일한 방식으로 계산되며, IP 또는 TCP, UDP와 같은 다른 전송 계층을 고려하지 않은 최대 대역폭입니다. maxBitrate의 단위는 초당 비트입니다.

참고

비트전송률이 달성되는 방식은 미디어 및 인코딩에 따라 다릅니다. 비디오의 경우, 프레임은 항상 가능한 한 빨리 전송되지만, 비트전송률이 충분히 낮아질 때까지 프레임이 드롭될 수 있습니다. 따라서 비트전송률이 0이어도 하나의 프레임을 전송할 수 있습니다. 오디오의 경우, 선택한 인코딩에 충분한 대역폭을 제공하지 못하면 재생을 중단해야 할 수 있습니다.

maxFramerate 타입 double

이 멤버는 sender의 kind"video"인 경우에만 존재할 수 있습니다. 존재하는 경우, 초당 프레임 단위로 이 인코딩을 송신하는 데 사용할 수 있는 최대 프레임 레이트를 나타냅니다. 사용자 에이전트maxFramerate 값을 초과하지 않는 한, 인코딩 간에 대역폭을 자유롭게 할당할 수 있습니다.

setParameters()로 변경된 경우, 새로운 프레임 레이트는 현재 그림이 완료된 후 적용됩니다. 따라서 최대 프레임 레이트를 0으로 설정하면 다음 프레임에서 비디오가 멈추는 효과가 있습니다.

scaleResolutionDownBy 타입 double

이 멤버는 sender의 kind"video"인 경우에만 존재합니다. 비디오의 해상도는 전송 전에 주어진 값만큼 각 치수에서 축소됩니다. 예를 들어, 값이 2.0이면 비디오는 각 치수에서 2배로 축소되어 크기가 1/4인 비디오가 전송됩니다. 값이 1.0이면 비디오는 영향을 받지 않습니다. 값은 1.0 이상이어야 합니다. 기본적으로, 스케일링은 작은 해상도에서 큰 해상도로 오더링되는 방식으로 2배수로 역순으로 적용됩니다(예: 4:2:1). 레이어가 하나만 있는 경우, sender는 기본적으로 스케일링을 적용하지 않습니다 (즉, scaleResolutionDownBy가 1.0입니다).

5.2.6 RTCRtcpParameters 사전

WebIDLdictionary RTCRtcpParameters {
  DOMString cname;
  boolean reducedSize;
};
사전 RTCRtcpParameters 멤버
cname 타입 DOMString

RTCP가 사용하는 Canonical Name (CNAME)입니다 (예: SDES 메시지에서). 읽기 전용 매개변수.

reducedSize 타입 boolean

reduced size RTCP [RFC5506] 가 설정되어 있는지 여부입니다 (true인 경우) 또는 [RFC3550] 에서 지정된 compound RTCP인지 여부입니다 (false인 경우). 읽기 전용 매개변수.

5.2.7 RTCRtpHeaderExtensionParameters 사전

WebIDLdictionary RTCRtpHeaderExtensionParameters {
  required DOMString uri;
  required unsigned short id;
  boolean encrypted = false;
};
uri 타입 DOMString, 필수

[RFC5285]에서 정의된 RTP 헤더 확장의 URI입니다. 읽기 전용 매개변수.

id 타입 unsigned short, 필수

헤더 확장을 식별하기 위해 RTP 패킷에 삽입되는 값입니다. 읽기 전용 매개변수.

encrypted 타입 boolean

헤더 확장이 암호화되었는지 여부입니다. 읽기 전용 매개변수.

참고

RTCRtpHeaderExtensionParameters 사전은 애플리케이션이 RTCRtpSender 또는 RTCRtpReceiver 내에서 헤더 확장이 사용을 위해 설정되어 있는지 여부를 판단할 수 있도록 합니다. RTCRtpTransceiver transceiver에 대해, 애플리케이션은 SDP를 구문 분석하지 않고도 헤더 확장의 "direction" 매개변수 ([RFC5285] 섹션 5에서 정의됨)를 다음과 같이 판단할 수 있습니다:

  1. sendonly: 헤더 확장은 transceiver.sender.getParameters().headerExtensions에만 포함됩니다.
  2. recvonly: 헤더 확장은 transceiver.receiver.getParameters().headerExtensions에만 포함됩니다.
  3. sendrecv: 헤더 확장은 transceiver.sender.getParameters().headerExtensionstransceiver.receiver.getParameters().headerExtensions에 모두 포함됩니다.
  4. inactive: 헤더 확장은 transceiver.sender.getParameters().headerExtensionstransceiver.receiver.getParameters().headerExtensions에 포함되지 않습니다.

5.2.8 RTCRtpCodec 사전

WebIDLdictionary RTCRtpCodec {
  required DOMString mimeType;
  required unsigned long clockRate;
  unsigned short channels;
  DOMString sdpFmtpLine;
};
사전 RTCRtpCodec 멤버

RTCRtpCodec 사전은 코덱 객체에 대한 정보를 제공합니다.

mimeType 타입 DOMString, 필수

코덱 MIME 미디어 타입/서브타입입니다. 유효한 미디어 타입과 서브타입은 [IANA-RTP-2]에 나열되어 있습니다.

clockRate 타입 unsigned long, 필수

헤르츠 단위로 표현된 코덱 클럭 레이트입니다.

channels 타입 unsigned short

존재하는 경우, 최대 채널 수를 나타냅니다 (모노=1, 스테레오=2).

sdpFmtpLine 타입 DOMString

코덱에 해당하는 SDP의 a=fmtp 라인에서 "format specific parameters" 필드입니다. 존재하는 경우, [RFC9429] (섹션 5.8)에 정의되어 있습니다.

5.2.9 RTCRtpCodecParameters 사전

WebIDLdictionary RTCRtpCodecParameters : RTCRtpCodec {
  required octet payloadType;
};
사전 RTCRtpCodecParameters 멤버

RTCRtpCodecParameters 사전은 협상된 코덱에 대한 정보를 제공합니다. RTCRtpCodec에서 상속된 필드는 모두 읽기 전용 매개변수이어야 합니다.

RTCRtpSender의 경우, sdpFmtpLine 매개변수는 [[CurrentRemoteDescription]]에서 가져오며, RTCRtpReceiver의 경우, 로컬 설명 (해당 경우 [[PendingLocalDescription]], 그렇지 않으면 [[CurrentLocalDescription]])에서 가져옵니다.

payloadType 타입 octet, 필수

이 코덱을 식별하는 데 사용되는 RTP 페이로드 타입입니다. 읽기 전용 매개변수.

5.2.10 RTCRtpCapabilities 사전

WebIDLdictionary RTCRtpCapabilities {
  required sequence<RTCRtpCodec> codecs;
  required sequence<RTCRtpHeaderExtensionCapability> headerExtensions;
};
사전 RTCRtpCapabilities 멤버
codecs 타입 sequence<RTCRtpCodec>, 필수

지원되는 미디어 코덱 및 RTX, RED, FEC 메커니즘에 대한 항목입니다. 생성된 SDP 제안에서 고유한 페이로드 타입을 활용하는 조합만 제공해야 합니다. 예를 들어:

  1. 두 개의 H.264/AVC 코덱, 지원되는 두 개의 패킷화 모드 값 각각에 대해 하나씩.
  2. 다른 클럭 속도를 가진 두 개의 CN 코덱.

RTX를 통한 재전송에 대해 codecs에 단일 항목만 있어야 하며, sdpFmtpLine은 존재하지 않아야 합니다.

headerExtensions 타입 sequence<RTCRtpHeaderExtensionCapability>, 필수

지원되는 RTP 헤더 확장입니다.

5.2.11 RTCRtpHeaderExtensionCapability 사전

WebIDLdictionary RTCRtpHeaderExtensionCapability {
  required DOMString uri;
};
uri 타입 DOMString, 필수

[RFC5285]에서 정의된 RTP 헤더 확장의 URI입니다.

5.2.12 RTCSetParameterOptions 사전

WebIDLdictionary RTCSetParameterOptions {
};
사전 RTCSetParameterOptions 멤버

RTCSetParameterOptions는 확장성을 허용하기 위해 빈 사전으로 정의됩니다.

5.3 RTCRtpReceiver 인터페이스

RTCRtpReceiver 인터페이스는 애플리케이션이 MediaStreamTrack의 수신을 조사할 수 있게 합니다.

문자열 kindRTCRtpReceiver 생성을 수행하려면, 다음 단계를 실행합니다:

  1. receiver를 새로운 RTCRtpReceiver 객체로 둡니다.

  2. track을 새로운 MediaStreamTrack 객체로 둡니다 [GETUSERMEDIA]. track의 소스는 receiver가 제공하는 원격 소스입니다. 참고로 track.id사용자 에이전트에 의해 생성되며, 원격 측의 어떤 트랙 ID와도 매핑되지 않습니다.

  3. track.kindkind로 초기화합니다.

  4. track.label을 문자열 "remote "kind를 이어 붙인 결과로 초기화합니다.

  5. track.readyStatelive로 초기화합니다.

  6. track.mutedtrue로 초기화합니다. MediaStreamTrack 섹션에서 muted 속성이 MediaStreamTrack이 미디어 데이터를 수신 중인지 여부를 어떻게 반영하는지에 대해 설명합니다.

  7. receiver[[ReceiverTrack]] 내부 슬롯을 두고, track으로 초기화합니다.

  8. receiver[[ReceiverTransport]] 내부 슬롯을 두고 null로 초기화합니다.

  9. receiver[[LastStableStateReceiverTransport]] 내부 슬롯을 두고 null로 초기화합니다.

  10. receiver[[AssociatedRemoteMediaStreams]] 내부 슬롯을 두며, 이 수신기의 MediaStreamTrack 객체가 연관된 MediaStream 객체들의 목록을 나타내고, 빈 목록으로 초기화합니다.

  11. receiver[[LastStableStateAssociatedRemoteMediaStreams]] 내부 슬롯을 두고 빈 목록으로 초기화합니다.

  12. receiver[[ReceiveCodecs]] 내부 슬롯을 두며, 이는 RTCRtpCodecParameters 사전들의 목록을 나타내고, 빈 목록으로 초기화합니다.

  13. receiver[[LastStableStateReceiveCodecs]] 내부 슬롯을 두고 빈 목록으로 초기화합니다.

  14. receiver[[JitterBufferTarget]] 내부 슬롯을 두고 null로 초기화합니다.

  15. 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;
};

속성

track 타입 MediaStreamTrack, 읽기 전용

track 속성은 이 RTCRtpReceiver 객체 receiver와 연관된 트랙입니다.

track.stop()은 최종적이며, 클론에는 영향을 주지 않습니다. 또한 receiver.track.stop()receiver를 암묵적으로 중지시키지 않기 때문에, 수신기 보고(Receiver Reports)는 계속 전송됩니다. 가져오기를 수행할 때 이 속성은 반드시 [[ReceiverTrack]] 슬롯의 값을 반환해야 합니다.

transport 타입 RTCDtlsTransport, 읽기 전용, nullable

transport 속성은 수신기의 track에 대한 미디어가 RTP 패킷 형태로 수신되는 전송 수단입니다. RTCDtlsTransport 객체가 생성되기 전에는, transport 속성은 null입니다. 번들링이 사용될 때는, 여러 RTCRtpReceiver 객체가 하나의 transport를 공유하고, 동일한 전송 수단을 통해 RTP와 RTCP를 모두 수신합니다.

가져오기를 수행할 때 이 속성은 반드시 [[ReceiverTransport]] 슬롯의 값을 반환해야 합니다.

jitterBufferTarget 타입 DOMHighResTimeStamp, nullable

이 속성은 애플리케이션이 RTCRtpReceiver의 지터 버퍼가 보유할 미디어의 목표 지속시간(밀리초)을 지정할 수 있게 합니다. 이는 사용자 에이전트가 수행하는 버퍼링 양에 영향을 주며, 이는 다시 재전송과 패킷 손실 복구에 영향을 미칩니다. 목표 값을 변경하면 네트워크 지터로 인해 오디오 또는 비디오 프레임이 부족해질 위험과 재생 지연 간의 균형을 애플리케이션이 제어할 수 있습니다.

사용자 에이전트반드시 허용되는 최소 목표허용되는 최대 목표를 가져야 하며, 이는 네트워크 상태와 메모리 제약에 기반하여 사용자 에이전트가 제공할 수 있거나 제공하려는 바를 반영하고, 언제든지 변경될 수 있습니다.

참고

이는 목표 값입니다. 지연의 결과적 변화는 시간이 지나며 점진적으로 관찰될 수 있습니다. 수신기의 평균 지터 버퍼 지연은 jitterBufferDelay의 변화량을 jitterBufferEmittedCount의 변화량으로 나눠 측정할 수 있습니다.

DTX가 사용되는 경우에도 평균 지연이 예상됩니다. 예를 들어, DTX가 사용되고 정적 이후 패킷이 흐르기 시작하면, 더 큰 목표는 사용자 에이전트가 이러한 패킷을 재생하는 대신 버퍼링하도록 영향을 줄 수 있습니다.

가져오기를 수행할 때 이 속성은 반드시 [[JitterBufferTarget]] 내부 슬롯의 값을 반환해야 합니다.

설정 시, 사용자 에이전트반드시 다음 단계를 실행해야 합니다:

  1. 세터가 호출된 RTCRtpReceiver 객체를 receiver로 둡니다.

  2. 세터의 인자를 target으로 둡니다.

  3. target이 음수이거나 4000밀리초보다 크면 예외를 던져 RangeError를 발생시킵니다.

  4. receiver[[JitterBufferTarget]]target으로 설정합니다.

  5. trackreceiver[[ReceiverTrack]]로 둡니다.

  6. 병렬로 다음 단계를 실행하기 시작합니다:

    1. 기반 시스템에 새로운 target에 대해 업데이트하거나, targetnull이면 애플리케이션의 선호가 없음을 알립니다.

      track이 다른 RTCRtpReceiver의 트랙과 오디오/비디오 동기화를 위해 동기화되어 있다면, 사용자 에이전트는 두 수신기의 [[JitterBufferTarget]] 중 더 큰 값을 두 수신기에 모두 적용하는 것이 권장됩니다.

      기반 시스템이 지터 버퍼 목표를 적용할 때에는, 실제 지터 버퍼 목표가 항상 허용되는 최소 목표허용되는 최대 목표 범위로 제한되도록 지속적으로 보장합니다.

      참고

      사용자 에이전트가 요청된 값과 다른 목표(예: 네트워크 상태나 물리적 메모리 제약으로 인해)를 실제로 사용하게 되더라도, 이는 [[JitterBufferTarget]] 내부 슬롯에 반영되지 않습니다.

    2. 기반 시스템의 지터 버퍼 목표를 수정하는 작업은 사용자 경험을 해치지 않도록 내부 오디오 또는 비디오 버퍼링에 점진적으로 영향을 주는 것이 권장됩니다. 오디오 샘플 또는 비디오 프레임은 재생 전에 가감속되는 것이 권장되며, 이는 오디오/비디오 동기화나 혼잡 제어에 대응할 때와 유사합니다.

      가감속 비율은 네트워크 조건이나 수신된 오디오의 종류(예: 음성 또는 배경 소음)에 따라 달라질 수 있습니다. 패킷이 수신되고 있다고 가정할 때, 1초 분량의 버퍼링을 달성하는 데 몇 초가 걸릴 수 있지만 30초를 넘지 않는 것이 권장됩니다. 속도는 오디오와 비디오 간에 서로 다를 수 있습니다.

      참고

      오디오의 경우, 가감속은 insertedSamplesForDecelerationremovedSamplesForAcceleration로 측정될 수 있습니다. 비디오의 경우, 동일한 프레임이 여러 번 렌더링되거나 프레임이 드롭될 수 있습니다.

메서드

getCapabilities, 정적

정적 RTCRtpReceiver.getCapabilities() 메서드는 주어진 종류의 미디어를 수신하기 위해 사용자 에이전트가 지원하는 기능의 유형을, 어떤 리소스, 포트, 기타 상태도 예약하지 않고 알아내는 방법을 제공합니다.

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

  1. kind를 메서드의 첫 번째 인자로 둡니다.

  2. kind"video""audio"도 아니면 null을 반환합니다.

  3. 새로운 RTCRtpCapabilities 사전을 반환하되, 해당 사전의 codecs 멤버를 kind에 대한 구현된 수신 코덱 목록으로 초기화하고, headerExtensions 멤버를 구현된 수신용 헤더 확장 목록으로 초기화합니다.

kind가 주어졌을 때, 구현된 수신 코덱 목록구현 정의RTCRtpCodec 사전들의 목록으로, 주어진 kind(비디오 또는 오디오)의 미디어 수신을 위해 사용자 에이전트가 지원하는 코덱을 가장 낙관적으로 표현합니다.

kind가 주어졌을 때, 구현된 수신용 헤더 확장 목록구현 정의RTCRtpHeaderExtensionCapability 사전들의 목록으로, 주어진 kind(비디오 또는 오디오)의 미디어 수신을 위해 사용자 에이전트가 지원하는 헤더 확장에 대한 낙관적 관점을 나타냅니다.

이러한 기능은 장치에 대해 일반적으로 지속되는 교차 출처 정보를 제공하므로 애플리케이션의 지문 채취 표면을 증가시킵니다. 프라이버시에 민감한 상황에서, 사용자 에이전트는 할 수 있습니다 공통 부분집합만 보고하는 등의 완화책을 고려할 수 있습니다. (This is a fingerprinting vector.)

참고

반환된 코덱 기능은 setCodecPreferences() 알고리즘과, 해당 알고리즘이 어떤 입력에서 InvalidModificationError를 던지는지에 영향을 줍니다. 또한 수신을 위해 협상된 코덱에 대해 createOffer()createAnswer() 가 드러내는 정보와도 일관되어야 하며, 이를 통해 프라이버시 완화가 효과적이도록 해야 합니다.

getParameters

getParameters() 메서드는 RTCRtpReceiver 객체의 track이 어떻게 디코딩되는지에 대한 현재 매개변수를 반환합니다.

getParameters가 호출되면, RTCRtpReceiveParameters 사전은 다음과 같이 구성됩니다:

  • headerExtensions 시퀀스는 수신기가 현재 수신할 준비가 된 헤더 확장에 기반하여 채워집니다.
  • codecs[[ReceiveCodecs]] 내부 슬롯의 값으로 설정됩니다.

    참고
    로컬 설명과 원격 설명 모두 이 코덱 목록에 영향을 줄 수 있습니다. 예를 들어, 세 개의 코덱이 제안되면, 수신기는 각 코덱을 수신할 준비가 되어 있으며 getParameters에서 이들을 모두 반환할 것입니다. 그러나 원격 엔드포인트가 두 개에 대해서만 응답하면, 부재한 코덱은 더 이상 getParameters에서 반환되지 않는데, 이는 수신기가 더 이상 해당 코덱을 수신할 준비가 필요하지 않기 때문입니다.
  • rtcp.reducedSize는 수신기가 현재 reduced-size RTCP 패킷을 수신할 준비가 되어 있으면 true, 그렇지 않으면 false로 설정됩니다. rtcp.cname은 포함되지 않습니다.
getContributingSources

지난 10초 동안 이 RTCRtpReceiver가 수신한 각 고유한 CSRC 식별자에 대해, 내림차순 timestamp 순서로 RTCRtpContributingSource를 반환합니다.

getSynchronizationSources

지난 10초 동안 이 RTCRtpReceiver가 수신한 각 고유한 SSRC 식별자에 대해, 내림차순 timestamp 순서로 RTCRtpSynchronizationSource를 반환합니다.

getStats

이 수신기에 대해서만 통계를 수집하고, 결과를 비동기적으로 보고합니다.

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

  1. selector를 이 메서드가 호출된 RTCRtpReceiver 객체로 둡니다.

  2. p를 새로운 프로미스로 두고, 다음 단계를 병렬로 실행합니다:

    1. selector가 지정한 통계를 통계 선택 알고리즘에 따라 수집합니다.

    2. 현재 렐름의 전역 객체global로 하여 네트워킹 작업 소스전역 작업을 큐에 추가하여, 수집된 통계를 포함하는 RTCStatsReport 객체로 resolve하여 p를 이행합니다.

  3. p를 반환합니다.

RTCRtpContributingSourceRTCRtpSynchronizationSource 사전은 각각 주어진 기여 소스(CSRC) 또는 동기화 소스(SSRC)에 대한 정보를 포함합니다. 하나 이상의 RTP 패킷으로부터의 오디오 또는 비디오 프레임이 RTCRtpReceiverMediaStreamTrack에 전달될 때, 사용자 에이전트는 반드시 이러한 패킷의 내용을 기반으로 RTCRtpContributingSourceRTCRtpSynchronizationSource 사전에 대한 관련 정보를 업데이트하는 작업을 큐에 넣어야 합니다. SSRC 식별자에 해당하는 RTCRtpSynchronizationSource 사전의 정보는 매번 업데이트되며, RTP 패킷에 CSRC 식별자가 포함되어 있다면 해당 CSRC 식별자에 해당하는 RTCRtpContributingSource 사전의 정보 또한 업데이트됩니다. 사용자 에이전트는 반드시 RTP 타임스탬프가 오름차순이 되도록 RTP 패킷을 처리해야 합니다. 사용자 에이전트는 반드시 이전 10초 동안 RTCRtpReceiverMediaStreamTrack에 전달된 RTP 패킷의 정보를 유지해야 합니다.

참고
MediaStreamTrack이 재생을 위한 어떤 싱크에도 연결되어 있지 않더라도, getSynchronizationSourcesgetContributingSources는 트랙이 종료되지 않는 한 최신 정보를 반환합니다. 싱크는 RTP 패킷을 디코딩하기 위한 전제 조건이 아닙니다.
참고
적합성 섹션에 명시된 대로, 알고리즘으로 표현된 요구 사항은 최종 결과가 동등한 한 어떤 방식으로든 구현될 수 있습니다. 따라서, 구현은 매 프레임마다 실제로 작업을 큐에 넣을 필요는 없으며, 단일 이벤트 루프 작업 실행 내에서 특정 RTCRtpReceiver에 대해 반환되는 모든 RTCRtpSynchronizationSourceRTCRtpContributingSource 사전이 RTP 스트림의 단일 시점의 정보를 포함하도록 하면 됩니다.
WebIDLdictionary RTCRtpContributingSource {
  required DOMHighResTimeStamp timestamp;
  required unsigned long source;
  double audioLevel;
  required unsigned long rtpTimestamp;
};

사전 RTCRtpContributingSource 멤버

timestamp 타입 DOMHighResTimeStamp, 필수

이 소스에서 기원한 RTP 패킷의 프레임이 RTCRtpReceiverMediaStreamTrack에 가장 최근에 전달된 시간을 나타내는 timestamp입니다. timestamp는 해당 시점의 Performance.timeOrigin + Performance.now()로 정의됩니다.

source 타입 unsigned long, 필수

기여 소스 또는 동기화 소스의 CSRC 또는 SSRC 식별자입니다.

audioLevel 타입 double

오디오 수신기에만 존재합니다. 0..1(선형) 범위의 값이며, 1.0은 0 dBov, 0은 무음을 나타내고, 0.5는 0 dBov로부터 약 6 dBSPL의 음압 수준 변화를 나타냅니다.

CSRC의 경우, RFC 6465 헤더 확장이 존재하면 [RFC6465]에 정의된 레벨 값에서 변환되어야(MUST) 하며, 그렇지 않으면 이 멤버는 반드시 존재하지 않아야 합니다.

SSRC의 경우, 수신된 패킷에 RFC 6464 헤더 확장이 존재하면 [RFC6464]에 정의된 레벨 값에서 변환되어야(MUST) 합니다. 수신된 패킷에 RFC 6464 헤더 확장이 존재하지 않는 경우(예: 다른 엔드포인트가 사용자 에이전트가 아니거나 레거시 엔드포인트인 경우), 이 값은 권장되지만 존재하지 않을 수 있습니다.

두 RFC 모두 레벨을 0에서 127 사이의 정수 값으로 정의하며, 이는 시스템이 가능한 가장 큰 신호에 대한 음압 수준(음의 데시벨)을 나타냅니다. 따라서 0은 시스템이 인코딩할 수 있는 가장 큰 신호를, 127은 무음을 나타냅니다.

이러한 값을 선형 0..1 범위로 변환하려면, 127은 0으로 변환하고, 그 외의 값은 다음 식을 사용하여 변환합니다: 10^(-rfc_level/20).

rtpTimestamp 타입 unsigned long, 필수

[RFC3550] 섹션 5.1에 정의된, timestamp 시점에 재생된 미디어의 RTP 타임스탬프입니다.

WebIDLdictionary RTCRtpSynchronizationSource : RTCRtpContributingSource {};

RTCRtpSynchronizationSource 사전은 SSRC에서만 얻을 수 있는 데이터를 노출하기 위한 명세의 확장 지점으로 사용될 것으로 예상됩니다.

5.4 RTCRtpTransceiver 인터페이스

RTCRtpTransceiver 인터페이스는 공통의 미디어 스트림 "identification-tag"를 공유하는 RTCRtpSenderRTCRtpReceiver의 조합을 나타냅니다. [RFC9429] (섹션 3.4.1.)에 정의된 바와 같이, RTCRtpTransceiver는 그 "mid" 속성이 null이 아니고 미디어 스트림 "identification-tag"미디어 설명 내의 값과 일치하는 경우, 해당 미디어 설명연결됨(associated)이라고 하며; 그렇지 않으면 그 미디어 설명과 연결 해제됨(disassociated)이라고 합니다.

참고

RTCRtpTransceiver는 현재 설명과는 여전히 연결 해제된 상태인 동안에도 RFC9429의 새로운 보류(pending) 설명과 연결될 수 있습니다. 이는 협상이 필요한지 확인 과정에서 발생할 수 있습니다.

RTCRtpTransceiver트랜시버 종류(transceiver kind)는 연관된 RTCRtpReceiverMediaStreamTrack 객체의 kind로 정의됩니다.

RTCRtpTransceiver 생성RTCRtpReceiver 객체 receiver, RTCRtpSender 객체 sender, 그리고 RTCRtpTransceiverDirectiondirection으로 수행하려면 다음 단계를 실행합니다:

  1. transceiver를 새로운 RTCRtpTransceiver 객체로 둡니다.

  2. transceiver[[Sender]] 내부 슬롯을 두고, sender로 초기화합니다.

  3. transceiver[[Receiver]] 내부 슬롯을 두고, receiver로 초기화합니다.

  4. transceiver[[Stopping]] 내부 슬롯을 두고, false로 초기화합니다.

  5. transceiver[[Stopped]] 내부 슬롯을 두고, false로 초기화합니다.

  6. transceiver[[Direction]] 내부 슬롯을 두고, direction으로 초기화합니다.

  7. transceiver[[Receptive]] 내부 슬롯을 두고, false로 초기화합니다.

  8. transceiver[[CurrentDirection]] 내부 슬롯을 두고 null로 초기화합니다.

  9. transceiver[[FiredDirection]] 내부 슬롯을 두고, null로 초기화합니다.

  10. transceiver[[PreferredCodecs]] 내부 슬롯을 두고, 빈 목록으로 초기화합니다.

  11. transceiver[[JsepMid]] 내부 슬롯을 두고 null로 초기화합니다. 이는 [RFC9429] (섹션 5.2.1., 섹션 5.3.1.)에서 정의된 "RtpTransceiver mid property"이며, 그곳에서만 수정됩니다.

  12. transceiver[[Mid]] 내부 슬롯을 두고 null로 초기화합니다.

  13. transceiver를 반환합니다.

참고
트랜시버를 생성하더라도 기본이 되는 RTCDtlsTransportRTCIceTransport 객체는 생성되지 않습니다. 이는 세션 설명 설정 과정의 일부로만 발생합니다.
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);
};

속성

mid 타입 DOMString, 읽기 전용, nullable

mid 속성은 로컬 및 원격 설명에서 협상되고 존재하는 미디어 스트림 "identification-tag"입니다. 가져오기를 수행할 때, 이 속성은 반드시 [[Mid]] 슬롯의 값을 반환해야 합니다.

sender 타입 RTCRtpSender, 읽기 전용

sender 속성은 mid = [[Mid]]로 전송될 수 있는 RTP 미디어에 대응하는 RTCRtpSender를 노출합니다. 가져오기를 수행할 때, 이 속성은 반드시 [[Sender]] 슬롯의 값을 반환해야 합니다.

receiver 타입 RTCRtpReceiver, 읽기 전용

receiver 속성은 mid = [[Mid]]로 수신될 수 있는 RTP 미디어에 대응하는 RTCRtpReceiver입니다. 가져오기를 수행할 때, 이 속성은 반드시 [[Receiver]] 슬롯의 값을 반환해야 합니다.

direction 타입 RTCRtpTransceiverDirection

[RFC9429] (섹션 4.2.4.)에 정의된 대로, direction 속성은 이 트랜시버의 선호하는 방향(preferred direction)을 나타내며, 이는 createOffercreateAnswer 호출에서 사용됩니다. 방향성 업데이트는 즉시 적용되지 않습니다. 대신 이후의 createOffercreateAnswer 호출은 관련 미디어 설명sendrecv, sendonly, recvonly 또는 inactive로 표시합니다 (표시는 [RFC9429] (섹션 5.2.2., 섹션 5.3.2.)에 정의됨).

가져오기를 수행할 때, 사용자 에이전트는 반드시 다음 단계를 실행해야 합니다:

  1. transceiver를 게터가 호출된 RTCRtpTransceiver 객체로 둡니다.

  2. transceiver.[[Stopping]]true이면, "stopped"를 반환합니다.

  3. 그렇지 않으면 [[Direction]] 슬롯의 값을 반환합니다.

설정 시, 사용자 에이전트는 반드시 다음 단계를 실행해야 합니다:

  1. transceiver를 세터가 호출된 RTCRtpTransceiver 객체로 둡니다.

  2. connectiontransceiver와 연관된 RTCPeerConnection 객체로 둡니다.

  3. transceiver.[[Stopping]]true이면, 예외를 던져 InvalidStateError를 발생시킵니다.

  4. newDirection을 세터의 인자로 둡니다.

  5. newDirectiontransceiver.[[Direction]]과 같다면, 이 단계를 중단합니다.

  6. newDirection이 "stopped"와 같다면, 예외를 던져 TypeError를 발생시킵니다.

  7. transceiver.[[Direction]]newDirection으로 설정합니다.

  8. 협상 필요 플래그를 업데이트합니다 (connection에 대해).

currentDirection 타입 RTCRtpTransceiverDirection, 읽기 전용, nullable

[RFC9429] (섹션 4.2.5.)에 정의된 대로, currentDirection 속성은 이 트랜시버에 대해 협상된 현재 방향을 나타냅니다. currentDirection의 값은 RTCRtpEncodingParametersactive 값과 독립적이며, 한 값으로부터 다른 값을 유추할 수는 없습니다. 이 트랜시버가 오퍼/응답 교환에 한 번도 표현된 적이 없다면 값은 null입니다. 트랜시버가 stopped 상태라면, 값은 "stopped"입니다.

가져오기를 수행할 때, 사용자 에이전트는 반드시 다음 단계를 실행해야 합니다:

  1. transceiver를 게터가 호출된 RTCRtpTransceiver 객체로 둡니다.

  2. transceiver.[[Stopped]]true이면, "stopped"를 반환합니다.

  3. 그렇지 않으면 [[CurrentDirection]] 슬롯의 값을 반환합니다.

메서드

stop

트랜시버가 이미 stopped 상태가 아닌 한, 트랜시버를 stopping 상태로 되돌릴 수 없게(irreversibly) 표시합니다. 이는 즉시 트랜시버의 sender가 더 이상 전송하지 않게 하고, receiver가 더 이상 수신하지 않게 합니다. stop()을 호출하면, 협상 필요 플래그를 업데이트하여, RTCRtpTransceiver와 연관된 RTCPeerConnection에도 반영합니다.

stopping 상태의 트랜시버는 향후 createOffer 호출 시, 해당 트랜시버에 대응하는 미디어 설명에서 포트를 0으로 생성하게 합니다. 이는 [RFC9429] (섹션 4.2.1.)에 정의된 바와 같습니다 (이 경우에 한해 사용자 에이전트는 RFC9429 목적상 stopping 트랜시버를 stopped로 취급해야 함). 그러나 [RFC8843]와의 문제를 피하기 위해, stopping이지만 stopped는 아닌 트랜시버는 createAnswer에 영향을 주지 않습니다.

stopped 트랜시버는 향후 createOffer 또는 createAnswer 호출이 해당 트랜시버에 대응하는 미디어 설명에서 포트를 0으로 생성하도록 합니다 (정의는 [RFC9429] (섹션 4.2.1.) 참조).

트랜시버는 stopping 상태를 유지하며, 원격 오퍼 또는 응답의 거부된 m-line을 setRemoteDescription이 처리하여 stopped가 되지 않는 한 계속됩니다.

참고

stopping이지만 stopped는 아닌 트랜시버는 항상 협상이 필요합니다. 실제로는 트랜시버에서 stop()를 호출하면, 양 단에서 협상이 완료되도록 허용되는 경우 결국 stopped가 됩니다.

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

  1. transceiver를 메서드가 호출된 RTCRtpTransceiver 객체로 둡니다.

  2. connectiontransceiver와 연관된 RTCPeerConnection 객체로 둡니다.

  3. connection.[[IsClosed]]true이면, 예외를 던져 InvalidStateError를 발생시킵니다.

  4. transceiver.[[Stopping]]true이면, 이 단계를 중단합니다.

  5. 전송 및 수신 중지transceiver에 대해 수행합니다.

  6. 협상 필요 플래그를 업데이트합니다 (connection에 대해).

transceiver와 선택적으로 기본값이 false인 불리언 disappear가 주어졌을 때의 전송 및 수신 중지 알고리즘은 다음과 같습니다:

  1. sendertransceiver.[[Sender]]로 둡니다.

  2. receivertransceiver.[[Receiver]]로 둡니다.

  3. 병렬로, sender로 미디어 전송을 중지하고, [RFC3550]에 명시된 대로 sender가 전송하고 있던 각 RTP 스트림에 대해 RTCP BYE를 전송합니다.

  4. 병렬로, receiver로 미디어 수신을 중지합니다.

  5. disappearfalse이면, receiver[[ReceiverTrack]]종료되도록 하는 단계를 실행합니다. 이는 이벤트를 발생시킵니다.

  6. transceiver.[[Direction]]을 "inactive"로 설정합니다.

  7. transceiver.[[Stopping]]true로 설정합니다.

transceiver와 선택적으로 기본값이 false인 불리언 disappear가 주어졌을 때의 RTCRtpTransceiver 중지 알고리즘은 다음과 같습니다:

  1. transceiver.[[Stopping]]false이면, 전송 및 수신 중지transceiverdisappear와 함께 수행합니다.

  2. transceiver.[[Stopped]]true로 설정합니다.

  3. transceiver.[[Receptive]]false로 설정합니다.

  4. transceiver.[[CurrentDirection]]null로 설정합니다.

setCodecPreferences
Candidate Addition 51:setCodecPreferences가 전송 및 수신 코덱 둘 다를 지원(방향으로 필터링) (PR #3018)

setCodecPreferences 메서드는 사용자 에이전트의 기본 코덱 선호도를 협상에 대한 입력으로 재정의합니다. WhenWhen createOffer 또는 createAnswer를 사용하여 세션 설명을 생성할 때, 사용자 에이전트MUST use the indicated codecs MUST direction에 따라 선호 코덱을 필터링하며, 그 결과 비어 있지 않은 목록이 되면 the order해당 코덱들을 codecs 인자의 순서대로 해당 media section미디어 섹션에 대해 RTCRtpTransceiver에 대응하도록 사용(MUST)해야 합니다.

이 메서드를 사용하면 특정 코덱(RTX/RED/FEC 포함)의 협상을 비활성화할 수 있으며 . It also allows an application to cause a remote peer to prefer the codec that appears first in the list for sending 비활성화할 코덱을 나열하여 for sending그 외 모든 코덱만 나열하는 방식으로 설정할 수 있습니다.

참고

m= 섹션이 수신에 사용되는 경우, SDP(오퍼와 응답 모두)에서 코덱의 순서는 로컬 엔드포인트가 수신을 선호하는 코덱을 원격 엔드포인트에 알려줍니다. m= 섹션이 수신에 사용되지 않더라도, 자체 코덱 선호도가 없는 응답자는 SDP 응답에서 동일한 순서를 기본으로 사용할 수 있습니다.

참고

RTCRtpSender는 기본적으로 원격 엔드포인트가 수신을 선호한다고 표시한 것을 전송하지만, 애플리케이션은 협상된 codecs 중에서 어느 코덱을 전송할지 setParameters를 호출하고 codec를 지정하여 변경할 수 있습니다. RTCRtpReceiver는 협상된 어떠한 코덱도 수신할 준비가 되어 있습니다.

코덱 선호도는 이 RTCRtpTransceiver가 포함된 모든 createOffercreateAnswer 호출에 대해 이 메서드가 다시 호출될 때까지 유지됩니다. codecs를 빈 시퀀스로 설정하면 코덱 선호도가 기본값으로 재설정됩니다 시퀀스로 설정하거나, direction 필터링 후 빈 목록이 되면 기본 코덱 선호도가 적용됩니다.

참고

코덱은 각 m= 섹션 아래에 나열된 SDP에서 페이로드 유형을 정의하며, 이는 페이로드 유형과 코덱 간의 매핑을 정의합니다. 이러한 페이로드 유형은 m=video 또는 m=audio 줄에서 선호 순서대로 참조되며, 협상되지 않은 코덱은 [RFC8829RFC9429] 섹션 5.2.1에 정의된 대로 이 목록에 나타나지 않습니다. 이전에 협상된 코덱이 이후 제거되면 m=video 또는 m=audio 줄에서 사라지며, 해당 코덱 페이로드 유형은 향후 오퍼 또는 응답에서 재사용되지 않아야 하며, 페이로드 유형의 매핑에서도 제거될 수 있습니다.

codecs 시퀀스를 setCodecPreferences 에 전달할 경우, codecs를 설정하려는 시도를 거부합니다. 이는 일치하지 않는 코덱이 반환된 경우에만 가능합니다 다음에서 발견된 경우에만 가능합니다: RTCRtpSender.getCapabilities(kind) 또는 RTCRtpReceiver.getCapabilities(kind), 여기서 kind는 메서드가 호출된 RTCRtpTransceiver의 종류입니다. 또한, RTCRtpCodecCapability 사전 멤버는 수정될 수 없습니다. codecs가 이러한 요구 사항을 충족하지 않으면, 사용자 에이전트는 반드시 throw를 호출하고, InvalidModificationError를 던져야 합니다.

참고

[SDP] 권고에 따라, createAnswer를 호출하는 경우, 코덱 선호도와 제안서에 나타나는 코덱의 공통 부분만 사용해야 합니다. 예를 들어, 코덱 선호도가 "C, B, A"이고, 제안서에 "A, B" 코덱만 포함된 경우 응답에는 "B, A"만 포함되어야 합니다. 하지만 [RFC8829] (섹션 5.3.1.)은 제안서에 없는 코덱을 추가하는 것을 허용하므로, 구현에 따라 동작이 다를 수 있습니다.

setCodecPreferences() 가 호출되면, 가 호출될 때, 사용자 에이전트반드시 다음 단계를 실행해야 합니다:

  1. transceiver를 이 메서드가 호출된 RTCRtpTransceiver 객체로 둡니다.

  2. codecs를 첫 번째 인자로 둡니다.

  3. codecs가 빈 목록이면, transceiver.[[PreferredCodecs]]codecs로 설정하고 이 단계를 중단합니다.

  4. codecs에서 중복 값을 제거하되, 각 값의 첫 번째 발생 위치는 유지합니다.

  5. kindtransceiver트랜시버 종류로 둡니다.

  6. codecCapabilitiesRTCRtpSender.getCapabilities(kind).codecsRTCRtpReceiver.getCapabilities(kind).codecs의 합집합으로 둡니다.

  7. codecs의 각 codec에 대해,

    1. codeccodecCapabilities의 어떤 코덱과도 일치하지 않으면, InvalidModificationError를 던집니다.

  8. codecs가 RTX, RED, FEC 또는 Comfort Noise에 대한 항목만 포함하거나 빈 집합이면, InvalidModificationError를 던집니다. 이는 transceiver.direction에 관계없이 항상 제안할 수 있도록 보장합니다.

  9. transceiver.[[PreferredCodecs]]codecs로 설정합니다.

두 개의 RTCRtpCodec 사전 firstsecond가 주어지고, 지정되지 않은 경우 기본값이 falseignoreLevels 불리언이 주어졌을 때의 codec dictionary match 알고리즘은 다음과 같습니다:

  1. first.mimeTypesecond.mimeTypeASCII 대소문자 구분 없이 일치하지 않으면, false를 반환합니다.

  2. first.clockRatesecond.clockRate와 다르면, false를 반환합니다.

  3. first.channelssecond.channels 중 어느 하나(두 개는 아님)만 없거나, 둘 다 존재하지만 first.channelssecond.channels와 다르면, false를 반환합니다.

  4. first.sdpFmtpLinesecond.sdpFmtpLine 중 어느 하나(두 개는 아님)만 없으면, false를 반환합니다.

  5. first.sdpFmtpLinesecond.sdpFmtpLine가 모두 존재하면 다음 단계를 실행합니다:

    1. first.sdpFmtpLinesecond.sdpFmtpLine 중 어느 하나가 키-값 형식이 아니라면, first.sdpFmtpLinesecond.sdpFmtpLine 간의 동등성 비교 결과를 반환합니다.

    2. firstMediaFormatfirst.sdpFmtpLine에서 구성된 미디어 포맷의 키-값 맵으로 두고, secondMediaFormatsecond.sdpFmtpLine에서 구성된 미디어 포맷의 키-값 맵으로 둡니다.

      참고

      어떤 FMTP 파라미터가 미디어 포맷을 구성하는지는 코덱에 따라 다릅니다. 어떤 경우에는 파라미터가 생략되더라도 추론될 수 있으며, 이러한 경우에도 해당 코덱의 미디어 포맷의 일부입니다.

    3. firstMediaFormatsecondMediaFormat과 같지 않으면, false를 반환합니다.

    4. Candidate Correction 52:level-id가 달라도 두 코덱은 동일로 간주 (PR #3023)

      ignoreLevelsfalse이고, first.sdpFmtpLinesecond.sdpFmtpLine에서 유추된 준수 가능한 최고 비트스트림 레벨이 서로 다르면, false를 반환합니다.

      참고

      ignoreLevelstrue인 경우에도, 일부 코덱(H.264 등)은 미디어 포맷에 레벨을 포함하므로, 레벨을 무시하려면 코덱별 파싱이 필요합니다.

  6. true를 반환합니다.

참고

설정된 경우, 오퍼러의 수신 코덱 선호도가 오퍼의 코덱 순서를 결정합니다. 응답자가 자체 코덱 선호도가 없다면 동일한 순서가 응답에도 사용됩니다. 그러나 응답자에게도 코덱 선호도가 있으면, 응답에서 그 선호도가 순서를 재정의합니다. 이 경우 오퍼러의 선호도는 어떤 코덱이 제안되는지에는 영향을 주지만 최종 순서에는 영향을 주지 않습니다.

5.4.1 동시 송출(simulcast) 기능

동시 송출 전송 기능은 addTransceiver 메서드의 sendEncodings 인자를 통해 활성화되거나, 원격 오퍼로 동시 수신을 요청하는 setRemoteDescription 메서드를 통해 활성화됩니다. 두 방법 모두 RTCPeerConnection 객체의 메서드입니다. 추가로 각 RTCRtpSender 객체의 setParameters 메서드를 사용하여 이 기능을 점검하고 수정할 수 있습니다.

RTCRtpSender동시 송출 엔벨로프(simulcast envelope)는 단일 송출(unicast)이 아닌 동시 송출(simulcast) 전송을 포함하는 첫 번째 성공적인 협상에서 설정되며, 전송 가능한 동시 송출 스트림의 최대 개수와 encodings의 순서를 포함합니다. 이 동시 송출 엔벨로프는 이후 재협상에서 범위가 좁아질 수(레이어 수 감소) 있으나, 다시 확장(reexpand)할 수는 없습니다. 개별 동시 송출 스트림의 특성은 setParameters 메서드를 사용해 수정할 수 있지만, 동시 송출 엔벨로프 자체는 해당 메서드로 변경할 수 없습니다.

동시 송출을 구성하는 한 가지 방법은 sendEncodings 옵션을 사용해 addTransceiver()를 호출하는 것입니다. addTrack() 메서드에는 동시 송출을 구성하는 데 필요한 sendEncodings 인자가 없지만, 사용자 에이전트가 응답자(answerer)일 때 송신자가 동시 송출로 승격될 수 있습니다. 원격 동시 수신 오퍼와 함께 setRemoteDescription 메서드를 호출하면, 지정된 세션 설명에 기술된 레이어를 포함하도록 RTCRtpSender제안된 엔벨로프(proposed envelope)가 구성됩니다. 이 설명이 롤백되지 않는 한, 협상이 완료될 때 이 제안된 엔벨로프는 위에서 설명한 것과 같이 RTCRtpSender동시 송출 엔벨로프가 됩니다. 마찬가지로, 이 동시 송출 엔벨로프는 이후 재협상에서 좁혀질 수 있으나, 다시 확장할 수는 없습니다.

Candidate Correction 12:RTP Pause/Resume 비지원 명시 (PR #2755)

setParameters로는 동시 송출 엔벨로프를 수정할 수 없지만, 전송되는 스트림 수와 해당 스트림의 특성을 제어하는 것은 여전히 가능합니다. setParameters를 사용하여, active 멤버를 false로 설정해 동시 송출 스트림을 비활성화하거나, active 멤버를 true로 설정해 다시 활성화할 수 있습니다. [RFC7728] (RTP Pause/Resume)은 지원되지 않으며, SDP 오퍼/응답을 통한 pause/resume 시그널링도 지원되지 않습니다. setParameters를 사용하여, maxBitrate와 같은 속성을 수정함으로써 스트림 특성을 변경할 수 있습니다.

참고

동시 송출은 자주 여러 인코딩을 SFU로 전송하는 데 사용되며, SFU는 그중 하나의 동시 송출 스트림을 최종 사용자에게 포워딩합니다. 따라서 사용자 에이전트는 모든 동시 송출 스트림이 각각 독립적으로 사용 가능하도록 인코딩 간에 대역폭을 할당해야 합니다. 예를 들어 두 동시 송출 스트림이 동일한 maxBitrate를 가진다면, 두 스트림 모두에서 유사한 비트레이트가 관찰될 것으로 기대됩니다. 대역폭이 모든 동시 송출 스트림을 사용 가능한 형태로 전송하기에 충분하지 않으면, 사용자 에이전트는 일부 동시 송출 스트림의 전송을 중지하는 것이 기대됩니다.

[RFC9429] (섹션 3.7.)에 정의된 대로, 사용자 에이전트의 오퍼는 a=simulcast 라인에 "send" 설명만 포함하며 "recv" 설명은 포함하지 않습니다. (설명은 [RFC8853]) 에 제한 및 대안이 기술되어 있지만, 지원되지 않습니다.

이 명세는 createOffer, createAnswer 또는 addTransceiver를 사용하여 다중 RTP 인코딩의 수신을 구성하는 방법을 정의하지 않습니다. 그러나 setRemoteDescription[RFC9429]에 정의된 다중 RTP 인코딩을 전송할 수 있는 원격 설명과 함께 호출되고, 브라우저가 다중 RTP 인코딩 수신을 지원하는 경우, RTCRtpReceiver는 다중 RTP 인코딩을 수신할 수 있으며, 트랜시버의 receiver.getParameters() 메서드에서 검색된 파라미터는 협상된 인코딩을 반영합니다.

참고

RTCRtpReceiver는 SFU(Selective Forwarding Unit)가 사용자 에이전트에서 받은 동시 송출 스트림을 전환(switching)하는 시나리오에서 다중 RTP 스트림을 수신할 수 있습니다. SFU가 RTP 헤더를 재작성하지 않아 전환된 스트림을 전달하기 전에 단일 RTP 스트림으로 재구성하지 않는 경우, RTCRtpReceiver는 고유한 SSRC 및 시퀀스 번호 공간을 가진 별개의 RTP 스트림으로부터 패킷을 수신하게 됩니다. SFU가 특정 시점에서 단일 RTP 스트림만 전달할 수 있지만, 수신자에서는 재정렬(reordering)로 인해 다중 RTP 스트림의 패킷이 섞일 수 있습니다. 다중 RTP 스트림을 수신할 수 있도록 장착된 RTCRtpReceiver는 수신된 패킷을 올바르게 정렬하고, 잠재적인 손실 이벤트를 인식하며 이에 대응할 수 있어야 합니다. 이러한 시나리오에서의 올바른 동작은 간단하지 않으며, 따라서 이 명세의 구현에서 선택 사항입니다.

5.4.1.1 인코딩 파라미터 예제

이 섹션은 규범적이지 않습니다.

인코딩 파라미터로 구현된 동시 송출 시나리오 예제:

// 가장 낮은 해상도 레이어를 제외하고 비활성화된 3-레이어 공간 동시 송출 예제
var encodings = [
  {rid: 'q', active: true, scaleResolutionDownBy: 4.0}
  {rid: 'h', active: false, scaleResolutionDownBy: 2.0},
  {rid: 'f', active: false},
];

5.4.2 "보류" 기능

이 섹션은 규범적이지 않습니다.

direction 특성과 replaceTrack 메서드는 개발자가 "보류" 시나리오를 구현할 수 있도록 합니다.

상대방에게 음악을 보내고 수신된 오디오의 렌더링을 중지하려면 (음악-보류):

async function playMusicOnHold() {
  try {
    // 오디오 트랜시버와 musicTrack이라는 음악 트랙이 있다고 가정합니다.
    await audio.sender.replaceTrack(musicTrack);
    // 수신된 오디오 음소거
    audio.receiver.track.enabled = false;
    // 방향을 send-only로 설정 (협상 필요)
    audio.direction = 'sendonly';
  } catch (err) {
    console.error(err);
  }
}

원격 피어의 "sendonly" 오퍼에 응답하려면:

async function handleSendonlyOffer() {
  try {
    // 먼저 sendonly 오퍼를 적용하여
    // 수신기가 ICE 후보에 준비될 수 있도록 합니다.
    await pc.setRemoteDescription(sendonlyOffer);
    // 오디오 전송 중지
    await audio.sender.replaceTrack(null);
    // 추가 협상이 필요 없도록 방향 맞추기
    audio.direction = 'recvonly';
    // createAnswer 호출 후 recvonly 답변 전송
    await doAnswer();
  } catch (err) {
    // 신호 오류 처리
  }
}

음악 전송을 중지하고 마이크로폰에서 캡처된 오디오를 전송하며 수신된 오디오를 렌더링하려면:

async function stopOnHoldMusic() {
  // 오디오 트랜시버와 micTrack 이름의 마이크 트랙이 있다고 가정합니다.
  await audio.sender.replaceTrack(micTrack);
  // 수신된 오디오 음소거 해제
  audio.receiver.track.enabled = true;
  // 방향을 sendrecv로 설정 (협상 필요)
  audio.direction = 'sendrecv';
}

원격 피어가 보류를 해제했을 때 응답하려면:

async function onOffHold() {
  try {
    // 먼저 sendrecv 오퍼를 적용하여, 수신기가 ICE 후보에 준비될 수 있도록 합니다.
    await pc.setRemoteDescription(sendrecvOffer);
    // 오디오 전송 시작
    await audio.sender.replaceTrack(micTrack);
    // sendrecv 방향 설정 (답변 직전에 설정)
    audio.direction = 'sendrecv';
    // createAnswer 호출 후 sendrecv 답변 전송
    await doAnswer();
  } catch (err) {
    // 신호 오류 처리
  }
}

5.5 RTCDtlsTransport 인터페이스

RTCDtlsTransport 인터페이스는 애플리케이션이 RTP 및 RTCP 패킷이 전송되고 수신되는 Datagram Transport Layer Security (DTLS) 전송에 대한 정보를 액세스할 수 있도록 합니다. RTCRtpSenderRTCRtpReceiver 객체, 그리고 데이터 채널에 의해 전송되고 수신되는 SCTP 패킷과 같은 기타 데이터도 포함됩니다. 특히, DTLS는 기본 전송에 보안을 추가하며, RTCDtlsTransport 인터페이스는 기본 전송 및 추가된 보안에 대한 정보를 액세스할 수 있도록 합니다. RTCDtlsTransport 객체는 setLocalDescription()setRemoteDescription() 호출의 결과로 생성됩니다. 각 RTCDtlsTransport 객체는 특정 RTCRtpTransceiver의 RTP 혹은 RTCP component에 대한 DTLS 전송 계층을 나타내거나, [RFC8843]에 따라 협상된 그룹의 RTCRtpTransceiver를 나타냅니다.

참고
기존 RTCRtpTransceiver에 대한 새로운 DTLS 연결은 새로운 객체가 아닌, 기존 RTCDtlsTransport 객체로 나타나며, 해당 객체의 state가 적절히 업데이트됩니다.

RTCDtlsTransport는 "new"로 초기화된 [[DtlsTransportState]] 내부 슬롯과 빈 목록으로 초기화된 [[RemoteCertificates]] 슬롯을 가집니다.

기본 DTLS 전송에서 인증서 검증 실패나 치명적 경고([RFC5246] 섹션 7.2 참조)와 같은 오류가 발생한 경우, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 추가해야 합니다:

  1. transport를 상태 업데이트 및 오류 알림을 받을 RTCDtlsTransport 객체로 설정합니다.

  2. transport의 상태가 이미 "failed"인 경우, 이 단계를 중단합니다.

  3. transport.[[DtlsTransportState]]를 "failed"로 설정합니다.

  4. error라는 이름의 이벤트를 transport에서 RTCErrorEvent 인터페이스를 사용하여 발생시키고, errorDetail 속성을 적절히 "dtls-failure" 또는 "fingerprint-failure"로 설정합니다.

  5. statechange라는 이름의 이벤트를 transport에서 발생시킵니다.

기본 DTLS 전송이 다른 이유로 해당 RTCDtlsTransport 객체의 상태를 업데이트해야 할 때, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 추가해야 합니다:

  1. transport를 상태 업데이트를 받을 RTCDtlsTransport 객체로 설정합니다.

  2. newState를 새로운 상태로 설정합니다.

  3. transport.[[DtlsTransportState]]newState로 설정합니다.

  4. newStateconnected인 경우, newRemoteCertificates를 원격 측에서 사용하는 인증서 체인으로 설정하고, 각 인증서는 이진 Distinguished Encoding Rules (DER) 형식으로 인코딩되어야 하며 [X690], transport.[[RemoteCertificates]]newRemoteCertificates로 설정합니다.

  5. statechange라는 이름의 이벤트를 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;
};

속성

iceTransport 유형 RTCIceTransport, 읽기 전용

iceTransport 속성은 패킷의 전송 및 수신에 사용되는 기본 전송입니다. 기본 전송은 여러 활성 RTCDtlsTransport 객체 간에 공유될 수 없습니다.

state 유형 RTCDtlsTransportState, 읽기 전용

state 속성은 가져올 때 [[DtlsTransportState]] 슬롯의 값을 반환해야 합니다.

onstatechange 유형 EventHandler
이 이벤트 핸들러의 이벤트 유형은 statechange입니다.
onerror 유형 EventHandler
이 이벤트 핸들러의 이벤트 유형은 error입니다.

메서드

getRemoteCertificates

[[RemoteCertificates]] 값을 반환합니다.

5.5.1 RTCDtlsTransportState 열거형(Enum)

WebIDLenum RTCDtlsTransportState {
  "new",
  "connecting",
  "connected",
  "closed",
  "failed"
};
RTCDtlsTransportState 열거형 설명
열거형 값 설명
new DTLS는 아직 협상을 시작하지 않았습니다.
connecting DTLS는 보안 연결을 협상하고 원격 핑거프린트를 검증하는 중입니다.
connected DTLS는 보안 연결 협상을 완료하고 원격 핑거프린트를 검증했습니다.
closed 전송은 close_notify 경고를 수신하거나 close() 호출의 결과로 의도적으로 종료되었습니다.
failed 전송은 오류(예: 오류 경고 수신 또는 원격 핑거프린트 검증 실패)의 결과로 실패했습니다.

5.5.2 RTCDtlsFingerprint 사전(Dictionary)

RTCDtlsFingerprint 사전은 [RFC4572]에 설명된 해시 함수 알고리즘과 인증서 핑거프린트를 포함합니다.

WebIDLdictionary RTCDtlsFingerprint {
  DOMString algorithm;
  DOMString value;
};
사전 RTCDtlsFingerprint 멤버
algorithm 유형 DOMString

'Hash function Textual Names' 레지스트리에서 정의된 해시 함수 알고리즘 중 하나 [IANA-HASH-FUNCTION].

value 유형 DOMString

[RFC4572] 섹션 5에서 'fingerprint' 구문을 사용하여 표현된 소문자 16진수 문자열 형식의 인증서 핑거프린트 값.

5.6 RTCIceTransport 인터페이스

RTCIceTransport 인터페이스는 애플리케이션이 패킷이 전송되고 수신되는 ICE 전송에 대한 정보를 액세스할 수 있도록 합니다. 특히 ICE는 애플리케이션이 액세스하고 싶을 수 있는 상태를 포함한 피어-투-피어 연결을 관리합니다. RTCIceTransport 객체는 setLocalDescription()setRemoteDescription() 호출 결과로 생성됩니다. 기본 ICE 상태는 ICE 에이전트에 의해 관리됩니다. 따라서 RTCIceTransport의 상태는 아래에 설명된 대로 ICE 에이전트가 사용자 에이전트에 알림을 제공할 때 변경됩니다. 각 RTCIceTransport 객체는 특정 RTCRtpTransceiver의 RTP 또는 RTCP component에 대한 ICE 전송 계층을 나타내거나, [RFC8843]에 따라 협상된 RTCRtpTransceiver 그룹을 나타냅니다.

참고
기존 RTCRtpTransceiver에 대한 ICE 재시작은 새 객체가 아닌, 기존 RTCIceTransport 객체로 나타나며, 해당 객체의 state가 적절히 업데이트됩니다.
Candidate Correction 24:ICE 수집 완료 시 두 태스크를 큐에 추가하고, 동일한 태스크에서 gatheringstatechange 및 icegatheringstatechange를 발생시킵니다 (PR #2894)

ICE 에이전트generation의 후보를 RTCIceTransport transport 와 연결된 RTCPeerConnection connection에 대해 수집하기 시작했다고 나타내면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 추가해야 합니다:

  1. RTCPeerConnection 객체와 이 ICE 에이전트를 연결합니다.

  2. 만약 connection.[[IsClosed]]true라면, 이 단계를 중단합니다.

  3. transport를 후보 수집이 시작된 RTCIceTransport 로 설정합니다.

  4. transport.[[IceGathererState]]gathering로 설정합니다.

    .

  5. connection.[[IceGatheringState]]RTCIceGatheringState 열거형이 설명하는 새로운 상태 값으로 설정합니다.

  6. connectionIceGatheringStateChangedconnection.[[IceGatheringState]]가 이전 단계에서 변경되었으면 true, 그렇지 않으면 false로 설정합니다.

  7. 이 시점 이후로 상태를 읽거나 수정하지 마십시오.

  8. 이벤트gatheringstatechange 라는 이름으로 transport에서 발생시킵니다.

  9. ICE 수집 상태 업데이트connection에서 수행합니다.

  10. connectionIceGatheringStateChangedtrue라면, 이벤트icegatheringstatechange 라는 이름으로 connection에서 발생시킵니다.

ICE 에이전트generation의 후보를 RTCIceTransport transport 와 연결된 RTCPeerConnection connection에서 수집을 완료하고, 해당 후보가 애플리케이션에 표시되었을 때, 사용자 에이전트는 반드시 태스크를 큐에 추가하여 다음 단계를 실행합니다:

  1. connection을 이 ICE 에이전트와 연결된 RTCPeerConnection 객체로 설정합니다.

  2. 만약 connection.[[IsClosed]]true라면, 이 단계를 중단합니다.

  3. transport를 후보 수집이 완료된 RTCIceTransport 로 설정합니다.

  4. 만약 connection.[[PendingLocalDescription]]null이 아니고, 후보 수집이 완료된 ICE generation을 나타낸다면, a=end-of-candidatesconnection.[[PendingLocalDescription]].sdp에 추가합니다.

  5. 만약 connection.[[CurrentLocalDescription]]null이 아니고, 후보 수집이 완료된 ICE generation을 나타낸다면, a=end-of-candidatesconnection.[[CurrentLocalDescription]].sdp에 추가합니다.

  6. RTCIceCandidate 생성의 결과를 사용하여, endOfGatheringCandidate를 새로운 딕셔너리로 생성합니다. 이 딕셔너리는 sdpMidsdpMLineIndex가 이 RTCIceTransport에 연관된 값으로 설정됩니다. 또한, usernameFragment는 후보 수집이 완료된 ICE generation의 사용자 이름 조각으로 설정되고, candidate""로 설정됩니다.

  7. 이벤트icecandidate라는 이름으로, RTCPeerConnectionIceEvent 인터페이스를 사용하여, candidate 속성을 endOfGatheringCandidate로 설정하여 connection에서 발생시킵니다.

  1. 만약 또 다른 generation의 후보가 여전히 수집되고 있다면, 이 단계를 중단합니다.

    참고
    이것은 ICE 에이전트가 이전 generation의 후보를 여전히 수집하고 있는 동안 ICE 재시작이 시작된 경우 발생할 수 있습니다.
  2. transport.[[IceGathererState]]complete로 설정합니다.

  3. 이벤트를 발생시킵니다. 이벤트 이름은 gatheringstatechange이며, transport에서 발생시킵니다.

  4. ICE 수집 상태를 업데이트합니다. connection.

ICE 에이전트가 위 태스크를 큐에 추가했으며, 다른 generation의 후보가 여전히 수집 중이 아니라면, 사용자 에이전트는 반드시 다음 단계를 실행하는 두 번째 태스크를 큐에 추가해야 합니다:

참고
다른 generation의 후보가 여전히 수집 중일 수 있습니다. 이는 ICE 에이전트가 이전 generation의 후보를 수집하는 동안 ICE 재시작이 시작된 경우 발생할 수 있습니다.
  1. 만약 connection.[[IsClosed]]true라면, 이 단계를 중단합니다.

  2. transport.[[IceGathererState]]complete로 설정합니다.

  3. connection.[[IceGatheringState]]RTCIceGatheringState 열거형이 설명하는 새로운 상태 값으로 설정합니다.

  4. connectionIceGatheringStateChangedtrue로 설정합니다. 이는 connection.[[IceGatheringState]]가 이전 단계에서 변경된 경우에 해당하며, 그렇지 않으면 false로 설정합니다.

  5. 이 시점 이후로 상태를 읽거나 수정하지 마십시오.

  6. 이벤트를 발생시킵니다. 이벤트 이름은 gatheringstatechange이며, transport에서 발생합니다.

  7. 만약 connectionIceGatheringStateChangedtrue라면, 이벤트를 발생시킵니다. 이벤트 이름은 icegatheringstatechange이며, connection에서 발생합니다.

  8. 이벤트를 발생시킵니다. 이벤트 이름은 icecandidate이며, RTCPeerConnectionIceEvent 인터페이스를 사용하여 candidate 속성을 null로 설정하고, connection에서 발생시킵니다.

    참고
    null 후보 이벤트는 레거시 호환성을 보장하기 위해 발생합니다. 새로운 코드는 RTCIceTransport 및/또는 RTCPeerConnection의 수집 상태를 모니터링해야 합니다.

ICE 에이전트RTCIceTransport에 대해 새로운 ICE 후보가 사용 가능하다고 나타내면, 이는 ICE 후보 풀에서 가져오거나 새로 수집된 것입니다. 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 추가해야 합니다:

  1. candidate를 사용 가능한 ICE 후보로 설정합니다.

  2. connection을 이 RTCPeerConnection 객체로 설정합니다. 이 객체는 ICE 에이전트와 연결되어 있습니다.

  3. 만약 connection.[[IsClosed]]true라면, 이 단계를 중단합니다.

  4. 만약 connection.[[PendingLocalDescription]] 또는 connection.[[CurrentLocalDescription]]null이 아니며, candidate가 수집된 ICE generation을 나타낸다면, 후보를 표시하고 candidateconnection을 사용하여 이 단계를 중단합니다.

  5. 그렇지 않다면, candidateconnection.[[EarlyCandidates]]에 추가합니다.

ICE 에이전트가 [RFC8445] 섹션 7.3.1.1에 따라 역할 충돌이 있는 ICE 바인딩 요청으로 인해 ICE 역할이 변경되었음을 신호하면, UA는 [[IceRole]] 값을 새 값으로 설정하는 작업을 큐에 추가합니다.

connection초기 후보를 해제하려면 다음 단계를 실행합니다:

  1. connection.[[EarlyCandidates]]에 있는 각 candidate에 대해, 후보를 표시하는 태스크를 큐에 추가합니다.

  2. connection.[[EarlyCandidates]]를 빈 목록으로 설정합니다.

candidateconnection을 사용하여 후보를 표시하려면 다음 단계를 실행합니다:

  1. 만약 connection.[[IsClosed]]true라면, 이 단계를 중단합니다.

  2. candidate가 사용 가능하게 된 RTCIceTransporttransport로 설정합니다.

  3. 만약 connection.[[PendingLocalDescription]]null이 아니며, candidate가 수집된 ICE generation을 나타낸다면, candidateconnection.[[PendingLocalDescription]].sdp에 추가합니다.

  4. 만약 connection.[[CurrentLocalDescription]]null이 아니며, candidate가 수집된 ICE generation을 나타낸다면, candidateconnection.[[CurrentLocalDescription]].sdp에 추가합니다.

  5. RTCIceCandidate 생성의 결과를 사용하여 newCandidate를 설정합니다. 새 딕셔너리의 sdpMidsdpMLineIndexRTCIceTransport와 관련된 값으로 설정됩니다. 또한 usernameFragment는 후보의 사용자 이름 조각으로 설정되며, candidatecandidate-attribute 문법을 사용하여 candidate를 표현한 문자열로 설정됩니다.

  6. newCandidatetransport의 로컬 후보 집합에 추가합니다.

  7. 이벤트를 발생시킵니다. 이벤트 이름은 icecandidate이며, RTCPeerConnectionIceEvent 인터페이스를 사용하여 candidate 속성을 newCandidate로 설정하고, connection에서 발생시킵니다.

RTCIceTransportStateRTCIceTransport에서 사용 가능한 연결이 있는 후보 쌍이 발견되어 선택되거나, 선택된 후보 쌍이 변경되지 않은 상태에서도 변경될 수 있습니다. 선택된 쌍과 RTCIceTransportState는 관련이 있으며 동일한 태스크에서 처리됩니다.

ICE 에이전트RTCIceTransport의 선택된 후보 쌍, RTCIceTransportState 또는 둘 다 변경되었음을 나타내면, 사용자 에이전트는 선택된 후보 쌍과 상태를 변경하는 단계를 실행하는 태스크를 큐에 추가해야 합니다:

  1. connection을 이 RTCPeerConnection 객체로 설정합니다. 이 객체는 ICE 에이전트와 연결됩니다.

  2. 만약 connection.[[IsClosed]]true라면, 이 단계를 중단합니다.

  3. 상태가 변경된 RTCIceTransporttransport로 설정합니다.

  4. selectedCandidatePairChangedfalse로 설정합니다.

  5. transportIceConnectionStateChangedfalse로 설정합니다.

  6. connectionIceConnectionStateChangedfalse로 설정합니다.

  7. connectionStateChangedfalse로 설정합니다.

  8. 만약 transport의 선택된 후보 쌍이 변경되었다면, 다음 단계를 실행합니다:

    1. RTCIceCandidatePair 생성의 결과를 사용하여, newCandidatePairlocalremote를 포함하는 새 쌍으로 설정합니다. 쌍이 선택되지 않은 경우, null로 설정합니다.

    2. transport.[[SelectedCandidatePair]]newCandidatePair로 설정합니다.

    3. selectedCandidatePairChangedtrue로 설정합니다.

  9. 만약 transportRTCIceTransportState가 변경되었다면, 다음 단계를 실행합니다:

    1. transport.[[IceTransportState]]를 새롭게 지정된 RTCIceTransportState로 설정합니다.

    2. transportIceConnectionStateChangedtrue로 설정합니다.

    3. connection.[[IceConnectionState]]RTCIceConnectionState 열거형이 설명하는 새 상태 값으로 설정합니다.

    4. 만약 connection.[[IceConnectionState]]가 이전 단계에서 변경되었다면, connectionIceConnectionStateChangedtrue로 설정합니다.

    5. connection.[[ConnectionState]]RTCPeerConnectionState 열거형이 설명하는 새 상태 값으로 설정합니다.

    6. 만약 connection.[[ConnectionState]]가 이전 단계에서 변경되었다면, connectionStateChangedtrue로 설정합니다.

  10. 만약 selectedCandidatePairChangedtrue라면, 이벤트를 발생시킵니다. 이벤트 이름은 selectedcandidatepairchange이며, transport에서 발생합니다.

  11. 만약 transportIceConnectionStateChangedtrue라면, 이벤트를 발생시킵니다. 이벤트 이름은 statechange이며, transport에서 발생합니다.

  12. 만약 connectionIceConnectionStateChangedtrue라면, 이벤트를 발생시킵니다. 이벤트 이름은 iceconnectionstatechange이며, connection에서 발생합니다.

  13. 만약 connectionStateChangedtrue라면, 이벤트를 발생시킵니다. 이벤트 이름은 connectionstatechange이며, connection에서 발생합니다.

RTCIceTransport 객체는 다음과 같은 내부 슬롯을 가집니다:

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;
};

속성

role 유형 RTCIceRole, 읽기 전용

role 속성은 반드시 가져올 때 [[IceRole]] 내부 슬롯의 값을 반환해야 합니다.

component 유형 RTCIceComponent, 읽기 전용

component 속성은 반드시 전송의 ICE 구성 요소를 반환해야 합니다. RTCP mux가 사용될 때 단일 RTCIceTransport가 RTP와 RTCP를 모두 전송하며, component는 "rtp"로 설정됩니다.

state 유형 RTCIceTransportState, 읽기 전용

state 속성은 반드시 가져올 때 [[IceTransportState]] 슬롯의 값을 반환해야 합니다.

gatheringState 유형 RTCIceGathererState, 읽기 전용

gatheringState 속성은 반드시 가져올 때 [[IceGathererState]] 슬롯의 값을 반환해야 합니다.

onstatechange 유형 EventHandler
이 이벤트 핸들러는 이벤트 핸들러 이벤트 유형 statechange이며, 반드시 RTCIceTransportstate가 변경될 때마다 발생해야 합니다.
ongatheringstatechange 유형 EventHandler
이 이벤트 핸들러는 이벤트 핸들러 이벤트 유형 gatheringstatechange이며, 반드시 RTCIceTransport[[IceGathererState]]가 변경될 때마다 발생해야 합니다.
onselectedcandidatepairchange 유형 EventHandler
이 이벤트 핸들러는 이벤트 핸들러 이벤트 유형 selectedcandidatepairchange이며, 반드시 RTCIceTransport의 선택된 후보 쌍이 변경될 때마다 발생해야 합니다.

메서드

getLocalCandidates

RTCIceTransport에 대해 수집된 로컬 ICE 후보를 설명하는 시퀀스를 반환하며, onicecandidate에서 전송된 후보를 반환합니다.

getRemoteCandidates

RTCIceTransport를 통해 addIceCandidate()로 수신된 원격 ICE 후보를 설명하는 시퀀스를 반환합니다.

참고
getRemoteCandidates는 피어 반사 후보(peer reflexive candidates)를 노출하지 않습니다. 이는 addIceCandidate()를 통해 수신되지 않기 때문입니다.
getSelectedCandidatePair

패킷이 전송되는 선택된 후보 쌍을 반환합니다. 이 메서드는 반드시 [[SelectedCandidatePair]] 슬롯의 값을 반환해야 합니다. RTCIceTransport.state가 "new" 또는 "closed"일 때, getSelectedCandidatePairnull을 반환합니다.

getLocalParameters

RTCIceTransport를 통해 setLocalDescription로 수신된 로컬 ICE 매개변수를 반환하거나, 매개변수가 아직 수신되지 않은 경우 null을 반환합니다.

getRemoteParameters

RTCIceTransport를 통해 setRemoteDescription로 수신된 원격 ICE 매개변수를 반환하거나, 매개변수가 아직 수신되지 않은 경우 null을 반환합니다.

5.6.1 RTCIceParameters 사전(Dictionary)

WebIDLdictionary RTCIceParameters {
  DOMString usernameFragment;
  DOMString password;
};
사전(Dictionary) RTCIceParameters 멤버
usernameFragment 유형 DOMString

[RFC5245], 섹션 7.1.2.3에서 정의된 ICE 사용자 이름 조각(username fragment)입니다.

password 유형 DOMString

[RFC5245], 섹션 7.1.2.3에서 정의된 ICE 비밀번호입니다.

Candidate Addition 45:RTCIceCandidatePair 사전을 인터페이스로 변환 (PR #2961)

5.6.2 RTCIceCandidatePair 사전

5.6.2 RTCIceCandidatePair 인터페이스

이 인터페이스는 RTCIceCandidatePair를 나타내며, 이는 [RFC8445]의 섹션 4에서 설명되었습니다. RTCIceCandidate의 로컬 및 원격 페어링입니다.

RTCIceCandidate 객체인 localremoteRTCIceCandidatePair를 생성하려면 다음 단계를 수행합니다:

  1. candidatePair를 새롭게 생성된 RTCIceCandidatePair 객체로 설정합니다.
  2. candidatePairlocal로 초기화된 [[Local]] 내부 슬롯을 추가합니다.
  3. candidatePairremote로 초기화된 [[Remote]] 내부 슬롯을 추가합니다.
  4. candidatePair를 반환합니다.
dictionary [Exposed=Window]
interface RTCIceCandidatePair {
  [SameObject] readonly attribute RTCIceCandidate local;
  [SameObject] readonly attribute RTCIceCandidate remote;
};
사전 RTCIceCandidatePair 멤버
속성
local 타입의 RTCIceCandidate , 읽기 전용

로컬 ICE 후보입니다.

local 속성은 반드시, [[Local]] 내부 슬롯의 값을 반환해야 합니다.

remote 타입의 RTCIceCandidate , 읽기 전용

원격 ICE 후보입니다.

remote 속성은 반드시, [[Remote]] 내부 슬롯의 값을 반환해야 합니다.

5.6.3 RTCIceGathererState 열거형

WebIDLenum RTCIceGathererState {
  "new",
  "gathering",
  "complete"
};
RTCIceGathererState 열거형 설명
열거값 설명
new RTCIceTransport가 방금 생성되었으며, 아직 후보 수집을 시작하지 않았습니다.
gathering RTCIceTransport가 후보를 수집 중입니다.
complete RTCIceTransport가 후보 수집을 완료했고, 이 전송에 대한 후보 종료 표시가 전송되었습니다. ICE 재시작이 발생하지 않는 한 다시 후보를 수집하지 않습니다.

5.6.4 RTCIceTransportState 열거형

WebIDLenum RTCIceTransportState {
  "closed",
  "failed",
  "disconnected",
  "new",
  "checking",
  "completed",
  "connected"
};
RTCIceTransportState 열거형 설명
열거값 설명
closed RTCIceTransport가 종료되어 더 이상 STUN 요청에 응답하지 않습니다.
failed
RTCIceTransport가 후보 수집을 완료했고, 더 이상 원격 후보가 없다는 신호를 받았으며, 모든 후보 쌍에 대한 검사를 마쳤고, 모든 쌍이 연결성 검사에 실패했거나 동의를 상실했으며, 로컬 후보가 하나도 수집되지 않았거나 PAC 타이머가 만료되었습니다 [RFC8863]. 이는 ICE가 재시작되기 전까지 종단 상태입니다. ICE 재시작으로 연결성이 회복될 수 있으므로 "failed" 상태로 들어가더라도 DTLS 전송, SCTP 연합 및 그 위에서 동작하는 데이터 채널이 닫히거나 트랙이 음소거되지는 않습니다.
disconnected ICE 에이전트가 이 RTCIceTransport의 연결성이 현재 손실되었다고 판단했습니다. 이는 일시적 상태로, 불안정한 네트워크에서 간헐적으로 트리거되었다가 (조치 없이) 스스로 복구될 수 있습니다. 이 상태의 판정 방식은 구현에 따라 달라질 수 있습니다. 예:
  • 사용 중인 연결의 네트워크 인터페이스를 상실함
  • STUN 요청에 대한 응답 수신에 반복적으로 실패함
또는, RTCIceTransport가 기존 후보 쌍에 대한 검사를 모두 마쳤지만 연결을 찾지 못했고(이전에 성공했던 동의 확인 [RFC7675] 이 이제 실패했을 수 있음), 여전히 수집 중이거나 추가 원격 후보를 기다리는 중입니다.
new RTCIceTransport가 후보를 수집 중이거나 원격 후보가 제공되기를 기다리고 있으며, 아직 검사(checking)를 시작하지 않았습니다.
checking RTCIceTransport가 최소 하나의 원격 후보를 수신했으며( addIceCandidate() 를 통해 혹은 STUN 바인딩 요청을 수신할 때 피어-반사 후보로 발견) 후보 쌍을 검사하고 있고, 아직 연결을 찾지 못했거나 이전에 성공했던 후보 쌍들에서의 동의 확인 [RFC7675] 이 모두 실패했습니다. 검사와 더불어, 여전히 후보를 수집 중일 수도 있습니다.
completed RTCIceTransport가 후보 수집을 완료했고, 더 이상 원격 후보가 없다는 신호를 받았으며, 모든 후보 쌍 검사를 마친 뒤 연결을 찾았습니다. 이후 동의 확인 [RFC7675] 이 모든 성공한 후보 쌍에서 실패하면, 상태는 "failed"로 전이됩니다.
connected RTCIceTransport가 사용 가능한 연결을 찾았지만, 더 나은 연결이 있는지 확인하기 위해 다른 후보 쌍을 계속 검사하고 있습니다. 또한 계속 후보를 수집 중이거나 추가 원격 후보를 기다리고 있을 수 있습니다. 사용 중인 연결에서 동의 확인 [RFC7675] 이 실패하고, 사용 가능한 다른 성공한 후보 쌍이 없다면, 상태는 남은 후보 쌍이 있다면 "checking"로, 검사할 후보 쌍은 없지만 피어가 여전히 수집 중이거나 추가 원격 후보를 기다리는 경우에는 "disconnected"로 전이됩니다.
참고

성공적인 통화에서 가장 일반적인 전이는 new -> checking -> connected -> completed 순서이지만, 특정 상황(마지막으로 검사한 후보만 성공하고, 성공 이전에 후보 수집과 더 이상 후보가 없다는 신호가 모두 발생한 경우)에서는 상태가 "checking"에서 "completed"로 바로 전이될 수 있습니다.

ICE 재시작은 후보 수집과 연결성 검사를 다시 시작하게 하며, "connected" 상태로 전이됩니다(시작이 "completed" 상태에서 이루어진 경우). 일시적인 "disconnected" 상태에서 시작한 경우에는 "checking"으로 전이되어, 이전에 연결이 끊어졌다는 사실을 사실상 잊게 됩니다.

"failed" 및 "completed" 상태는 추가적인 원격 후보가 없다는 신호가 필요합니다. 이는 addIceCandidate를 호출할 때 후보 값의 candidate 프로퍼티를 빈 문자열로 설정하거나, canTrickleIceCandidatesfalse로 설정되어 있음을 통해 나타낼 수 있습니다.

상태 전이 예시는 다음과 같습니다:

ICE 전송 상태 전이 다이어그램
그림 2 비규범적 ICE 전송 상태 전이 다이어그램

5.6.5 RTCIceRole 열거형

WebIDLenum RTCIceRole {
  "unknown",
  "controlling",
  "controlled"
};
RTCIceRole 열거형 설명
열거값 설명
unknown [RFC5245] 섹션 3에 정의된 역할이 아직 결정되지 않은 에이전트입니다.
controlling [RFC5245] 섹션 3에 정의된 제어 에이전트입니다.
controlled [RFC5245] 섹션 3에 정의된 제어를 받는 에이전트입니다.

5.6.6 RTCIceComponent 열거형

WebIDLenum RTCIceComponent {
  "rtp",
  "rtcp"
};
RTCIceComponent 열거형 설명
열거값 설명
rtp ICE 전송이 RTP(또는 RTCP 멀티플렉싱)에 사용되며, 이는 [RFC5245] 섹션 4.1.1.1에서 정의되었습니다. RTP와 멀티플렉싱되는 프로토콜(예: 데이터 채널)은 해당 컴포넌트 ID를 공유합니다. 이는 candidate-attribute로 인코딩 될 때 component-id1을 나타냅니다.
rtcp ICE 전송이 RTCP에 사용되며, 이는 [RFC5245] 섹션 4.1.1.1에서 정의되었습니다. 이는 candidate-attribute로 인코딩 될 때 component-id2를 나타냅니다.

5.7 RTCTrackEvent

track 이벤트는 RTCTrackEvent 인터페이스를 사용합니다.

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;
};

생성자

RTCTrackEvent.constructor()

속성

receiver 타입 RTCRtpReceiver, 읽기 전용

receiver 속성은 이벤트와 연관된 RTCRtpReceiver 객체를 나타냅니다.

track 타입 MediaStreamTrack, 읽기 전용

track 속성은 MediaStreamTrack 객체를 나타내며, 이는 RTCRtpReceiver 에 의해 식별된 receiver와 연관됩니다.

streams 타입 FrozenArray<MediaStream>, 읽기 전용

streams 속성은 이 이벤트의 MediaStream 객체를 나타내는 배열을 반환하며, 이 이벤트의 track이 포함되어 있습니다.

transceiver 타입 RTCRtpTransceiver, 읽기 전용

transceiver 속성은 이 이벤트와 연관된 RTCRtpTransceiver 객체를 나타냅니다.

WebIDLdictionary RTCTrackEventInit : EventInit {
  required RTCRtpReceiver receiver;
  required MediaStreamTrack track;
  sequence<MediaStream> streams = [];
  required RTCRtpTransceiver transceiver;
};

사전 RTCTrackEventInit 멤버

receiver 타입 RTCRtpReceiver, 필수

receiver 멤버는 이벤트와 연관된 RTCRtpReceiver 객체를 나타냅니다.

track 타입 MediaStreamTrack, 필수

track 멤버는 MediaStreamTrack 객체를 나타내며, 이는 RTCRtpReceiver 에 의해 식별된 receiver와 연관됩니다.

streams 타입 sequence<MediaStream>, 기본값은 []

streams 멤버는 이 이벤트의 MediaStream 객체를 나타내는 배열이며, 이 이벤트의 track 이 포함되어 있습니다.

transceiver 타입 RTCRtpTransceiver, 필수

transceiver 속성은 이 이벤트와 연관된 RTCRtpTransceiver 객체를 나타냅니다.

6. 피어-투-피어 데이터 API

피어-투-피어 데이터 API는 웹 애플리케이션이 피어-투-피어로 일반 애플리케이션 데이터를 송수신할 수 있도록 합니다. 데이터 송수신 API는 웹소켓 의 동작을 모델링합니다.

6.1 RTCPeerConnection 인터페이스 확장

피어-투-피어 데이터 API는 아래에 설명된 대로 RTCPeerConnection 인터페이스를 확장합니다.

WebIDL          partial interface RTCPeerConnection {
  readonly attribute RTCSctpTransport? sctp;
  RTCDataChannel createDataChannel(USVString label,
                                   optional RTCDataChannelInit dataChannelDict = {});
  attribute EventHandler ondatachannel;
};

속성

sctp 타입 RTCSctpTransport, 읽기 전용, nullable

SCTP 데이터가 송수신되는 SCTP 전송입니다. SCTP가 협상되지 않았다면 값은 null입니다. 이 속성은 반드시 RTCSctpTransport 객체(내부 슬롯 [[SctpTransport]]에 저장됨)를 반환해야 합니다.

ondatachannel 타입 EventHandler
이 이벤트 핸들러의 이벤트 타입은 datachannel입니다.

메서드

createDataChannel

주어진 라벨로 새로운 RTCDataChannel 객체를 생성합니다. RTCDataChannelInit 사전을 사용하여 데이터 신뢰성과 같은 기본 채널의 속성을 구성할 수 있습니다.

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

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

  2. 만약 connection.[[IsClosed]]true라면, throw를 호출하고 InvalidStateError를 던집니다.

  3. RTCDataChannel 생성, channel.

  4. channel.[[DataChannelLabel]]을 첫 번째 인자의 값으로 초기화합니다.

  5. 만약 [[DataChannelLabel]]의 UTF-8 표현이 65535 바이트보다 길다면, throw를 호출하고 TypeError를 던집니다.

  6. options를 두 번째 인자로 둡니다.

  7. channel.[[MaxPacketLifeTime]]을 초기화합니다. option.maxPacketLifeTime이 존재하면 그 값으로, 그렇지 않으면 null로 설정합니다.

  8. channel.[[MaxRetransmits]]를 초기화합니다. option.maxRetransmits이 존재하면 그 값으로, 그렇지 않으면 null로 설정합니다.

  9. channel.[[Ordered]]option.ordered의 값으로 초기화합니다.

  10. channel.[[DataChannelProtocol]]option.protocol의 값으로 초기화합니다.

  11. 만약 [[DataChannelProtocol]]의 UTF-8 표현이 65535 바이트보다 길다면, throw를 호출하고 TypeError를 던집니다.

  12. channel.[[Negotiated]]option.negotiated의 값으로 초기화합니다.

  13. channel.[[DataChannelId]]를 다음의 값으로 초기화합니다: option.id가 존재하고 [[Negotiated]]가 true일 때는 그 값으로, 그렇지 않으면 null로 설정합니다.

    참고
    이는 데이터 채널이 인밴드로 협상된 경우 id 멤버가 무시된다는 뜻이며, 이는 의도된 동작입니다. 인밴드로 협상된 데이터 채널의 ID는 [RFC8832]에 명시된 대로 DTLS 역할을 기반으로 선택되어야 합니다.
  14. [[Negotiated]]true이고 [[DataChannelId]]null이라면, throw를 호출하고 TypeError를 던집니다.

  15. [[MaxPacketLifeTime]][[MaxRetransmits]] 속성이 둘 다 설정되어 있다면(null이 아님), throw를 호출하고 TypeError를 던집니다.

  16. [[MaxPacketLifeTime]] 또는 [[MaxRetransmits]] 설정을 통해 비신뢰(불안정) 모드를 지정했는데 그 값이 사용자 에이전트가 지원하는 최대값을 초과한다면, 해당 값은 사용자 에이전트의 최대값으로 설정되어야 합니다.

  17. 만약 [[DataChannelId]]가 65535와 같다면(허용되는 최대 ID 65534보다 크지만 여전히 unsigned short에 해당), throw를 호출하고 TypeError를 던집니다.

  18. [[DataChannelId]] 슬롯이 null이고(이는 createDataChannel에 ID가 전달되지 않았거나, [[Negotiated]]가 false이기 때문) SCTP 전송의 DTLS 역할이 이미 협상되었다면, [RFC8832]에 따라 사용자 에이전트가 생성한 값으로 [[DataChannelId]]를 초기화하고 다음 단계로 건너뜁니다. 사용 가능한 ID를 생성할 수 없거나, [[DataChannelId]] 슬롯의 값이 기존 RTCDataChannel에서 사용 중이라면, throw를 호출하고 OperationError 예외를 던집니다.

    참고
    이 단계 이후에도 [[DataChannelId]] 슬롯이 null이라면, RTCSctpTransport 연결됨 절차 동안 채워집니다.
  19. transportconnection.[[SctpTransport]]로 둡니다.

    [[DataChannelId]] 슬롯이 null이 아니고, transport가 "connected" 상태이며, [[DataChannelId]]transport.[[MaxChannels]]보다 크거나 같다면, throw를 호출하고 OperationError를 던집니다.

  20. channelconnection에서 생성된 첫 번째 RTCDataChannel이라면, 협상 필요 플래그를 업데이트합니다.

  21. Append channelconnection.[[DataChannels]]에 추가합니다.

  22. channel을 반환하고 이어지는 단계를 병렬로 계속 수행합니다.

  23. channel에 연관된 기저 데이터 전송을 생성하고, channel의 관련 속성에 따라 구성합니다.

6.1.1 RTCSctpTransport 인터페이스

RTCSctpTransport 인터페이스는 특정 SCTP 연관(association)에 연결된 SCTP 데이터 채널에 대한 정보에 애플리케이션이 접근할 수 있도록 합니다.

6.1.1.1 인스턴스 생성

초기 상태 initialStateRTCSctpTransport 생성을 하려면, 다음 단계를 수행합니다:

  1. transport를 새로운 RTCSctpTransport 객체로 둡니다.

  2. transport[[SctpTransportState]] 내부 슬롯을 두고 initialState로 초기화합니다.

  3. transport[[MaxMessageSize]] 내부 슬롯을 두고, 이를 초기화하기 위해 데이터 최대 메시지 크기 업데이트 단계를 실행합니다.

  4. transport[[MaxChannels]] 내부 슬롯을 두고 null로 초기화합니다.

  5. transport를 반환합니다.

6.1.1.2 최대 메시지 크기 업데이트

RTCSctpTransport데이터 최대 메시지 크기 업데이트를 수행하려면 다음 단계를 실행합니다:

  1. 업데이트할 객체인 transportRTCSctpTransport 객체로 둡니다.

  2. remoteMaxMessageSize를 원격 설명에서 읽은 max-message-size SDP 속성의 값( [RFC8841] 섹션 6에 설명됨)으로 하되, 해당 속성이 없으면 65536으로 둡니다.

  3. canSendSize를 이 클라이언트가 보낼 수 있는 바이트 수(즉, 로컬 송신 버퍼의 크기)로 하거나, 구현이 임의의 크기의 메시지를 처리할 수 있는 경우 0으로 둡니다.

  4. remoteMaxMessageSizecanSendSize가 모두 0이면, [[MaxMessageSize]]를 양의 무한대로 설정합니다.

  5. 그렇지 않고 remoteMaxMessageSize 또는 canSendSize 중 하나가 0이라면, [[MaxMessageSize]]를 두 값 중 더 큰 값으로 설정합니다.

  6. 그 밖의 경우에는 [[MaxMessageSize]]remoteMaxMessageSizecanSendSize 중 더 작은 값으로 설정합니다.

6.1.1.3 연결 절차

SCTP 전송이 연결됨 상태, 즉 RTCSctpTransport의 SCTP 연관이 설정되면, 사용자 에이전트는 다음 단계를 수행하는 작업을 큐에 추가해야 합니다(MUST):

  1. transportRTCSctpTransport 객체로 둡니다.

  2. connectiontransport와 연관된 RTCPeerConnection 객체로 둡니다.

  3. [[MaxChannels]]를, 협상된 수신 및 송신 SCTP 스트림 수의 최솟값으로 설정합니다.

  4. connection의 각 RTCDataChannel에 대해:

    1. channelRTCDataChannel 객체로 둡니다.

    2. channel.[[DataChannelId]]null이면, [RFC8832]에 따라 하위 sctp 데이터 채널이 생성한 값으로 [[DataChannelId]]를 초기화합니다.

    3. channel.[[DataChannelId]]transport.[[MaxChannels]]보다 크거나 같거나, 이전 단계에서 ID 할당에 실패했다면, 실패로 인해 채널을 닫습니다. 그렇지 않으면, 채널이 열렸음을 알립니다.

  5. transport에서 이벤트를 발생시키며, 이름은 statechange로 합니다.

    참고

    이 이벤트는 채널이 열렸음을 알리는 과정에서 발생하는 open 이벤트들보다 먼저 발생합니다. open 이벤트들은 별도의 큐에 추가된 작업에서 발생합니다.

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;
};
속성
transport 타입 RTCDtlsTransport, 읽기 전용

데이터 채널의 모든 SCTP 패킷이 송수신되는 전송(transport)입니다.

state 타입 RTCSctpTransportState, 읽기 전용

SCTP 전송의 현재 상태입니다. 이 속성은 가져올 때 [[SctpTransportState]] 슬롯의 값을 반환해야 합니다(MUST).

maxMessageSize 타입 unrestricted double, 읽기 전용

RTCDataChannelsend() 메서드에 전달할 수 있는 데이터의 최대 크기입니다. 이 속성은 가져올 때 [[MaxMessageSize]] 슬롯의 값을 반환해야 합니다(MUST).

maxChannels 타입 unsigned short , 읽기 전용, nullable

동시에 사용할 수 있는 RTCDataChannel의 최대 개수입니다. 이 속성은 가져올 때 [[MaxChannels]] 슬롯의 값을 반환해야 합니다(MUST).

참고
이 속성의 값은 SCTP 전송이 "connected" 상태가 될 때까지 null입니다.
onstatechange 타입 EventHandler

이 이벤트 핸들러의 이벤트 타입은 statechange 입니다.

6.1.2 RTCSctpTransportState 열거형

RTCSctpTransportState는 SCTP 전송의 상태를 나타냅니다.

WebIDLenum RTCSctpTransportState {
  "connecting",
  "connected",
  "closed"
};
RTCSctpTransportState 열거형 설명
열거값 설명
connecting

RTCSctpTransport가 연관(association)을 협상하는 중입니다. 이는 RTCSctpTransport 가 생성될 때 [[SctpTransportState]] 슬롯의 초기 상태입니다.

connected

연관 협상이 완료되면 [[SctpTransportState]] 슬롯을 "connected"로 업데이트하기 위한 작업이 큐에 추가됩니다.

closed

다음의 경우 [[SctpTransportState]] 슬롯을 "closed"로 업데이트하기 위한 작업이 큐에 추가됩니다:

  • SHUTDOWN 또는 ABORT 청크를 수신한 경우.
  • 피어 연결을 종료하거나 데이터를 거부하거나 SCTP 포트를 변경하는 원격 설명을 적용하는 등, 의도적으로 SCTP 연관이 종료된 경우.
  • 하위 DTLS 연관이 "closed" 상태로 전이한 경우.

마지막 전이는 SCTP 연관이 설정된 DTLS 연결을 필요로 한다는 점에서 논리적입니다. 또한 [RFC8261] 섹션 6.1은 DTLS 위의 SCTP가 단일 홈(single-homed)임을 명시하고 있으며, 이 API에는 대체 전송으로 전환하는 방법이 정의되어 있지 않습니다.

6.2 RTCDataChannel

RTCDataChannel 인터페이스는 두 피어 간의 양방향 데이터 채널을 나타냅니다. RTCDataChannelRTCPeerConnection 객체의 팩토리 메서드를 통해 생성됩니다. 브라우저 간에 전송되는 메시지는 [RFC8831] 및 [RFC8832]에 설명되어 있습니다.

RTCDataChannel로 연결을 설정하는 방법은 두 가지가 있습니다. 첫 번째 방법은 피어 중 한쪽에서 RTCDataChannel을 단순히 생성하되, negotiated RTCDataChannelInit 사전 멤버를 설정하지 않거나 기본값인 false로 두는 것입니다. 이는 인밴드로 새로운 채널을 알리고, 상대 피어에서 해당하는 RTCDataChannelEvent를 트리거하여 해당 RTCDataChannel 객체를 전달합니다. 두 번째 방법은 애플리케이션이 RTCDataChannel을 직접 협상하는 것입니다. 이를 위해 RTCDataChannel 객체를 생성하되, negotiated RTCDataChannelInit 사전 멤버를 true로 설정하고, (예: 웹 서버를 통해) 대역외로 상대 측에 동일한 id와 함께 SHOULD에 따라 대응하는 RTCDataChannel을 생성하도록 신호를 보냅니다. 이렇게 하면 개별적으로 생성된 두 RTCDataChannel 객체가 연결됩니다. 두 번째 방법은 비대칭 속성을 가진 채널을 생성할 수 있게 하며, 일치하는 id를 지정하여 선언적으로 채널을 생성할 수 있게 합니다.

RTCDataChannel에는 다른 피어로 실제 데이터를 전달하는 데 사용되는 연관된 기저 데이터 전송이 있습니다. RTCSctpTransport(SCTP 연관의 상태를 나타냄)를 활용하는 SCTP 데이터 채널의 경우, 기저 데이터 전송은 SCTP 스트림 쌍입니다. 기저 데이터 전송의 전송 속성(예: 순서 보장 설정 및 신뢰성 모드)은 채널이 생성될 때 피어에 의해 구성됩니다. 채널의 속성은 생성된 이후 변경될 수 없습니다. 피어 간의 실제 와이어 프로토콜은 WebRTC DataChannel Protocol 명세 [RFC8831]에 의해 규정됩니다.

RTCDataChannel은 다양한 신뢰성 모드에서 동작하도록 구성할 수 있습니다. 신뢰성 있는 채널은 재전송을 통해 데이터가 상대 피어에 전달되도록 보장합니다. 비신뢰(불안정) 채널은 재전송 횟수를 제한하도록( maxRetransmits ) 또는 전송(재전송 포함)이 허용되는 시간을 설정하도록( maxPacketLifeTime ) 구성됩니다. 이 두 속성은 동시에 사용할 수 없으며, 동시에 사용하려고 시도하면 오류가 발생합니다. 이들 속성을 설정하지 않으면 신뢰성 있는 채널이 됩니다.

RTCDataChannelcreateDataChannel로 생성되거나 RTCDataChannelEvent를 통해 디스패치된 경우, 초기에는 MUST "connecting" 상태에 있어야 합니다. RTCDataChannel 객체의 기저 데이터 전송이 준비되면, 사용자 에이전트는 MUST RTCDataChannel이 열렸음을 알립니다.

6.2.1 데이터 채널 생성

RTCDataChannel 생성을 위해, 다음 단계를 수행합니다:

  1. channel을 새로 생성된 RTCDataChannel 객체로 둡니다.

  2. channel[[ReadyState]] 내부 슬롯을 두고 "connecting"으로 초기화합니다.

  3. channel[[BufferedAmount]] 내부 슬롯을 두고 0으로 초기화합니다.

  4. channel에 다음 이름의 내부 슬롯을 둡니다: [[DataChannelLabel]], [[Ordered]], [[MaxPacketLifeTime]], [[MaxRetransmits]], [[DataChannelProtocol]], [[Negotiated]], 그리고 [[DataChannelId]].

  5. channel[[IsTransferable]] 내부 슬롯을 두고 true로 초기화합니다.
  6. 작업을 큐에 추가 하여 다음 단계를 실행합니다:
    1. channel.[[IsTransferable]]false로 설정합니다.

    이 작업은 channel에 대한 데이터 채널에서 메시지 수신 알고리즘에 의해 큐에 추가되는 어떤 작업보다 먼저 실행되어야 합니다. 이는 RTCDataChannel의 전송 중에 메시지가 유실되지 않도록 보장합니다.

  7. channel을 반환합니다.

6.2.2 데이터 채널 열림 알림

사용자 에이전트가 RTCDataChannel이 열렸음을 알리려 할 때, 사용자 에이전트는 MUST 다음 단계를 실행하는 작업을 큐에 추가해야 합니다:

  1. 연관된 RTCPeerConnection 객체의 [[IsClosed]] 슬롯이 true이면, 이 단계를 중단합니다.

  2. channel을 알릴 RTCDataChannel 객체로 둡니다.

  3. channel.[[ReadyState]]가 "closing" 또는 "closed"라면, 이 단계를 중단합니다.

  4. channel.[[ReadyState]]를 "open"으로 설정합니다.

  5. 이벤트를 발생시키되, 이름을 open으로 하여 channel에서 발생시킵니다.

6.2.3 데이터 채널 인스턴스 알림

기저 데이터 전송을 알리려 할 때(다른 피어가 negotiated를 설정하지 않았거나 false로 설정하여 채널을 만든 경우), 생성 과정을 시작하지 않은 피어의 사용자 에이전트는 다음 단계를 실행하는 작업을 MUST 큐에 추가해야 합니다:

  1. connectionRTCPeerConnection 객체로 둡니다. 이 객체는 기저 데이터 전송과 연관되어 있습니다.

  2. connection.[[IsClosed]]true이면, 이 단계를 중단합니다.

  3. RTCDataChannel 생성, channel.

  4. configuration을 상대 피어로부터 수신한 정보 번들로 둡니다. 이는 WebRTC DataChannel Protocol 명세 [RFC8832]에 설명된 기저 데이터 전송을 설정하는 과정의 일부입니다.

  5. channel[[DataChannelLabel]], [[Ordered]], [[MaxPacketLifeTime]], [[MaxRetransmits]], [[DataChannelProtocol]], 그리고 [[DataChannelId]] 내부 슬롯을 configuration의 해당 값으로 초기화합니다.

  6. channel.[[Negotiated]]false로 초기화합니다.

  7. Append를 사용해 channelconnection.[[DataChannels]]에 추가합니다.

  8. channel.[[ReadyState]]를 "open"으로 설정합니다 (하지만 아직 open 이벤트는 발생시키지 않습니다).

    참고
    이는 datachannel 이벤트 핸들러 내부에서 open 이벤트가 발생하기 전에 메시지 전송을 시작할 수 있게 합니다.
  9. 이벤트를 발생시키되, 이름을 datachannel로 하여, RTCDataChannelEvent 인터페이스를 사용하고, channel 속성을 channel로 설정하여 connection에서 발생시킵니다.

  10. 데이터 채널이 열렸음을 알립니다.

후보 수정 38:닫히지 않은 RTCDataChannel의 GC 방지 (PR #2902)

6.2.4 종료 절차

6.2.4 종료 절차

RTCDataChannel 객체의 기저 데이터 전송종료 절차를 실행하여 급작스럽지 않게 종료될 수 있습니다. 그 경우 사용자 에이전트는 MUST 다음 단계를 실행하는 작업을 큐에 추가해야 합니다:

  1. channelRTCDataChannel 객체(그의 기저 데이터 전송이 닫힌 객체)로 둡니다.

  2. connectionchannel과 연관된 RTCPeerConnection 객체로 둡니다.

  3. Remove를 사용해 connection.[[DataChannels]]에서 channel을 제거합니다.

  4. channel.close에 의해 절차가 시작되지 않았다면, channel.[[ReadyState]]를 "closing"으로 설정하고, 이벤트를 발생시키되 이름을 closing으로 하여 channel에서 발생시킵니다.

  5. 다음 단계를 in parallel병렬로 실행합니다:

    1. channel의 현재 보류 중인 모든 메시지 전송을 완료합니다.

    2. channel기저 데이터 전송에 대해 정의된 종료 절차를 따릅니다:

      1. SCTP 기반 전송의 경우, [RFC8831] 섹션 6.7을 따릅니다.

    3. 닫습니다 channel데이터 전송을 관련 절차를 따라 닫습니다.

6.2.5 데이터 채널 닫힘 알림

RTCDataChannel 객체의 기저 데이터 전송닫힌 경우, 사용자 에이전트는 MUST 다음 단계를 실행하는 작업을 큐에 추가해야 합니다:

  1. channelRTCDataChannel 객체(그의 기저 데이터 전송이 닫힌 객체)로 둡니다.

  2. 만약 channel.[[ReadyState]]가 "closed"라면, 이 단계를 중단합니다.
  3. channel.[[ReadyState]]를 "closed"로 설정합니다.

  4. Remove를 사용해 여전히 존재한다면 connection.[[DataChannels]]에서 channel을 제거합니다.

  5. 전송오류와 함께 닫힌 경우, 이벤트를 발생시키되 이름을 error로 하고 RTCErrorEvent 인터페이스를 사용하며, 그 errorDetail 속성을 "sctp-failure"로 설정하여 channel에서 발생시킵니다.

  6. 이벤트를 발생시키되, 이름을 close로 하여 channel에서 발생시킵니다.

6.2.6 데이터 채널 전송

RTCDataChannel전송 단계valuedataHolder가 주어졌을 때 다음과 같습니다:

  1. value.[[IsTransferable]]false이면, DataCloneError DOMException을 throw합니다.

  2. dataHolder.[[ReadyState]]value.[[ReadyState]]로 설정합니다.

  3. dataHolder.[[DataChannelLabel]]value.[[DataChannelLabel]]로 설정합니다.

  4. dataHolder.[[Ordered]]value.[[Ordered]]로 설정합니다.

  5. dataHolder.[[MaxPacketLifeTime]]value..[[MaxPacketLifeTime]]로 설정합니다.

  6. dataHolder.[[MaxRetransmits]]value.[[MaxRetransmits]]로 설정합니다.

  7. dataHolder.[[DataChannelProtocol]]value.[[DataChannelProtocol]]로 설정합니다.

  8. dataHolder.[[Negotiated]]value.[[Negotiated]]로 설정합니다.

  9. dataHolder.[[DataChannelId]]value.[[DataChannelId]]로 설정합니다.

  10. dataHolder기저 데이터 전송value기저 데이터 전송으로 설정합니다.

  11. value.[[IsTransferable]]false로 설정합니다.

  12. value.[[ReadyState]]를 "closed"로 설정합니다.

RTCDataChannel전송-수신 단계dataHolderchannel이 주어졌을 때 다음과 같습니다:

  1. channel.[[ReadyState]]dataHolder.[[ReadyState]]로 초기화합니다.

  2. channel.[[DataChannelLabel]]dataHolder.[[DataChannelLabel]]로 초기화합니다.

  3. channel.[[Ordered]]dataHolder.[[Ordered]]로 초기화합니다.

  4. channel.[[MaxPacketLifeTime]]dataHolder.[[MaxPacketLifeTime]]로 초기화합니다.

  5. channel.[[MaxRetransmits]]dataHolder.[[MaxRetransmits]]로 초기화합니다.

  6. channel.[[DataChannelProtocol]]dataHolder.[[DataChannelProtocol]]로 초기화합니다.

  7. channel.[[Negotiated]]dataHolder.[[Negotiated]]로 초기화합니다.

  8. channel.[[DataChannelId]]dataHolder.[[DataChannelId]]로 초기화합니다.

  9. channel기저 데이터 전송dataHolder기저 데이터 전송으로 초기화합니다.

위 단계들은 [[BufferedAmount]]를 전송할 필요가 없습니다. 그 값은 항상 0이기 때문입니다. 그 이유는 RTCDataChannel이 전송될 수 있는 경우가 send() 알고리즘이 전송 전에 호출되지 않았을 때뿐이기 때문입니다.

기저 데이터 전송전송-수신 단계 시점에 닫혀 있다면, RTCDataChannel 객체는 데이터 채널 닫힘 알림 알고리즘을 전송-수신 단계 직후 즉시 실행하여 닫히게 됩니다.

6.2.7 데이터 채널 생성 시 오류

경우에 따라, 사용자 에이전트는 RTCDataChannel을 생성할 수 없어 해당 채널의 기저 데이터 전송을 만들지 못할 수 있습니다. 예를 들어, 데이터 채널의 id가 SCTP 핸드셰이크에서 [RFC8831] 구현에 의해 협상된 범위를 벗어날 수 있습니다. 사용자 에이전트가 RTCDataChannel기저 데이터 전송을 생성할 수 없다고 판단하면, 사용자 에이전트는 MUST 다음 단계를 실행하는 작업을 큐에 추가해야 합니다:

  1. channel을 사용자 에이전트가 기저 데이터 전송을 생성하지 못한 RTCDataChannel 객체로 둡니다.

  2. channel.[[ReadyState]]를 "closed"로 설정합니다.

  3. 이벤트를 발생시키되, 이름을 error로 하고 RTCErrorEvent 인터페이스를 사용하며, errorDetail 속성을 "data-channel-failure"로 설정하여 channel에서 발생시킵니다.

  4. 이벤트를 발생시키되, 이름을 close로 하여 channel에서 발생시킵니다.

6.2.8 데이터 채널에서 메시지 수신

RTCDataChannel 메시지가 기저 데이터 전송을 통해 형식 type 및 데이터 rawData와 함께 수신되었을 때, 사용자 에이전트는 MUST 다음 단계를 실행하는 작업을 큐에 추가해야 합니다:

  1. channel을 사용자 에이전트가 메시지를 수신한 RTCDataChannel 객체로 둡니다.

  2. connectionchannel과 연관된 RTCPeerConnection 객체로 둡니다.

  3. channel.[[ReadyState]]가 "open"이 아니면, 이 단계를 중단하고 rawData를 폐기합니다.

  4. typechannel.binaryType에 따라 다음 하위 단계를 수행합니다:

    • typerawDatastring임을 나타내면:

      datarawData를 UTF-8로 디코딩한 결과를 나타내는 DOMString으로 둡니다.

    • typerawData가 바이너리임을 나타내고 binaryType"blob"이면:

      data를 원시 데이터 소스로 rawData를 포함하는 새로운 Blob 객체로 둡니다.

    • typerawData가 바이너리임을 나타내고 binaryType"arraybuffer"이면:

      data를 원시 데이터 소스로 rawData를 포함하는 새로운 ArrayBuffer 객체로 둡니다.

  5. 이벤트를 발생시키되, 이름을 message로 하고 MessageEvent 인터페이스를 사용하며, origin 속성을 origin의 직렬화connection.[[DocumentOrigin]]에 대해 초기화하고, data 속성을 data로 초기화하여 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);
};

속성

label 타입 USVString, 읽기 전용

label 속성은 이 RTCDataChannel 객체를 다른 RTCDataChannel 객체와 구분하기 위해 사용할 수 있는 라벨을 나타냅니다. 스크립트는 동일한 라벨을 가진 여러 RTCDataChannel 객체를 생성할 수 있습니다. 가져올 때, 이 속성은 반드시 [[DataChannelLabel]] 슬롯의 값을 반환해야 합니다.

ordered 타입 boolean, 읽기 전용

ordered 속성은 해당 RTCDataChannel이 순서 보장일 경우 true, 무순서 전달이 허용되면 false를 반환합니다. 가져올 때, 이 속성은 반드시 [[Ordered]] 슬롯의 값을 반환해야 합니다.

maxPacketLifeTime 타입 unsigned short, 읽기 전용, nullable

maxPacketLifeTime 속성은 불안정 모드에서 전송과 재전송이 발생할 수 있는 시간 창(밀리초)을 반환합니다. 가져올 때, 이 속성은 반드시 [[MaxPacketLifeTime]] 슬롯의 값을 반환해야 합니다.

maxRetransmits 타입 unsigned short, 읽기 전용, nullable

maxRetransmits 속성은 불안정 모드에서 시도되는 최대 재전송 횟수를 반환합니다. 가져올 때, 이 속성은 반드시 [[MaxRetransmits]] 슬롯의 값을 반환해야 합니다.

protocol 타입 USVString, 읽기 전용

protocol 속성은 이 RTCDataChannel과 함께 사용하는 하위 프로토콜의 이름을 반환합니다. 가져올 때, 이 속성은 반드시 [[DataChannelProtocol]] 슬롯의 값을 반환해야 합니다.

negotiated 타입 boolean, 읽기 전용

negotiated 속성은 이 RTCDataChannel이 애플리케이션에 의해 협상되었으면 true, 그렇지 않으면 false를 반환합니다. 가져올 때, 이 속성은 반드시 [[Negotiated]] 슬롯의 값을 반환해야 합니다.

id 타입 unsigned short, 읽기 전용, nullable

id 속성은 이 RTCDataChannel의 ID를 반환합니다. 값은 초기에는 null이며, 이는 채널 생성 시 ID가 제공되지 않았고 SCTP 전송의 DTLS 역할이 아직 협상되지 않은 경우 반환됩니다. 그렇지 않으면 스크립트가 선택했거나 사용자 에이전트가 [RFC8832]에 따라 생성한 ID를 반환합니다. ID가 null이 아닌 값으로 설정된 이후에는 변경되지 않습니다. 가져올 때, 이 속성은 반드시 [[DataChannelId]] 슬롯의 값을 반환해야 합니다.

readyState 타입 RTCDataChannelState, 읽기 전용

readyState 속성은 RTCDataChannel 객체의 상태를 나타냅니다. 가져올 때, 이 속성은 반드시 [[ReadyState]] 슬롯의 값을 반환해야 합니다.

bufferedAmount 타입 unsigned long, 읽기 전용

bufferedAmount 속성은 가져올 때 반드시 [[BufferedAmount]] 슬롯의 값을 반환해야 합니다. 이 속성은 send()를 사용해 큐에 넣은 애플리케이션 데이터(UTF-8 텍스트와 바이너리 데이터)의 바이트 수를 노출합니다. 데이터 전송이 병렬로 발생할 수 있지만, 경쟁 상태를 방지하기 위해 현재 작업이 이벤트 루프로 제어를 반환하기 전에는 반환 값이 감소해서는 안 됩니다. 이 값에는 프로토콜로 인한 프레이밍 오버헤드나 운영 체제 또는 네트워크 하드웨어의 버퍼링은 포함되지 않습니다. [[BufferedAmount]] 슬롯의 값은 send() 메서드를 호출할 때마다, [[ReadyState]] 슬롯이 "open"인 한 증가하지만, 채널이 닫혀도 이 슬롯은 0으로 리셋되지 않습니다. 기저 데이터 전송이 큐에서 데이터를 보낼 때, 사용자 에이전트는 전송된 바이트 수만큼 [[BufferedAmount]]를 줄이는 작업을 반드시 큐에 추가해야 합니다.

bufferedAmountLowThreshold 타입 unsigned long

bufferedAmountLowThreshold 속성은 bufferedAmount가 낮다고 간주되는 임계값을 설정합니다. bufferedAmount가 이 임계값보다 높은 상태에서 임계값과 같거나 그 이하로 감소하면 bufferedamountlow 이벤트가 발생합니다. bufferedAmountLowThreshold의 초기값은 각 새로운 RTCDataChannel에서 0이지만, 애플리케이션은 언제든지 값을 변경할 수 있습니다.

onopen 타입 EventHandler
이 이벤트 핸들러의 이벤트 타입은 open입니다.
onbufferedamountlow 타입 EventHandler
이 이벤트 핸들러의 이벤트 타입은 bufferedamountlow입니다.
onerror 타입 EventHandler

이 이벤트 핸들러의 이벤트 타입은 RTCErrorEvent입니다. errorDetail에는 "sctp-failure"가 포함되고, sctpCauseCode에는 SCTP 원인 코드 값이, message에는 SCTP 원인별 정보(필요 시 추가 텍스트 포함)가 담깁니다.

onclosing 타입 EventHandler

이 이벤트 핸들러의 이벤트 타입은 closing입니다.

onclose 타입 EventHandler

이 이벤트 핸들러의 이벤트 타입은 close입니다.

onmessage 타입 EventHandler

이 이벤트 핸들러의 이벤트 타입은 message입니다.

binaryType 타입 BinaryType

binaryType 속성은 마지막으로 설정된 값을 반환합니다. RTCDataChannel 객체가 생성될 때, binaryType 속성은 문자열 "arraybuffer"로 초기화되어야 합니다.

이 속성은 바이너리 데이터를 스크립트에 어떻게 노출할지를 제어합니다. Web Socket의 binaryType을 참조하세요.

메서드

close()

RTCDataChannel을 닫습니다. 이 메서드는 해당 RTCDataChannel 객체가 로컬 피어에서 생성되었는지 원격 피어에서 생성되었는지와 관계없이 호출할 수 있습니다.

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

  1. channel을 이제 곧 닫히려는 RTCDataChannel 객체로 둡니다.

  2. channel.[[ReadyState]]가 "closing" 또는 "closed"이면, 이 단계를 중단합니다.

  3. channel.[[ReadyState]]를 "closing"으로 설정합니다.

  4. 종료 절차가 아직 시작되지 않았다면, 시작합니다.

send

인자 타입이 string 객체인 경우에 대한 send() 알고리즘에 기술된 단계를 실행합니다.

send

인자 타입이 Blob 객체인 경우에 대한 send() 알고리즘에 기술된 단계를 실행합니다.

send

인자 타입이 ArrayBuffer 객체인 경우에 대한 send() 알고리즘에 기술된 단계를 실행합니다.

send

인자 타입이 ArrayBufferView 객체인 경우에 대한 send() 알고리즘에 기술된 단계를 실행합니다.

send() 메서드는 다양한 데이터 인자 타입을 처리하도록 오버로드되어 있습니다. 메서드의 어떤 버전이 호출되더라도, 사용자 에이전트는 반드시 다음 단계를 실행해야 합니다:

  1. channel을 데이터를 전송할 RTCDataChannel 객체로 둡니다.

  2. channel.[[IsTransferable]]false로 설정합니다.

  3. channel.[[ReadyState]]가 "open"이 아니면, throw를 통해 InvalidStateError를 던집니다.

  4. 메서드 인자의 타입에 해당하는 하위 단계를 실행합니다:

    • string 객체:

      data를 메서드 인자를 UTF-8로 인코딩한 결과를 나타내는 바이트 버퍼로 둡니다.

    • Blob 객체:

      data를 해당 Blob 객체가 표현하는 원시 데이터로 둡니다.

      참고
      Blob 객체로부터 실제로 data를 가져오는 작업은 비동기적으로 일어날 수 있지만, 사용자 에이전트는 channel기저 데이터 전송에 데이터를 큐잉할 때 send 메서드가 호출된 순서를 보장합니다. data의 바이트 크기는 동기적으로 알아야 합니다.
    • ArrayBuffer 객체:

      data를 해당 ArrayBuffer 객체가 기술하는 버퍼에 저장된 데이터로 둡니다.

    • ArrayBufferView 객체:

      data를 해당 ArrayBuffer 객체의, ArrayBufferView 객체가 참조하는 구간에 저장된 데이터로 둡니다.

    참고
    이 메서드가 오버로드하지 않은 어떤 데이터 인자 타입도 TypeError를 유발합니다. 여기에는 nullundefined가 포함됩니다.
  5. data의 바이트 크기가 channel에 연관된 RTCSctpTransportmaxMessageSize 값을 초과하면, throw를 통해 TypeError를 던집니다.

  6. channel기저 데이터 전송data를 전송 큐에 넣습니다. 사용 가능한 버퍼 공간이 충분하지 않아 data를 큐잉할 수 없는 경우, throw를 통해 OperationError를 던집니다.

    참고
    실제 데이터 전송은 병렬로 발생합니다. 데이터를 보내는 과정에서 SCTP 레벨 오류가 발생하면, 애플리케이션은 비동기적으로 onerror를 통해 통지받습니다.
  7. [[BufferedAmount]] 슬롯의 값을 data의 바이트 크기만큼 증가시킵니다.

WebIDLdictionary RTCDataChannelInit {
  boolean ordered = true;
  [EnforceRange] unsigned short maxPacketLifeTime;
  [EnforceRange] unsigned short maxRetransmits;
  USVString protocol = "";
  boolean negotiated = false;
  [EnforceRange] unsigned short id;
};

사전 RTCDataChannelInit 멤버

ordered 타입 boolean, 기본값 true

false로 설정하면 데이터가 순서에 상관없이 전달될 수 있습니다. 기본값인 true는 데이터가 순서대로 전달됨을 보장합니다.

maxPacketLifeTime 타입 unsigned short

확인 응답이 없을 때 채널이 데이터를 전송 또는 재전송할 수 있는 시간(밀리초)을 제한합니다. 이 값이 사용자 에이전트가 지원하는 최대값을 초과하면 클램핑될 수 있습니다.

maxRetransmits 타입 unsigned short

전달에 실패할 경우 채널이 데이터를 재전송하려는 최대 횟수를 제한합니다. 이 값이 사용자 에이전트가 지원하는 최대값을 초과하면 클램핑될 수 있습니다.

protocol 타입 USVString, 기본값 ""

이 채널에 사용되는 서브프로토콜 이름입니다.

negotiated 타입 boolean, 기본값 false

기본값 false는 사용자 에이전트가 인밴드로 채널을 알리고, 상대 피어가 해당하는 RTCDataChannel 객체를 디스패치하도록 지시함을 의미합니다. true로 설정하면 채널 협상과 동일한 RTCDataChannel 객체 생성을 애플리케이션이 수행해야 하며, 상대 피어에서 동일한 id를 사용해야 합니다.

참고
true로 설정한 경우, 상대 피어가 수신할 데이터 채널을 생성하기 전에는 메시지를 보내지 않도록 애플리케이션이 주의해야 합니다. 연관된 데이터 채널이 없는 SCTP 스트림에서 메시지를 수신하는 동작은 정의되지 않았으며, 조용히 드롭될 수 있습니다. 양 끝점이 첫 번째 offer/answer 교환이 완료되기 전에 각자의 데이터 채널을 생성한다면 이런 상황은 발생하지 않습니다.
id 타입 unsigned short

negotiated가 true일 때 채널 ID를 설정합니다. negotiated가 false일 때는 무시됩니다.

WebIDLenum RTCDataChannelState {
  "connecting",
  "open",
  "closing",
  "closed"
};
RTCDataChannelState 열거형 설명
열거값 설명
connecting

사용자 에이전트가 기저 데이터 전송을 설정하려고 시도하고 있습니다. 이는 RTCDataChannel 객체의 초기 상태이며, createDataChannel로 생성되었는지, RTCDataChannelEvent의 일부로 디스패치되었는지와 관계없이 동일합니다.

open

기저 데이터 전송이 설정되어 통신이 가능합니다.

closing

절차를 따라 기저 데이터 전송을 종료하기 시작했습니다.

closed

기저 데이터 전송closed 상태가 되었거나, 설정할 수 없었습니다.

6.3 RTCDataChannelEvent

datachannel 이벤트는 RTCDataChannelEvent 인터페이스를 사용합니다.

WebIDL[Exposed=Window]
interface RTCDataChannelEvent : Event {
  constructor(DOMString type, RTCDataChannelEventInit eventInitDict);
  readonly attribute RTCDataChannel channel;
};

생성자

RTCDataChannelEvent.constructor()

속성

channel 타입 RTCDataChannel, 읽기 전용

channel 속성은 이벤트와 연관된 RTCDataChannel 객체를 나타냅니다.

WebIDLdictionary RTCDataChannelEventInit : EventInit {
  required RTCDataChannel channel;
};

사전 RTCDataChannelEventInit 멤버

channel 타입 RTCDataChannel, 필수

이벤트로 알릴 RTCDataChannel 객체입니다.

6.4 가비지 컬렉션

RTCDataChannel 객체는 다음의 경우 MUST 가비지 컬렉션되지 않아야 합니다:

7. 피어-투-피어 DTMF

이 섹션은 RTCRtpSender에 있는 인터페이스를 설명하며, RTCPeerConnection을 통해 DTMF (전화 키패드) 값을 전송합니다. 다른 피어로 DTMF를 전송하는 방법의 세부 사항은 [RFC7874]에 설명되어 있습니다.

7.1 RTCRtpSender 인터페이스 확장

피어-투-피어 DTMF API는 아래에 설명된 대로 RTCRtpSender 인터페이스를 확장합니다.

WebIDL          partial interface RTCRtpSender {
  readonly attribute RTCDTMFSender? dtmf;
};

속성

dtmf 타입 RTCDTMFSender, 읽기 전용, nullable

가져올 때, dtmf 속성은 [[Dtmf]] 내부 슬롯의 값을 반환합니다. 이 슬롯은 DTMF를 전송하는 데 사용할 수 있는 RTCDTMFSender를 나타내며, 설정되지 않았다면 null입니다. [[Dtmf]] 내부 슬롯은 RTCRtpSender[[SenderTrack]]의 종류가 "audio"일 때 설정됩니다.

7.2 RTCDTMFSender

RTCDTMFSender를 생성하기 위해, 사용자 에이전트는 MUST 다음 단계를 실행합니다:

  1. dtmf를 새로 생성된 RTCDTMFSender 객체로 둡니다.

  2. dtmf[[Duration]] 내부 슬롯을 둡니다.

  3. dtmf[[InterToneGap]] 내부 슬롯을 둡니다.

  4. dtmf[[ToneBuffer]] 내부 슬롯을 둡니다.

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;
};

속성

ontonechange 타입 EventHandler

이 이벤트 핸들러의 이벤트 타입은 tonechange입니다.

canInsertDTMF 타입 boolean, 읽기 전용

RTCDTMFSender dtmfSender가 DTMF를 전송할 수 있는지 여부입니다. 가져올 때, 사용자 에이전트는 MUST dtmfSender에 대해 DTMF를 전송할 수 있는지 결정의 결과를 반환해야 합니다.

toneBuffer 타입 DOMString, 읽기 전용

toneBuffer 속성은 재생이 남아 있는 톤들의 목록을 MUST 반환해야 합니다. 이 목록의 문법, 내용 및 해석은 insertDTMF를 참조하십시오.

메서드

insertDTMF

RTCDTMFSender 객체의 insertDTMF 메서드는 DTMF 톤을 전송하는 데 사용됩니다.

tones 매개변수는 일련의 문자로 처리됩니다. 문자 0에서 9, A에서 D, #, *는 해당 DTMF 톤을 생성합니다. 문자 a에서 d는 입력 시 대문자로 정규화되어 A에서 D와 동일해야 합니다(MUST). [RTCWEB-AUDIO] 섹션 3에서 언급했듯이, 문자 0에서 9, A에서 D, #, *에 대한 지원은 필수입니다. 문자 ','는 MUST 지원되어야 하며, tones 매개변수의 다음 문자를 처리하기 전에 2초의 지연을 의미합니다. 다른 모든 문자(그리고 그 문자들만)는 MUST 인식되지 않음으로 간주되어야 합니다.

duration 매개변수는 tones 매개변수에 전달된 각 문자에 사용할 ms 단위를 나타냅니다. duration은 6000ms를 초과할 수 없고 40ms 미만일 수 없습니다. 기본 duration은 각 톤에 대해 100ms입니다.

interToneGap 매개변수는 톤 사이의 간격(ms)을 나타냅니다. 사용자 에이전트는 이를 최소 30ms, 최대 6000ms로 클램핑합니다. 기본값은 70ms입니다.

브라우저는 RTP 패킷 경계에 맞추기 위해 durationinterToneGap 시간을 늘릴 수 MAY 있지만, 단일 RTP 오디오 패킷의 길이보다 더 많이 늘려서는 MUST 안 됩니다.

insertDTMF() 메서드가 호출되면, 사용자 에이전트는 MUST 다음 단계를 실행해야 합니다:

  1. sender를 DTMF 전송에 사용되는 RTCRtpSender로 둡니다.
  2. transceiversender와 연관된 RTCRtpTransceiver 객체로 둡니다.

  3. dtmfsender와 연관된 RTCDTMFSender로 둡니다.
  4. DTMF를 전송할 수 있는지 결정dtmf에 대해 false를 반환하면, throw를 통해 InvalidStateError를 던집니다.
  5. tones를 메서드의 첫 번째 인자로 둡니다.
  6. duration를 메서드의 두 번째 인자로 둡니다.
  7. interToneGap를 메서드의 세 번째 인자로 둡니다.
  8. tonesunrecognized 문자가 하나라도 포함되어 있다면, throw를 통해 InvalidCharacterError를 던집니다.
  9. 객체의 [[ToneBuffer]] 슬롯을 tones로 설정합니다.
  10. dtmf.[[Duration]]duration 값으로 설정합니다.
  11. dtmf.[[InterToneGap]]interToneGap 값으로 설정합니다.
  12. duration 값이 40ms보다 작으면, dtmf.[[Duration]]을 40ms로 설정합니다.
  13. duration 매개변수의 값이 6000ms보다 크면, dtmf.[[Duration]]을 6000ms로 설정합니다.
  14. interToneGap 값이 30ms보다 작으면, dtmf.[[InterToneGap]]을 30ms로 설정합니다.
  15. interToneGap 값이 6000ms보다 크면, dtmf.[[InterToneGap]]을 6000ms로 설정합니다.
  16. [[ToneBuffer]] 슬롯이 빈 문자열이라면, 이 단계를 중단합니다.
  17. DTMF 재생 작업 단계를 실행할 작업이 예약되어 있으면 이 단계를 중단하고, 그렇지 않으면 다음의 DTMF 재생 작업 단계를 실행하는 작업을 큐에 추가합니다:
    1. If transceiver.[[CurrentDirection]]If determine if DTMF can be sent is neither "sendrecv" nor "sendonly"for dtmf returns false, 이 단계를 중단합니다.
    2. [[ToneBuffer]] 슬롯이 빈 문자열을 포함하면, 이벤트를 발생시키되 이름을 tonechange로 하고, RTCDTMFToneChangeEvent 인터페이스를 사용하며 tone 속성을 빈 문자열로 설정하여 RTCDTMFSender 객체에서 발생시키고, 이 단계를 중단합니다.
    3. [[ToneBuffer]] 슬롯에서 첫 문자를 제거하고, 그 문자를 tone으로 둡니다.
    4. tone","이면, 관련 RTP 미디어 스트림에서 톤 전송을 2000ms 지연시키고, 지금으로부터 2000ms 후에 실행될 작업을 큐에 추가하여 DTMF 재생 작업 단계를 실행합니다.
    5. tone","가 아니면, 적절한 코덱을 사용하여 관련 RTP 미디어 스트림에서 tone의 재생을 [[Duration]] ms 동안 시작하고, 지금으로부터 [[Duration]] + [[InterToneGap]] ms 후에 실행될 작업을 큐에 추가하여 DTMF 재생 작업 단계를 실행합니다.
    6. 이벤트를 발생시키되 이름을 tonechange로 하고, RTCDTMFToneChangeEvent 인터페이스를 사용하며, tone 속성을 tone으로 설정하여 RTCDTMFSender 객체에서 발생시킵니다.

insertDTMF는 톤 버퍼를 대체하므로, 재생 중인 DTMF 톤에 추가하려면, 남아 있는 톤들([[ToneBuffer]] 슬롯에 저장됨)과 새 톤을 함께 연결한 문자열로 insertDTMF를 호출해야 합니다. 빈 tones 매개변수로 insertDTMF를 호출하면, 현재 재생 중인 톤 이후에 재생 대기 중인 모든 톤을 취소할 수 있습니다.

7.3 canInsertDTMF 알고리즘

DTMF를 전송할 수 있는지 결정하기 위해 RTCDTMFSender 인스턴스 dtmfSender에 대해, 사용자 에이전트는 MUST 다음 단계를 실행합니다:

  1. senderdtmfSender와 연관된 RTCRtpSender로 둡니다.
  2. transceiversender와 연관된 RTCRtpTransceiver로 둡니다.
  3. connectiontransceiver와 연관된 RTCPeerConnection으로 둡니다.
  4. connectionRTCPeerConnectionState가 "connected"가 아니면 false를 반환합니다.
  5. transceiver.[[Stopping]]true이면 false를 반환합니다.
  6. sender.[[SenderTrack]]null이면 false를 반환합니다.
  7. transceiver.[[CurrentDirection]]이 "sendrecv"도 "sendonly"도 아니면 false를 반환합니다.
  8. sender.[[SendEncodings]][0].activefalse이면 false를 반환합니다.
  9. sender로 전송하기 위해 mimetype이 "audio/telephone-event"인 코덱이 협상되지 않았다면, false를 반환합니다.
  10. 그 외의 경우, true를 반환합니다.

7.4 RTCDTMFToneChangeEvent

tonechange 이벤트는 RTCDTMFToneChangeEvent 인터페이스를 사용합니다.

WebIDL[Exposed=Window]
interface RTCDTMFToneChangeEvent : Event {
  constructor(DOMString type, optional RTCDTMFToneChangeEventInit eventInitDict = {});
  readonly attribute DOMString tone;
};

생성자

RTCDTMFToneChangeEvent.constructor()

속성

tone 타입 DOMString, 읽기 전용

tone 속성은 방금 재생이 시작된 톤의 문자("," 포함)를 담고 있습니다 (insertDTMF 참조). 값이 빈 문자열이라면, [[ToneBuffer]] 슬롯이 빈 문자열이며 이전 톤 재생이 완료되었음을 나타냅니다.

WebIDL          dictionary RTCDTMFToneChangeEventInit : EventInit {
  DOMString tone = "";
};

사전 RTCDTMFToneChangeEventInit 멤버

tone 타입 DOMString, 기본값 ""

tone 속성은 방금 재생이 시작된 톤의 문자("," 포함)를 담고 있습니다 (insertDTMF 참조). 값이 빈 문자열이라면, [[ToneBuffer]] 슬롯이 빈 문자열이며 이전 톤 재생이 완료되었음을 나타냅니다.

8. 통계 모델

8.1 소개

기본 통계 모델은 브라우저가 monitored object들에 대한 통계 집합을 stats object의 형태로 유지한다는 것입니다.

관련 객체들의 그룹은 selector로 참조될 수 있습니다. 예를 들어 selector는 MediaStreamTrack일 수 있습니다. 트랙이 유효한 selector가 되기 위해서는 MUST MediaStreamTrack이어야 하며, 통계 요청이 발행된 RTCPeerConnection 객체에 의해 전송되거나 수신되어야 합니다. 호출하는 웹 애플리케이션은 getStats() 메서드에 selector를 제공하고, 브라우저는 통계 선택 알고리즘에 따라 selector와 관련된 통계 집합을 (JavaScript에서) 내보냅니다. 이 알고리즘은 selector의 sender 또는 receiver를 대상으로 한다는 점에 유의하십시오.

stats object로 반환되는 통계는 반복 쿼리가 RTCStatsid 사전 멤버로 연결되도록 설계되어 있습니다. 따라서 웹 애플리케이션은 특정 기간의 시작과 끝에 측정을 요청하여 그 기간의 측정을 수행할 수 있습니다.

일부 예외를 제외하고, monitored object는 일단 생성되면 연관된 RTCPeerConnection의 수명 동안 존재합니다. 이는 연관된 피어 연결이 close된 이후에도 getStats() 결과에서 해당 통계를 사용할 수 있음을 보장합니다.

오직 소수의 monitored object만이 더 짧은 수명을 가집니다. 이러한 객체의 통계는 이후의 getStats() 결과에서는 더 이상 사용할 수 없습니다. [WEBRTC-STATS]의 객체 설명은 이러한 monitored object가 언제 삭제되는지 설명합니다.

8.2 RTCPeerConnection 인터페이스 확장

통계 API는 아래에 설명된 대로 RTCPeerConnection 인터페이스를 확장합니다.

WebIDL          partial interface RTCPeerConnection {
  Promise<RTCStatsReport> getStats(optional MediaStreamTrack? selector = null);
};

메서드

getStats

주어진 selector에 대한 통계를 수집하고, 결과를 비동기적으로 보고합니다.

getStats() 메서드가 호출되면, 사용자 에이전트는 MUST 다음 단계를 실행해야 합니다:

  1. selectorArg를 메서드의 첫 번째 인자로 둡니다.

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

  3. selectorArgnull이면, selectornull로 둡니다.

  4. selectorArgMediaStreamTrack인 경우, selectorconnection에서 RTCRtpSender 또는 RTCRtpReceiver로 둡니다. 이때 track 속성이 selectorArg와 일치해야 합니다. 그러한 sender나 receiver가 없거나, 하나를 초과하여 조건에 맞는 sender 또는 receiver가 존재하면, 새로 생성된 InvalidAccessError거부된 프라미스를 반환합니다.

  5. p를 새로운 프라미스로 둡니다.

  6. 다음 단계를 병렬로 실행합니다:

    1. 통계 선택 알고리즘에 따라 selector가 지시하는 통계를 수집합니다.

    2. 현재 realm의 global objectglobal로 하여 네트워킹 작업 소스에서 글로벌 태스크를 큐에 넣고, 수집된 통계를 포함하는 결과 RTCStatsReport 객체로 resolve하여 p를 이행합니다.

  7. p를 반환합니다.

8.3 RTCStatsReport 객체

getStats() 메서드는 성공 결과를 RTCStatsReport 객체의 형태로 전달합니다. RTCStatsReport 객체는 검사된 객체(즉, id 속성을 가진 RTCStats 인스턴스)들을 식별하는 문자열과, 그에 해당하는 RTCStats 파생 사전 간의 매핑입니다.

하나의 RTCStatsReport는 여러 개의 RTCStats 파생 사전으로 구성될 수 있으며, 각각은 구현이 selector와 관련 있다고 판단한 하나의 기저 객체에 대한 통계를 보고합니다. selector의 총계를 얻으려면 특정 종류의 통계를 모두 합산합니다. 예를 들어, RTCRtpSender가 네트워크 상에서 자신의 트랙을 전송하기 위해 다중 SSRC를 사용하는 경우, RTCStatsReport는 SSRC당 하나의 RTCStats 파생 사전을 포함할 수 있으며, 이는 ssrc 통계 속성의 값으로 구분될 수 있습니다.

WebIDL[Exposed=Window]
interface RTCStatsReport {
  readonly maplike<DOMString, object>;
};

이를 사용하여 이 통계 보고서를 구성하는 RTCStats에서 파생된 다양한 사전을 가져옵니다. 지원되는 프로퍼티 이름 집합[WEBIDL]은 이 통계 보고서에 대해 생성된 모든 RTCStats 파생 사전의 id로 정의됩니다.

8.4 RTCStats 사전

RTCStats 사전은 특정 stats object를 구성하기 위해 검사된 특정 monitored object를 표현합니다. RTCStats 사전은 timestamptype과 같은 기본 속성 집합을 지정하는 기본 타입입니다. 구체적인 통계는 RTCStats 사전을 확장하여 추가합니다.

통계 이름은 표준화되어 있지만, 특정 구현은 실험적인 값이나 아직 웹 애플리케이션에 알려지지 않은 값을 사용할 수 있습니다. 따라서 애플리케이션은 알 수 없는 통계에 대비할 MUST가 있습니다.

통계는 계산에서 합리적인 값을 얻기 위해 서로 동기화되어야 합니다. 예를 들어 bytesSentpacketsSent가 모두 보고되는 경우 두 값은 같은 구간에 대해 보고되어야 하므로, "평균 패킷 크기"를 "bytes / packets"로 계산할 수 있습니다. 구간이 다르면 오차가 발생합니다. 따라서 구현은 하나의 RTCStats 파생 사전 내의 모든 통계에 대해 동기화된 값을 MUST 반환해야 합니다.

WebIDLdictionary RTCStats {
  required DOMHighResTimeStamp timestamp;
  required RTCStatsType type;
  required DOMString id;
};

사전 RTCStats 멤버

timestamp of type DOMHighResTimeStamp
Candidate Correction 50:통계 타임스탬프에 Performance.timeOrigin + Performance.now() 사용 (PR #3005)

timestamp는 타입이 타임스탬프는 DOMHighResTimeStamp이며, 이 객체와 연관되어 있습니다. 시간은 UNIX epoch(1970년 1월[HIGHRES-TIME]에 따라,) Performance.timeOrigin UTC) + Performancenow()로 정의되며, 정보가 수집된 시점을 나타냅니다. 원격 소스(예: 수신된 RTCP 패킷)에서 온 통계의 경우, timestamp 는 정보가 로컬 엔드포인트에 도착한 시간을 나타냅니다. 원격 타임스탬프는 해당되는 경우 RTCStats 파생 사전의 추가 필드에서 찾을 수 있습니다.

type of type RTCStatsType

이 객체의 유형입니다.

type 속성은 이 RTCStats 사전이 표현하는 가장 구체적인 타입의 이름으로 초기화되어야 MUST 합니다.

id of type DOMString

RTCStats 객체를 생성하기 위해 검사된 객체와 연관된 고유한 id입니다. 서로 다른 RTCStatsReport 객체에서 추출된 두 개의 RTCStats 객체는 동일한 기저 객체를 검사하여 생성된 경우 동일한 id를 가져야 MUST 합니다.

통계 id는 애플리케이션에 의해 예측 가능해서는 MUST NOT 합니다. 이는 애플리케이션이 특정 사용자 에이전트의 id 생성 방식에 의존하는 것을 방지하며, 특정 통계 객체의 id를 미리 읽지 않은 이상 해당 id로 통계 객체를 얻지 못하게 합니다.

사용자 에이전트는 위 요구사항을 충족하는 한 어떤 형식의 id도 자유롭게 선택할 수 있습니다.

참고

사용자 에이전트는 피어 연결마다 고유한 salt를 사용하는 해시 함수를 통해 예측 가능한 문자열을 예측 불가능한 문자열로 변환할 수 있습니다. 이는 구현이 내부적으로 예측 가능한 id를 유지하도록 하여, getStats() 호출 간 통계 객체가 안정적인 id를 가지도록 보장하기를 용이하게 합니다.

RTCStatsType의 유효한 값 집합과, 그들이 가리키는 RTCStats로부터 파생된 사전은 [WEBRTC-STATS]에 문서화되어 있습니다.

8.5 통계 선택 알고리즘

통계 선택 알고리즘은 다음과 같습니다:

  1. result를 빈 RTCStatsReport로 둡니다.
  2. selectornull이면, 전체 connection에 대한 통계를 수집하여 result에 추가하고, result를 반환한 다음 이 단계를 중단합니다.
  3. selectorRTCRtpSender인 경우, 다음 객체들에 대한 통계를 수집하고 result에 추가합니다:
  4. selectorRTCRtpReceiver인 경우, 다음 객체들에 대한 통계를 수집하고 result에 추가합니다:
  5. result를 반환합니다.

8.6 구현 필수 통계

[WEBRTC-STATS]에 나열된 통계는 광범위한 사용 사례를 포괄하도록 의도되었습니다. 모든 WebRTC 구현이 이들을 모두 구현해야 하는 것은 아닙니다.

구현은 해당 객체가 RTCPeerConnection에 존재할 때, 아래의 type에 해당하는 통계를 생성하는 것을 MUST 지원해야 하며, 해당 객체에 대해 유효할 때 나열된 필드들과 RTCStats 사전에 정의된 일반 필드를 포함해야 합니다:

RTCStatsType 사전 필드
"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 (sender에 연결된 오디오 트랙의 경우)
RTCVideoSourceStats width, height, framesPerSecond (sender에 연결된 비디오 트랙의 경우)
"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

구현은 [WEBRTC-STATS]에 정의된 다른 모든 통계를 생성하는 것을 MAY 지원할 수 있으며, 문서화되지 않은 통계를 MAY 생성할 수도 있습니다.

8.7 GetStats 예제

사용자가 나쁜 소리를 경험하고 있고 애플리케이션이 그 원인이 패킷 손실인지 확인하려는 경우를 생각해 봅시다. 다음의 예제 코드를 사용할 수 있습니다:

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. 네트워크 사용을 위한 미디어 스트림 API 확장

9.1 소개

[GETUSERMEDIA] 명세에서 정의된 MediaStreamTrack 인터페이스는 일반적으로 오디오 또는 비디오 데이터의 스트림을 나타냅니다. 하나 이상의 MediaStreamTrackMediaStream에 모일 수 있습니다(엄밀히 말하면, [GETUSERMEDIA]에서 정의된 MediaStream은 0개 이상의 MediaStreamTrack 객체를 포함할 수 있습니다).

MediaStreamTrack은 미디어 흐름을 표현하도록 확장될 수 있으며, 이 흐름은 원격 피어로부터 오거나(예: 수신) 원격 피어로 전송될 수 있습니다(예: 발신, 단지 로컬 카메라만이 아님). 이 기능을 MediaStreamTrack 객체에서 가능하게 하는 데 필요한 확장들은 이 섹션에서 설명합니다. 피어에게 미디어가 어떻게 전송되는지는 [RFC8834], [RFC7874] 및 [RFC8835]에 설명되어 있습니다.

다른 피어로 전송된 하나의 MediaStreamTrack은 수신자에게 단 하나의 MediaStreamTrack으로 보입니다. 피어는 이 명세를 지원하는 사용자 에이전트로 정의됩니다. 또한 송신 측 애플리케이션은 해당 MediaStreamTrack이 어느 MediaStream 객체(들)의 구성원인지 표시할 수 있습니다. 수신 측의 해당 MediaStream 객체(들)는 (아직 존재하지 않는 경우) 생성되고 그에 따라 채워집니다.

이 문서의 앞부분에서도 설명했듯이, RTCRtpSenderRTCRtpReceiver 객체는 애플리케이션이 MediaStreamTrack의 전송과 수신을 보다 세밀하게 제어하는 데 사용할 수 있습니다.

채널은 Media Capture and Streams 명세에서 고려되는 가장 작은 단위입니다. 채널은 예를 들어 RTP 페이로드 타입처럼 전송을 위해 함께 인코딩되도록 의도됩니다. 코덱이 공동으로 인코딩해야 하는 모든 채널은 같은 MediaStreamTrack에 있어야 MUST 하며, 코덱은 트랙의 모든 채널을 인코딩하거나 폐기할 수 있어야 SHOULD 합니다.

주어진 MediaStreamTrack에 대한 입력과 출력의 개념은, 네트워크를 통해 전송되는 MediaStreamTrack 객체에도 동일하게 적용됩니다. 이 문서에서 이전에 설명한 바와 같이 RTCPeerConnection 객체에 의해 생성된 MediaStreamTrack은 원격 피어로부터 수신된 데이터를 입력으로 받습니다. 마찬가지로, 예를 들어 [GETUSERMEDIA]를 통해 카메라에서 나온 로컬 소스의 MediaStreamTrack은, 해당 객체가 RTCPeerConnection 객체와 함께 사용되는 경우 원격 피어로 전송되는 출력을 가집니다.

[GETUSERMEDIA]에 설명된 대로 MediaStreamMediaStreamTrack 객체를 복제하는 개념도 여기에서 적용됩니다. 이 기능은 예를 들어 화상 회의 시나리오에서 사용자의 카메라와 마이크로폰에서 나온 로컬 비디오를 로컬 모니터에 표시하되, 오디오만 원격 피어에 전송(예: 사용자가 "비디오 음소거" 기능을 사용하는 경우)하는 데 사용할 수 있습니다. 서로 다른 MediaStreamTrack 객체를 새로운 MediaStream 객체로 결합하는 것은 특정 상황에서 유용합니다.

참고

이 문서에서는, RTCPeerConnection과 함께 사용할 때 관련되는 다음 객체들의 측면만을 명세합니다. MediaStreamMediaStreamTrack 사용에 관한 일반 정보는 [GETUSERMEDIA] 문서의 원래 정의를 참조하십시오.

9.2 MediaStream

9.2.1 id

id 속성은 MediaStream에서 지정되며, 이 스트림에 고유한 ID를 반환하여, 원격 단의 RTCPeerConnection API에서 스트림을 식별할 수 있게 합니다.

원격 피어로부터 얻은 스트림을 나타내기 위해 MediaStream이 생성될 때, id 속성은 원격 소스가 제공한 정보로부터 초기화됩니다.

참고

id는 스트림의 소스에 대해 MediaStream 객체에 고유하지만, 이는 중복이 발생하지 않는다는 의미는 아닙니다. 예를 들어, 로컬에서 생성된 스트림의 트랙이 한 사용자 에이전트에서 원격 피어로 RTCPeerConnection을 사용해 전송되고 동일한 방식으로 다시 원래의 사용자 에이전트로 돌아오는 경우, 원래의 사용자 에이전트에는 동일한 id를 가진 여러 스트림(로컬에서 생성된 것과 원격 피어로부터 수신된 것)이 존재하게 됩니다.

9.3 MediaStreamTrack

비로컬 미디어 소스(각 RTCRtpReceiver에 연관된 RTP 소스의 경우와 같음)인 경우, MediaStreamTrack 객체가 자신의 MediaStream을 참조하는 방식은 항상 강한 참조입니다.

RTCRtpReceiver가, 해당 MediaStreamTrack이 음소거(muted)되어 있으나 종료(end)되지 않은 RTP 소스에서 데이터를 수신하고, 또한 [[Receptive]] 슬롯이 RTCRtpTransceiver 객체에서 RTCRtpReceiver가 구성원일 때 true이면, 해당하는 MediaStreamTrack의 음소거 상태를 false설정하는 작업을 큐에 넣어야 MUST 합니다.

RTCRtpReceiver가 수신하는 RTP 소스 미디어 스트림의 SSRC 중 하나가 BYE 수신 또는 타임아웃으로 제거되면, 해당하는 MediaStreamTrack의 음소거 상태를 true설정하는 작업을 큐에 넣어야 MUST 합니다. 또한 setRemoteDescription 또한 음소거 상태 설정을 유발하여, track의 값을 true로 만들 수 있습니다.

add a track, remove a trackset a track's muted state 절차는 [GETUSERMEDIA]에 명세되어 있습니다.

RTCRtpReceiver receiver가 생성한 MediaStreamTrack 트랙이 [GETUSERMEDIA]의 ended 상태가 되었을 때 (예: receiver.track.stop 호출과 같은 경우), 사용자 에이전트는 예컨대 receiver의 디코더를 끄는 방식으로 수신 스트림에 할당된 자원을 해제하기로 선택할 수 MAY 있습니다.

9.3.1 MediaTrackSupportedConstraints, MediaTrackCapabilities, MediaTrackConstraints 및 MediaTrackSettings

제약(constraints)과 제약 가능한 프로퍼티(constrainable properties)의 개념(예: MediaTrackConstraints (MediaStreamTrack.getConstraints(), MediaStreamTrack.applyConstraints()) 및 MediaTrackSettings (MediaStreamTrack.getSettings()))은 [GETUSERMEDIA]에 개략적으로 설명되어 있습니다. 그러나 피어 연결에서 소스가 되는 트랙의 제약 가능한 프로퍼티는 getUserMedia()에 의해 소스가 되는 트랙과는 다르며; 원격 소스에서 소스가 되는 MediaStreamTrack에 적용 가능한 제약과 설정은 여기에서 정의합니다. 원격 트랙의 설정은 최신으로 수신된 프레임을 나타냅니다.

원격 트랙에 대해 여기에서 정의된 제약에 대해서는, MediaStreamTrack.getCapabilities()는 항상 빈 집합을 반환해야 MUST 하며, MediaStreamTrack.applyConstraints()는 항상 OverconstrainedError로 거부(reject)되어야 MUST 합니다.

다음의 제약 가능한 프로퍼티는, 원격 소스에서 소스가 되는 비디오 MediaStreamTrack에 적용되도록 정의됩니다:

속성 이름 비고
width ConstrainULong 설정으로서, 이는 최근에 수신된 프레임의 너비(픽셀 단위)입니다.
height ConstrainULong 설정으로서, 이는 최근에 수신된 프레임의 높이(픽셀 단위)입니다.
frameRate ConstrainDouble 설정으로서, 이는 최근에 수신된 프레임을 기반으로 한 프레임 속도 추정치입니다.
aspectRatio ConstrainDouble 설정으로서, 이는 최신 프레임의 종횡비입니다. 픽셀 단위 너비를 픽셀 단위 높이로 나눈 값이며, 소수점 아래 열째 자리까지 반올림된 배정도(double)입니다.

이 문서는, 원격 소스에서 소스가 되는 오디오 MediaStreamTrack에 적용할 제약 가능한 프로퍼티를 정의하지 않습니다.

10. 예제와 호출 흐름

이 섹션은 비규범적입니다.

10.1 간단한 피어-투-피어 예제

두 피어가 서로 연결을 설정하기로 결정하면, 양쪽 모두 다음 단계를 거칩니다. STUN/TURN 서버 구성은 공개 IP 주소를 얻거나 NAT 트래버설을 설정하는 데 사용할 수 있는 서버를 설명합니다. 또한 신호(시그널링) 채널에 대한 데이터를 서로에게 보내야 하며, 이는 처음에 통신하기로 합의할 때 사용했던 동일한 대역외(out-of-band) 메커니즘을 사용합니다.

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 웜업이 포함된 고급 피어-투-피어 예제

두 피어가 서로 연결을 설정하기로 결정하고, ICE, DTLS, 미디어 연결을 즉시 미디어를 송수신할 수 있도록 “웜업” 상태로 만들고자 할 때, 양쪽 모두 다음 단계를 거칩니다.

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 시뮬캐스트 예제

클라이언트가 서버로 다중 RTP 인코딩(시뮬캐스트)을 전송하려고 합니다.

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 피어-투-피어 데이터 예제

이 예제는 RTCDataChannel 객체를 만드는 방법과, 채널을 다른 피어에 연결하기 위해 필요한 오퍼/앤서 교환을 수행하는 방법을 보여줍니다. RTCDataChannel은 사용자 입력을 위한 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 브라우저 간 호출 흐름

이는 두 브라우저 사이의 가능한 호출 흐름의 한 예를 보여줍니다. 로컬 미디어에 접근하는 절차나 발생하는 모든 콜백을 모두 보여주지는 않으며, 핵심 이벤트와 메시지만 보여주도록 간소화합니다.

두 브라우저 간의 호출 흐름을 자세히 나타내는 메시지 시퀀스 차트

10.6 DTMF 예제

예제는 senderRTCRtpSender라고 가정합니다.

톤당 500ms 지속 시간으로 DTMF 신호 "1234"를 전송하기:

if (sender.dtmf.canInsertDTMF) {
  const duration = 500;
  sender.dtmf.insertDTMF('1234', duration);
} else {
  console.log('DTMF function not available');
}

DTMF 신호 "123"을 전송하고, "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');
  }
}

DTMF 신호 "1234"를 보내고, 톤이 재생되는 동안 lightKey(key)를 사용하여 활성 키에 불을 켜기 (lightKey("")가 모든 키의 불을 끈다고 가정):

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');
}

톤 버퍼에 이어붙이는 것은 언제나 안전합니다. 이 예제는 재생이 시작되기 전과 재생 중 모두에서 이어붙입니다.

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');
}

1초 길이의 "1" 톤에 이어 2초 길이의 "2" 톤을 전송하기:

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) 예제

완전 협상은 비대칭적인 협상 작업을 애플리케이션의 나머지 부분으로부터 분리해 투명하게 관리하는 권장 패턴입니다. 이 패턴은 한쪽이 항상 오퍼러(offerer)가 되는 방식보다 유리한데, 애플리케이션이 글레어(glare) 위험 없이 두 피어 연결 객체를 동시에 다룰 수 있게 해주기 때문입니다(“stable” 상태 밖에서 오퍼가 도착하는 상황). 애플리케이션의 나머지 부분은 시그널링 상태 경합을 걱정하지 않고 모든 수정 메서드와 속성을 사용할 수 있습니다.

이 방식은 두 피어에 서로 다른 역할을 지정하고, 그 사이의 시그널링 충돌을 해결하는 동작을 정의합니다:

  1. 정중한(peolite) 피어는 들어오는 오퍼와의 충돌을 피하기 위해 롤백을 사용합니다.

  2. 무례한(impolite) 피어는 자신의 오퍼와 충돌하는 들어오는 오퍼를 무시합니다.

이 둘은 함께, 교착 상태 없이 애플리케이션의 나머지 부분을 위한 시그널링을 관리합니다. 예제는 지정된 역할을 나타내는 불리언 변수 polite가 있다고 가정합니다:

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);
  }
}

이는 타이밍에 민감하며, 의도적으로 인자 없이 호출하는 setLocalDescription와, 암묵적 롤백을 포함한 setRemoteDescription 버전을 사용하여 다른 시그널링 메시지 처리와의 경합을 피합니다.

ignoreOffer 변수가 필요한 이유는, 무례한(impolite) 측의 RTCPeerConnection 객체는 무시된 오퍼들에 대해 통보받지 않기 때문입니다. 따라서 그러한 오퍼에 속한 들어오는 후보(candidates)에서 발생하는 오류를 억제해야 합니다.

11. 오류 처리

일부 작업은 RTCError를 던지거나 발생시킵니다. 이는 추가적인 WebRTC 전용 정보를 담는 DOMException의 확장입니다.

11.1 RTCError 인터페이스

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 생성자

constructor()

다음 단계를 실행합니다:

  1. init을 생성자의 첫 번째 인수로 둡니다.

  2. message를 생성자의 두 번째 인수로 둡니다.

  3. e를 새로운 RTCError 객체로 둡니다.

  4. eDOMException 생성자를 호출하되, message 인수는 message로, name 인수는 "OperationError"로 설정합니다.

    참고

    이 이름은 레거시 코드로의 매핑이 없으므로 e.code는 0을 반환합니다.

  5. init에 해당 속성이 존재하면 그 값으로, 존재하지 않으면 nulle의 모든 RTCError 속성을 설정합니다.

  6. e를 반환합니다.

11.1.2 속성

errorDetail of type RTCErrorDetailType, readonly

발생한 오류 유형에 대한 WebRTC 전용 오류 코드입니다.

sdpLineNumber of type long, readonly, nullable

errorDetail 이 "sdp-syntax-error" 인 경우, 오류가 감지된 행 번호입니다(첫 번째 행의 번호는 1).

sctpCauseCode of type long, readonly, nullable

errorDetail이 "sctp-failure"인 경우, 실패한 SCTP 협상의 SCTP 원인 코드입니다.

receivedAlert of type unsigned long, readonly, nullable

errorDetail이 "dtls-failure"이고 치명적인 DTLS 알림을 수신했다면, 수신된 DTLS 알림의 값입니다.

sentAlert of type unsigned long, readonly, nullable

errorDetail이 "dtls-failure"이고 치명적인 DTLS 알림을 전송했다면, 전송된 DTLS 알림의 값입니다.

(위험에 처한 기능) 이슈 1

RTCError에 정의된 모든 속성(errorDetail, sdpLineNumber, sctpCauseCode, receivedAlert, sentAlert)은 구현 부족으로 인해 위험으로 표시되어 있습니다. 이는 DOMException에서 상속된 속성은 포함하지 않습니다.

11.1.3 RTCErrorInit 사전

WebIDLdictionary RTCErrorInit {
  required RTCErrorDetailType errorDetail;
  long sdpLineNumber;
  long sctpCauseCode;
  unsigned long receivedAlert;
  unsigned long sentAlert;
};

errorDetail, sdpLineNumber, sctpCauseCode, receivedAlertsentAlert 멤버는 RTCErrorInit의 동명 속성과 RTCError의 동명 속성 정의가 동일합니다.

11.2 RTCErrorDetailType 열거형

WebIDLenum RTCErrorDetailType {
  "data-channel-failure",
  "dtls-failure",
  "fingerprint-failure",
  "sctp-failure",
  "sdp-syntax-error",
  "hardware-encoder-not-available",
  "hardware-encoder-error"
};
RTCErrorDetailType 열거형 설명
열거형 값 설명
data-channel-failure 데이터 채널이 실패했습니다.
dtls-failure DTLS 협상이 실패했거나 연결이 치명적인 오류로 종료되었습니다. message에는 오류의 성격과 관련된 정보가 들어 있습니다. 치명적인 DTLS 알림을 수신한 경우, receivedAlert 속성은 수신된 DTLS 알림의 값으로 설정됩니다. 치명적인 DTLS 알림을 전송한 경우, sentAlert 속성은 전송된 DTLS 알림의 값으로 설정됩니다.
fingerprint-failure RTCDtlsTransport의 원격 인증서가 SDP에 제공된 어떤 지문과도 일치하지 않았습니다. 원격 피어가 제공된 지문으로 로컬 인증서를 일치시킬 수 없는 경우에는 이 오류가 생성되지 않습니다. 대신 원격 피어로부터 "bad_certificate"(42) DTLS 알림을 수신할 수 있으며, 이는 "dtls-failure"로 이어질 수 있습니다.
sctp-failure SCTP 협상이 실패했거나 연결이 치명적인 오류로 종료되었습니다. sctpCauseCode 속성은 SCTP 원인 코드로 설정됩니다.
sdp-syntax-error SDP 문법이 유효하지 않습니다. sdpLineNumber 속성은 문법 오류가 감지된 SDP의 행 번호로 설정됩니다.
hardware-encoder-not-available 요청된 작업에 필요한 하드웨어 인코더 리소스를 사용할 수 없습니다.
hardware-encoder-error 하드웨어 인코더가 제공된 매개변수를 지원하지 않습니다.

11.3 RTCErrorEvent 인터페이스

RTCErrorEvent 인터페이스는 RTCError가 이벤트로 발생하는 경우를 위해 정의됩니다:

WebIDL[Exposed=Window]
interface RTCErrorEvent : Event {
  constructor(DOMString type, RTCErrorEventInit eventInitDict);
  [SameObject] readonly attribute RTCError error;
};

11.3.1 생성자

constructor()

새로운 RTCErrorEvent를 생성합니다.

11.3.2 속성

error of type RTCError, readonly

이벤트를 트리거한 오류를 설명하는 RTCError입니다.

11.4 RTCErrorEventInit 사전

WebIDL          dictionary RTCErrorEventInit : EventInit {
  required RTCError error;
};

11.4.1 사전 RTCErrorEventInit 멤버

error of type RTCError

이벤트와 관련된 오류(있는 경우)를 설명하는 RTCError입니다.

12. 이벤트 요약

이 섹션은 비규범적입니다.

다음 이벤트는 RTCDataChannel 객체에서 발생합니다:

이벤트 이름 인터페이스 발생 조건
open Event RTCDataChannel 객체의 기저 데이터 전송이 설정(또는 재설정)되었을 때.
message MessageEvent [html] 메시지를 성공적으로 수신했을 때.
bufferedamountlow Event RTCDataChannel 객체의 bufferedAmount가 자신의 bufferedAmountLowThreshold 초과에서 그 값보다 작거나 같은 상태로 감소했을 때(bufferedAmountLowThreshold 이하가 되었을 때).
error RTCErrorEvent 데이터 채널에서 오류가 발생했을 때.
closing Event RTCDataChannel 객체가 "closing" 상태로 전이했을 때.
close Event RTCDataChannel 객체의 기저 데이터 전송이 종료되었을 때.

다음 이벤트는 RTCPeerConnection 객체에서 발생합니다:

이벤트 이름 인터페이스 발생 조건
track RTCTrackEvent 특정 RTCRtpReceiver에 대해 새로운 수신 미디어가 협상되었고, 해당 수신기의 track이 연관된 원격 MediaStream들에 추가되었을 때.
negotiationneeded Event 브라우저가 세션 협상이 필요함을 애플리케이션에 알리고자 할 때(예: createOffer 호출 후 setLocalDescription).
signalingstatechange Event 연결의 [[SignalingState]]가 변경되었을 때. 이 상태 변화는 setLocalDescription 또는 setRemoteDescription 호출의 결과입니다.
iceconnectionstatechange Event RTCPeerConnection[[IceConnectionState]]가 변경되었을 때.
icegatheringstatechange Event RTCPeerConnection[[IceGatheringState]]가 변경되었을 때.
icecandidate RTCPeerConnectionIceEvent 새로운 RTCIceCandidate가 스크립트에서 사용 가능해졌을 때.
connectionstatechange Event RTCPeerConnectionconnectionState가 변경되었을 때.
icecandidateerror RTCPeerConnectionIceErrorEvent ICE 후보를 수집하는 동안 오류가 발생했을 때.
datachannel RTCDataChannelEvent 상대 피어가 채널을 생성한 것에 응답하여 새로운 RTCDataChannel이 스크립트로 디스패치되었을 때.

다음 이벤트는 RTCDTMFSender 객체에서 발생합니다:

이벤트 이름 인터페이스 발생 조건
tonechange RTCDTMFToneChangeEvent RTCDTMFSender 객체가 톤 재생을 막 시작했거나(이는 tone 속성으로 반환됨), 또는 toneBuffer의 톤 재생을 막 끝냈을 때(tone 속성에 빈 값으로 반환됨).

다음 이벤트는 RTCIceTransport 객체에서 발생합니다:

이벤트 이름 인터페이스 발생 조건
statechange Event RTCIceTransport의 상태가 변경되었을 때.
gatheringstatechange Event RTCIceTransport의 후보 수집 상태가 변경되었을 때.
selectedcandidatepairchange Event RTCIceTransport의 선택된 후보 쌍이 변경되었을 때.

다음 이벤트는 RTCDtlsTransport 객체에서 발생합니다:

이벤트 이름 인터페이스 발생 조건
statechange Event RTCDtlsTransport의 상태가 변경되었을 때.
error RTCErrorEvent RTCDtlsTransport에서 오류가 발생했을 때 ("dtls-failure" 또는 "fingerprint-failure" 중 하나).

다음 이벤트는 RTCSctpTransport 객체에서 발생합니다:

이벤트 이름 인터페이스 발생 조건
statechange Event RTCSctpTransport의 상태가 변경되었을 때.

13. 개인정보 및 보안 고려사항

이 섹션은 비규범적입니다.

이 석션은 비규범적이며, 새로운 동작을 규정하지 않고 명세의 다른 부분에 이미 존재하는 정보를 요약합니다. WebRTC에서 사용되는 일반적인 API 및 프로토콜 집합에 대한 전반적인 보안 고려사항은 [RFC8827]에 설명되어 있습니다.

13.1 동일 출처 정책에 대한 영향

이 문서는 웹 플랫폼을 확장하여 브라우저와 다른 장치(다른 브라우저 포함) 간에 실시간, 직접 통신을 설정하는 능력을 제공합니다.

이는 서로 다른 브라우저에서 실행 중인 애플리케이션 간에, 또는 같은 브라우저에서 실행 중인 애플리케이션과 브라우저가 아닌 무언가 사이에서도 데이터와 미디어를 공유할 수 있음을 의미합니다. 이는 서로 다른 출처를 가진 엔터티 간 데이터 전송을 막는 웹 모델의 통상적 장벽을 확장하는 것입니다.

WebRTC 명세는 통신을 위한 사용자 프롬프트나 크롬 표시기를 제공하지 않습니다; 웹 페이지가 미디어 접근을 허용받으면 해당 미디어를 다른 엔터티와 자유롭게 공유할 수 있다고 가정합니다. 따라서 피어 투 피어 데이터 교환은 WebRTC 데이터 채널을 통해 사용자의 명시적 동의나 관여 없이도 일어날 수 있으며, 이는 서버 중개(예: Web Sockets)를 통한 교환이 사용자 관여 없이 발생할 수 있는 것과 유사합니다.

13.2 IP 주소 노출

WebRTC가 없어도 웹 애플리케이션을 제공하는 웹 서버는 애플리케이션이 전달되는 공용 IP 주소를 알 수 있습니다. 통신 설정은 애플리케이션에 브라우저의 네트워크 컨텍스트에 관한 추가 정보를 노출하며, WebRTC 사용을 위해 브라우저에서 사용할 수 있는 (사설일 수도 있는) IP 주소 집합을 포함할 수 있습니다. 이 정보 중 일부는 통신 세션 수립을 가능하게 하기 위해 상대방에게 전달되어야 합니다.

IP 주소를 노출하면 위치 및 접속 수단이 새어 나갈 수 있으며, 이는 민감할 수 있습니다. 네트워크 환경에 따라 지문 채집 표면을 증가시키고 사용자가 쉽게 지울 수 없는 지속적인 교차 출처 상태를 생성할 수도 있습니다.

연결은 통신에 제안된 IP 주소를 항상 상대방에게 노출합니다. 애플리케이션은 RTCIceTransportPolicy 사전에 노출된 설정을 사용하여 특정 주소를 사용하지 않도록 선택하고, 참가자 간 직접 연결 대신 릴레이(예: TURN 서버)를 사용함으로써 이러한 노출을 제한할 수 있습니다. 일반적으로 TURN 서버의 IP 주소는 민감한 정보가 아니라고 가정합니다. 이러한 선택은 예를 들어 사용자가 상대방과 미디어 연결을 시작하는 데 동의했는지 여부에 따라 애플리케이션에서 결정할 수 있습니다.

애플리케이션 자체에 대한 IP 주소 노출을 완화하려면 사용할 수 있는 IP 주소를 제한해야 하며, 이는 엔드포인트 간 최단 경로로 통신하는 능력에 영향을 줍니다. 브라우저는 사용자가 원하는 보안 태세에 따라 애플리케이션에 제공할 IP 주소를 결정할 수 있도록 적절한 제어 기능을 제공하는 것이 권장됩니다. 어떤 주소를 노출할지는 로컬 정책에 의해 제어됩니다 (자세한 내용은 [RFC8828] 참고).

13.3 로컬 네트워크에 대한 영향

브라우저는 신뢰된 네트워크 환경(방화벽 내부)에서 실행되는 능동적 플랫폼이므로, 브라우저가 로컬 네트워크의 다른 요소에 야기할 수 있는 피해를 제한하는 것이 중요하며, 신뢰할 수 없는 참여자에 의한 데이터 도청, 조작 및 수정으로부터 데이터를 보호하는 것도 중요합니다.

완화책은 다음과 같습니다:

이러한 조치는 관련 IETF 문서에 규정되어 있습니다.

13.4 통신의 기밀성

네트워크를 관찰할 수 있는 공격자에게 통신이 이루어지고 있다는 사실은 숨길 수 없으므로, 이는 공용 정보로 간주해야 합니다.

통신 인증서는 미래의 필요에 대비해 postMessage(message, options)를 사용하여 불투명하게 공유될 수 있습니다. 사용자 에이전트는 이 객체들이 보유한 핸들이 가리키는 개인 키 재료를, RTCCertificate 객체에 접근할 수 있는 프로세스로부터 격리하여 메모리 공격 표면을 줄일 것을 강력히 권장합니다.

13.5 WebRTC가 노출하는 지속적 정보

위에서 설명했듯이, WebRTC API가 노출하는 IP 주소 목록은 지속적인 교차 출처 상태로 사용될 수 있습니다.

IP 주소를 넘어서, WebRTC API는 RTCRtpSender.getCapabilitiesRTCRtpReceiver.getCapabilities 메서드를 통해 기반 미디어 시스템에 관한 정보를 노출합니다. 여기에는 시스템이 생성·소비할 수 있는 코덱에 대한 상세하고 순서화된 정보가 포함됩니다. 이 정보의 하위 집합은 세션 협상 중에 생성·노출·전송되는 SDP 세션 기술에 반영될 가능성이 큽니다. 이러한 정보는 대부분의 경우 시간과 출처 전반에 걸쳐 지속되며, 특정 장치의 지문 채집 표면을 증가시킵니다.

DTLS 연결을 설정할 때, WebRTC API는 애플리케이션이 보존할 수 있는(예: IndexedDB에) 인증서를 생성할 수 있습니다. 이 인증서는 출처 간에 공유되지 않으며, 해당 출처의 영구 저장소가 삭제되면 함께 삭제됩니다.

13.6 원격 엔드포인트로부터 SDP 설정

setRemoteDescription은 예외를 던져 잘못되거나 무효인 SDP로부터 보호하지만, 애플리케이션에 예상치 못한 SDP에 대해서는 보호를 시도하지 않습니다. 원격 설명을 설정하면 상당한 리소스 할당(이미지 버퍼 및 네트워크 포트 포함), 미디어의 흐름 시작(개인정보 보호 및 대역폭 영향 가능) 등 다양한 일이 발생할 수 있습니다. 악의적인 SDP에 대한 방어를 하지 않는 애플리케이션은 리소스 고갈, 의도치 않은 수신 미디어 허용, 또는 상대 엔드포인트가 송신을 협상하지 않는 경우 ontrack 같은 특정 이벤트가 발생하지 않는 등의 위험에 처할 수 있습니다. 애플리케이션은 악의적인 SDP에 대비해야 합니다.

14. 접근성 고려사항

이 섹션은 비규범적입니다.

WebRTC 1.0 명세는 실시간 오디오, 비디오 및 데이터 교환을 설정하는 데 필요한 (IETF 내에서 정의된) 프로토콜을 제어하기 위한 API를 노출합니다.

TDD/TTY(청각장애·언어장애용 통신장치)는 청각 또는 언어에 장애가 있는 개인(등)이 전화 회선을 통해 통신할 수 있게 해줍니다. 실시간 텍스트(Real-Time Text)는 [RFC4103]에서 정의된 바와 같이 RTP에 캡슐화된 T.140을 활용하여 TDD/TTY 장치에서 IP 기반 통신으로의 전환을 가능하게 하며, 공공 안전 접근 지점(PSAP)과의 긴급 통신도 포함합니다.

실시간 텍스트는 거의 실시간으로 데이터를 송수신하는 능력을 필요로 하므로, WebRTC 1.0 데이터 채널 API를 통해 가장 잘 지원될 수 있습니다. IETF에서 정의한 바에 따르면, 데이터 채널 프로토콜은 SCTP/DTLS/UDP 프로토콜 스택을 사용하며, 신뢰 가능한 데이터 채널과 신뢰 불가능한 데이터 채널을 모두 지원합니다. IETF는 SRTP 키 관리에 의존하고 신뢰 불가능한 통신에 초점을 맞춘 RTP 데이터 채널 제안보다 SCTP/DTLS/UDP를 표준으로 채택했습니다.

IETF가 WebRTC 프로토콜 모음의 일부로 RTP 데이터 채널과는 다른 접근 방식을 선택했기 때문에, 이 문서를 발행하는 시점에는 IETF에서 정의되고 미국(FCC) 규정에 구현된 실시간 텍스트를 WebRTC API가 직접 지원하는 표준화된 방법이 없습니다. WebRTC 워킹 그룹은 이 영역에서 개발 중인 IETF 프로토콜을 브라우저 API에 직접 노출할 필요가 있는지 평가할 것이며, 이 잠재적 격차에 대해 관련 사용자 커뮤니티의 의견을 구하고 있습니다.

IETF MMUSIC 워킹 그룹에서는, 게이트웨이가 SCTP 데이터 채널 프로토콜과 RFC 4103 실시간 텍스트 간 변환을 수행할 수 있도록 WebRTC 데이터 채널을 통한 실시간 텍스트 전송을 가능하게 하는 작업이 진행 중입니다. 이 작업이 완료되면, 게이트웨이를 통해서든 다른 방식을 통해서든 WebRTC 사용자 에이전트(브라우저 포함)에 실시간 텍스트를 통합하기 위한 통합적이고 상호운용 가능한 접근 방식을 가능하게 할 것으로 예상됩니다.

이 문서를 발행하는 시점에는, WebRTC 클라이언트에서 효과적인 RTT 지원을 가능하게 하는 게이트웨이는 예를 들어 사용자 정의 WebRTC 데이터 채널을 통해 개발할 수 있습니다. 이는 향후 IETF 프로토콜(예: SCTP 데이터 채널 프로토콜 및 RFC 4103 실시간 텍스트)을 통해 표준화된 게이트웨이가 제공될 때까지는 충분하다고 판단됩니다. 이는 W3C 관련 작업과 함께 IETF에서 정의되어, 국제적으로 효과적이고 일관된 RTT 지원 표준화를 달성해야 합니다.

A. 후보 개정안

2021년 1월 W3C 권고안으로 발표된 이후, 다음 후보 개정안들이 이 문서에 통합되었습니다.

B. 감사의 글

편집자들은 워킹 그룹 의장과 팀 연락 담당자 Harald Alvestrand, Stefan Håkansson, Erik Lagerway, Dominique Hazaël-Massieux에게 지원에 감사드립니다. 이 명세의 상당 부분은 Martin Thomson, Harald Alvestrand, Justin Uberti, Eric Rescorla, Peter Thatcher, Jan-Ivar Bruaroey, Peter Saint-Andre 등 많은 분들에 의해 기여되었습니다. Dan Burnett은 이 명세의 개발 과정에서 Voxeo와 Aspect로부터 받은 중요한 지원에 대해 감사의 뜻을 표합니다.

RTCRtpSenderRTCRtpReceiver 객체는 처음에 W3C ORTC CG에서 기술되었으며, 이 명세에 맞게 적용되었습니다.

C. 참고문헌

후보 수정 46:RFC8829 참조를 RFC9429로 교체 (PR #2966)

B.1 규범적 참고문헌

C.1 규범적 참고문헌

[DOM]
DOM 표준. Anne van Kesteren. WHATWG. 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT-6.0]
ECMA-262 6판, ECMAScript 2015 언어 명세. Allen Wirfs-Brock. Ecma International. 2015년 6월. 표준. URL: http://www.ecma-international.org/ecma-262/6.0/index.html
[Fetch]
Fetch 표준. Anne van Kesteren. WHATWG. 현행 표준. URL: https://fetch.spec.whatwg.org/
[FILEAPI]
File API. Marijn Kruisselbrink. W3C. 2024년 12월 4일. W3C 작업 초안. URL: https://www.w3.org/TR/FileAPI/
[FIPS-180-4]
FIPS PUB 180-4: Secure Hash Standard (SHS). 미국 상무부/국립표준기술연구소(NIST). 2015년 8월. 국가 표준. URL: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
[GETUSERMEDIA]
미디어 캡처 및 스트림. Cullen Jennings; Bernard Aboba; Jan-Ivar Bruaroey; Henrik Boström; youenn fablet. W3C. 2024년 12월 19일. CRD. URL: https://www.w3.org/TR/mediacapture-streams/
[hr-time]
고해상도 시간. Yoav Weiss. W3C. 2024년 11월 7일. W3C 작업 초안. URL: https://www.w3.org/TR/hr-time-3/
[HTML]
HTML 표준. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[IANA-HASH-FUNCTION]
해시 함수 텍스트 이름. IANA. URL: https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml
[IANA-RTP-2]
RTP 페이로드 형식 미디어 타입. IANA. URL: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-2
[INFRA]
Infra 표준. Anne van Kesteren; Domenic Denicola. WHATWG. 현행 표준. URL: https://infra.spec.whatwg.org/
[RFC2119]
RFC에서 요구 사항 수준을 표시하기 위한 핵심 단어. S. Bradner. IETF. 1997년 3월. 현행 최선 관행. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC3550]
RTP: 실시간 애플리케이션을 위한 전송 프로토콜. H. Schulzrinne; S. Casner; R. Frederick; V. Jacobson. IETF. 2003년 7월. 인터넷 표준. URL: https://www.rfc-editor.org/rfc/rfc3550
[RFC3890]
세션 기술 프로토콜(SDP)에서의 전송 독립적 대역폭 지정자. M. Westerlund. IETF. 2004년 9월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc3890
[RFC4566]
SDP: 세션 기술 프로토콜. M. Handley; V. Jacobson; C. Perkins. IETF. 2006년 7월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc4566
[RFC4572]
세션 기술 프로토콜(SDP)에서 TLS 프로토콜을 통한 연결 지향 미디어 전송. J. Lennox. IETF. 2006년 7월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc4572
[RFC5245]
상호 연결성 설정(ICE): 오퍼/응답 프로토콜을 위한 NAT 트래버설 프로토콜. J. Rosenberg. IETF. 2010년 4월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc5245
[RFC5246]
전송 계층 보안(TLS) 프로토콜 버전 1.2. T. Dierks; E. Rescorla. IETF. 2008년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc5246
[RFC5285]
RTP 헤더 확장에 대한 일반 메커니즘. D. Singer; H. Desineni. IETF. 2008년 7월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc5285
[RFC5389]
NAT(STUN) 세션 트래버설 유틸리티. J. Rosenberg; R. Mahy; P. Matthews; D. Wing. IETF. 2008년 10월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc5389
[RFC5506]
축소 크기 RTCP 지원: 기회와 결과. I. Johansson; M. Westerlund. IETF. 2009년 4월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc5506
[RFC5888]
세션 기술 프로토콜(SDP) 그룹화 프레임워크. G. Camarillo; H. Schulzrinne. IETF. 2010년 6월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc5888
[RFC6464]
클라이언트-믹서 오디오 레벨 표시를 위한 RTP 헤더 확장. J. Lennox, Ed.; E. Ivov; E. Marocco. IETF. 2011년 12월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6464
[RFC6465]
믹서-클라이언트 오디오 레벨 표시를 위한 RTP 헤더 확장. E. Ivov, Ed.; E. Marocco, Ed.; J. Lennox. IETF. 2011년 12월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6465
[RFC6544]
ICE를 이용한 TCP 후보. J. Rosenberg; A. Keranen; B. B. Lowekamp; A. B. Roach. IETF. 2012년 3월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6544
[RFC7064]
STUN 프로토콜용 URI 스킴. S. Nandakumar; G. Salgueiro; P. Jones; M. Petit-Huguenin. IETF. 2013년 11월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7064
[RFC7065]
TURN NAT 트래버설용 URI. M. Petit-Huguenin; S. Nandakumar; G. Salgueiro; P. Jones. IETF. 2013년 11월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7065
[RFC7656]
RTP 소스의 의미론 및 메커니즘 분류. J. Lennox; K. Gross; S. Nandakumar; G. Salgueiro; B. Burman, Ed. IETF. 2015년 11월. 정보성. URL: https://www.rfc-editor.org/rfc/rfc7656
[RFC7675]
합의 신선도 유지를 위한 NAT(STUN) 세션 트래버설 유틸리티 사용. M. Perumal; D. Wing; R. Ravindranath; T. Reddy; M. Thomson. IETF. 2015년 10월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7675
[RFC7874]
WebRTC 오디오 코덱 및 처리 요구사항. JM. Valin; C. Bran. IETF. 2016년 5월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7874
[RFC8174]
RFC 2119 키워드에서 대소문자 모호성. B. Leiba. IETF. 2017년 5월. 현행 최선 관행. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8261]
DTLS 캡슐화된 SCTP 패킷. M. Tuexen; R. Stewart; R. Jesup; S. Loreto. IETF. 2017년 11월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8261
[RFC8445]
상호 연결성 설정(ICE): NAT 트래버설 프로토콜. A. Keranen; C. Holmberg; J. Rosenberg. IETF. 2018년 7월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8445
[RFC8656]
TURN: STUN 세션 트래버설을 위한 릴레이 확장. T. Reddy, Ed.; A. Johnston, Ed.; P. Matthews; J. Rosenberg. IETF. 2020년 2월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8656
[RFC8826]
WebRTC 보안 고려사항. E. Rescorla. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8826
[RFC8831]
WebRTC 데이터 채널. R. Jesup; S. Loreto; M. Tüxen. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8831
[RFC8832]
WebRTC 데이터 채널 설정 프로토콜. R. Jesup; S. Loreto; M. Tüxen. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8832
[RFC8834]
WebRTC에서 미디어 전송 및 RTP 사용. C. Perkins; M. Westerlund; J. Ott. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8834
[RFC8835]
WebRTC용 전송. H. Alvestrand. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8835
[RFC8838]
Trickle ICE: ICE 프로토콜을 위한 점진적 후보 제공. E. Ivov; J. Uberti; P. Saint-Andre. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8838
[RFC8841]
DTLS 전송을 통한 SCTP 스트림 제어 전송 프로토콜(SDP) 오퍼/응답 절차. C. Holmberg; R. Shpount; S. Loreto; G. Camarillo. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8841
[RFC8843]
SDP를 이용한 미디어 멀티플렉싱 협상. C. Holmberg; H. Alvestrand; C. Jennings. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8843
[RFC8851]
RTP 페이로드 형식 제한. A.B. Roach, Ed. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8851
[RFC8853]
SDP 및 RTP 세션에서 시뮬캐스트 사용. B. Burman; M. Westerlund; S. Nandakumar; M. Zanaty. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8853
[RFC8863]
상호 연결성 설정: 연결 대기(ICE PAC). C. Holmberg; J. Uberti. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8863
[RFC9429]
JavaScript 세션 설정 프로토콜(JSEP). J. Uberti; C. Jennings; E. Rescorla, Ed. IETF. 2024년 4월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9429
[SDP]
SDP를 통한 오퍼/응답 모델. J. Rosenberg; H. Schulzrinne. IETF. 2002년 6월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc3264
[STUN-PARAMETERS]
STUN 오류 코드. IETF. IANA. 2011년 4월. IANA 파라미터 할당. URL: https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml#stun-parameters-6
[WebCryptoAPI]
Web Cryptography API. Mark Watson. W3C. 2017년 1월 26일. W3C 권고안. URL: https://www.w3.org/TR/WebCryptoAPI/
[WEBIDL]
Web IDL 표준. Edgar Chen; Timothy Gu. WHATWG. 현행 표준. URL: https://webidl.spec.whatwg.org/
[WEBRTC-STATS]
WebRTC 통계 API 식별자. Harald Alvestrand; Varun Singh; Henrik Boström. W3C. 2025년 3월 6일. CRD. 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]
권고 X.690 — 정보 기술 — ASN.1 인코딩 규칙 — 기본 인코딩 규칙(BER), 정규 인코딩 규칙(CER), 구별 인코딩 규칙(DER) 명세. ITU. URL: https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf

C.2 비규범적 참고문헌

[API-DESIGN-PRINCIPLES]
웹 플랫폼 설계 원칙. Martin Thomson; Jeffrey Yasskin. W3C. 2025년 3월 6일. W3C 워킹 그룹 노트. URL: https://www.w3.org/TR/design-principles/
[INDEXEDDB]
인덱스드 데이터베이스 API. Nikunj Mehta; Jonas Sicking; Eliot Graff; Andrei Popescu; Jeremy Orlow; Joshua Bell. W3C. 2015년 1월 8일. W3C 권고안. URL: https://www.w3.org/TR/IndexedDB/
[RFC4103]
텍스트 대화를 위한 RTP 페이로드. G. Hellstrom; P. Jones. IETF. 2005년 6월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc4103
[RFC6236]
세션 기술 프로토콜(SDP)에서의 일반 이미지 속성 협상. I. Johansson; K. Jung. IETF. 2011년 5월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6236
[RFC7728]
RTP 스트림 일시정지 및 재개. B. Burman; A. Akram; R. Even; M. Westerlund. IETF. 2016년 2월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7728
[RFC8825]
브라우저 기반 애플리케이션을 위한 실시간 프로토콜 개요. H. Alvestrand. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8825
[RFC8827]
WebRTC 보안 아키텍처. E. Rescorla. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8827
[RFC8828]
WebRTC IP 주소 처리 요구사항. J. Uberti; G. Shieh. IETF. 2021년 1월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8828