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

W3C 권고안

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

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


초록

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

이 문서의 상태

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

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

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

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

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

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

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

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

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

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

1. 소개

이 절은 비규범적이다.

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

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

2. 적합성

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

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

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

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

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

3. 용어

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

참고

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

4. 피어 투 피어 연결

4.1 소개

이 절은 비규범적이다.

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

4.2 구성

4.2.1 RTCConfiguration 딕셔너리

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

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

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

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

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

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

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

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

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

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

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

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

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

참고

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

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

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

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

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

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

4.2.2 RTCIceServer 딕셔너리

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

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

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

username의 타입은 DOMString이다.

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

credential의 타입은 DOMString이다.

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

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

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

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

4.2.3 RTCIceTransportPolicy 열거형

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

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

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

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

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

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

4.2.4 RTCBundlePolicy 열거형

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

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

4.2.5 RTCRtcpMuxPolicy 열거형

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

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

4.2.6 제안/응답 옵션

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

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

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

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

참고

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

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

WebIDLdictionary RTCAnswerOptions : RTCOfferAnswerOptions {};

4.3 상태 정의

4.3.1 RTCSignalingState 열거형

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

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

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

4.3.2 RTCIceGatheringState 열거형

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

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

4.3.3 RTCPeerConnectionState 열거형

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

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

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

4.3.4 RTCIceConnectionState 열거형

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

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

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

4.4 RTCPeerConnection 인터페이스

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

4.4.1 동작

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

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

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

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

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

참고

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

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

  1. window를 document의 관련 전역 객체로 둔다.

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

4.4.1.1 생성자

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

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

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

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

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

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

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

    3. certificate를 저장한다.

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

  7. connection의 ICE 에이전트를 초기화한다.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  27. connection을 반환한다.

4.4.1.2 비동기 작업 연결

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. p를 반환한다.

4.4.1.3 연결 상태 업데이트

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

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

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

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

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

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

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

4.4.1.4 세션 설명 설정

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      4. remote가 true이고, connection의 RTCRtcpMuxPolicy가 require이며 설명에서 RTCP mux를 사용하지 않으면, 새로 생성된 InvalidAccessError로 p를 거부하고 이 단계를 중단한다.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      8. trackEventInits, muteTracks, addList, removeList 및 errorList를 빈 목록으로 둔다.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            참고

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            4. transceiver를 connection의 트랜시버 집합에 집합에 추가한다.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

          1. codecs를 transceiver.[[Sender]].[[SendCodecs]]로 한다.

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

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

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

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

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

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

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

      18. addList의 각 stream 및 track 쌍에 대해, stream에 track을 추가 한다.

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

      20. p를 undefined로 이행한다.

  5. p를 반환한다.

4.4.1.5 구성 설정

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

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

  2. oldConfig를 connection.[[Configuration]]으로 한다.

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

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

    2. index를 0으로 한다.

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

      1. configuration.certificates의 index 위치에 있는 값이 나타내는 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. iceServers를 configuration.iceServers로 한다.

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

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

    1. urls를 server.urls로 한다.

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

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

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

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

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

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

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

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

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

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

  2. parsedURL을 url을 구문 분석한 결과로 한다.

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

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

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

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

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

    참고

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

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

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

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

4.4.2 인터페이스 정의

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

signalingState의 유형: RTCSignalingState, 읽기 전용

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

iceGatheringState 유형: RTCIceGatheringState, 읽기 전용

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

iceConnectionState 유형: RTCIceConnectionState, 읽기 전용

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

connectionState 유형: RTCPeerConnectionState, 읽기 전용

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  4. p를 반환한다.

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

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

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

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

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

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

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

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

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

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

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

      1. kind를 transceiver의 [[Receiver]]의 [[ReceiverTrack]]의 kind로 한다.

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

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

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

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

      참고

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

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

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

  6. p를 offer로 이행한다.

createAnswer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  4. p를 반환한다.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      1. kind를 transceiver의 [[Receiver]]의 [[ReceiverTrack]]의 kind로 한다.

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

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

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

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

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

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

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

      참고

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

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

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

  6. p를 answer로 이행한다.

setLocalDescription

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

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

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

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

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

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

  3. sdp를 description.sdp로 한다.

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

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

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

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

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

      1. sdp를 connection.[[LastCreatedOffer]]의 값으로 설정한다.

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

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

      1. sdp를 connection.[[LastCreatedAnswer]]의 값으로 설정한다.

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

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

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

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

참고

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

setRemoteDescription

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

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

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

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

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

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

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

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

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

addIceCandidate

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        4. p를 undefined로 이행한다.

    8. p를 반환한다.

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

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

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

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

참고

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

restartIce

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

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

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

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

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

getConfiguration

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

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

setConfiguration

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

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

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

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

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

close

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

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

  2. connection과 false 값을 사용하여 연결을 닫는다.

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

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

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

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

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

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

    2. transceiver와 disappear를 사용하여 RTCRtpTransceiver를 중지한다.

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

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

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

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

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

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

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

4.4.3 레거시 인터페이스 확장

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

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

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

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

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

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

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

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

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

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

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

setLocalDescription

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

setRemoteDescription

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

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

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

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

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

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

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

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

addIceCandidate

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

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

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

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

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

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

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

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

콜백 정의

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

offerToReceiveVideo의 형식은 boolean

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

4.4.4 가비지 컬렉션

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

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

4.5 오류 처리

4.5.1 일반 원칙

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

4.6 세션 기술 모델

4.6.1 RTCSdpType

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

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

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

pranswer

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

answer

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

rollback

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

4.6.2 RTCSessionDescription 클래스

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

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

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

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

4.7 세션 협상 모델

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

4.7.1 협상 필요 상태 설정

이 절은 비규범적이다.

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

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

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

4.7.2 협상 필요 상태 해제

이 절은 비규범적이다.

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

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

4.7.3 협상 필요 플래그 갱신

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

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

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

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

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

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

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

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

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

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

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

    참고

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4.8.1 RTCIceCandidate 인터페이스

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

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

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

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

  1. candidateInitDict의 sdpMid 및 sdpMLineIndex 멤버가 모두 null이면 다음 예외를 던진다: TypeError.
  2. candidateInitDict로 RTCIceCandidate를 생성한 결과를 반환한다.

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. candidate를 candidateInitDict의 candidate 사전 멤버로 한다. candidate가 빈 문자열이 아니면 다음 단계를 실행한다.
    1. candidate를 candidate-attribute 문법을 사용하여 파싱한다.
    2. candidate-attribute 파싱에 실패하면 이 단계들을 중단한다.
    3. 파싱 결과의 필드 중 iceCandidate의 대응 속성에 유효하지 않은 값을 나타내는 것이 있으면 이 단계들을 중단한다.
    4. iceCandidate의 대응 내부 슬롯을 파싱 결과의 필드 값으로 설정한다.
  5. iceCandidate를 반환한다.
참고

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

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

속성

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

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

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

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

참고

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

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

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

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

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

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

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

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

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

4.8.1.2 RTCIceProtocol 열거형

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

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

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

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

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

4.8.1.4 RTCIceCandidateType 열거형

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

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

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

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

4.8.2 RTCPeerConnectionIceEvent

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

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

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

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

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

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

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

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

참고

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

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

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

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

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

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

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

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

4.8.3 RTCPeerConnectionIceErrorEvent

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

url의 형식은 DOMString이다.

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

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

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

errorText의 형식은 USVString이다.

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

4.9 인증서 관리

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

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

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

메서드

generateCertificate, 정적

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

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

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

참고

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

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

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

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

  1. keygenAlgorithm을 generateCertificate의 첫 번째 인수로 한다.

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

    참고

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

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

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

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

    3. certificateExpiration.expires가 undefined가 아니면 expires를 certificateExpiration.expires로 설정한다.

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

      참고

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. p를 반환한다.

4.9.1 RTCCertificateExpiration 사전

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

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

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

4.9.2 RTCCertificate 인터페이스

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

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

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

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

메서드
getFingerprints

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

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

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

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

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

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

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

5. RTP 미디어 API

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

참고

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

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

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

참고

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

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

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

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

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

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

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

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

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

5.1 RTCPeerConnection 인터페이스 확장

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

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

속성

ontrack의 타입은 EventHandler

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

메서드

getSenders

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  3. kind를 track.kind로 둔다.

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

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

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

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

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

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

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

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

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

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

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

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

  9. sender가 null이면 다음 단계를 실행한다.

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

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

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

    4. transceiver를 connection의 트랜시버 집합에 추가한다.

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

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

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

  12. sender를 반환한다.

removeTrack

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

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

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

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

  1. sender를 removeTrack에 전달된 인수로 둔다.

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

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

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

  5. transceiver를 RTCRtpTransceiver 객체로 둔다. 이 객체는 sender에 대응한다.

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

  7. senders를 CollectSenders 알고리즘을 실행한 결과로 둔다.

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

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

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

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

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

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

addTransceiver

새 RTCRtpTransceiver를 생성하여 트랜시버 집합에 추가한다.

트랜시버를 추가하면 이후 createOffer를 호출할 때 대응하는 트랜시버의 미디어 설명이 추가된다. 이는 [RFC9429]의 ( 5.2.2절)에 정의되어 있다.

mid의 초기값은 null이다. 세션 기술을 설정하면 나중에 이 값이 null이 아닌 값으로 변경될 수 있다.

sendEncodings 인수를 사용하여 제안할 동시 전송 인코딩의 수와 선택적으로 해당 RID 및 인코딩 매개변수를 지정할 수 있다.

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

  1. init을 두 번째 인수로 둔다.

  2. streams를 init.streams로 둔다.

  3. sendEncodings를 init.sendEncodings로 둔다.

  4. direction을 init.direction으로 둔다.

  5. 첫 번째 인수가 문자열이면 kind를 첫 번째 인수로 두고 다음 단계를 실행한다.

    1. kind가 "audio"도 아니고 "video"도 아니면 다음 예외를 발생시킨다: TypeError.

    2. track을 null로 둔다.

  6. 첫 번째 인수가 MediaStreamTrack이면 track을 첫 번째 인수로 두고 kind를 track.kind로 둔다.

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

  8. 다음 sendEncodings에 대해 addTransceiver sendEncodings 검증 단계를 실행한다. 그 안의 각 RTCRtpEncodingParameters 딕셔너리를 “인코딩”이라고 하며, 이를 통해 검증한다.

    1. 각 rid 값이 sendEncodings에서 [RFC8851] 10절에 명시된 문법을 준수하는지 확인한다. RID 중 하나라도 이 요구 사항을 충족하지 않으면 다음 예외를 발생시킨다: TypeError.

      다음 조건 중 하나라도 충족되면 다음 예외를 발생시킨다: TypeError.
      • 어떤 인코딩이 포함하는 rid 멤버의 값이 [RFC8851] 10절에 명시된 문법 요구 사항을 준수하지 않는다.
      • 일부 인코딩에는 포함된 rid 멤버가 있지만 모든 인코딩에 있는 것은 아니다.
      • 어떤 인코딩이 포함하는 rid 멤버의 값이 다른 인코딩의 rid 멤버에 포함된 값과 같다. 해당 다른 인코딩은 sendEncodings에 있다.
    2. 어떤 인코딩이 포함하는 읽기 전용 매개변수가 rid가 아니면 다음 예외를 발생시킨다: InvalidAccessError.

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

      어떤 인코딩이 포함하는 codec 멤버의 값이 어떤 코덱과도 일치하지 않으면 다음에서 지원하는 코덱이 아니다: RTCRtpSender.getCapabilities(kind).codecs. 이 경우 다음 예외를 발생시킨다: OperationError.

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

      사용자 에이전트가 협상 없이 코덱을 변경하는 기능을 지원하지 않거나 개별 인코딩에 코덱을 설정하는 기능을 지원하지 않으면 프로미스를 거부된 상태로 반환한다. 이때 새로 생성한 OperationError를 사용한다.

    5. kind가 "audio"이면 scaleResolutionDownBy 및 maxFramerate 멤버 중 하나라도 포함하는 모든 인코딩에서 해당 멤버를 제거한다.

    6. 어떤 인코딩이 포함하는 scaleResolutionDownBy 멤버의 값이 1.0보다 작으면 다음 예외를 발생시킨다: RangeError.

    7. 정의된 각 maxFramerate 멤버가 sendEncodings에서 0.0보다 큰 값을 갖는지 확인한다. maxFramerate 값 중 하나라도 이 요구 사항을 충족하지 않으면 다음 예외를 발생시킨다: RangeError.

    8. maxN을 사용자 에이전트가 지원할 수 있는 동시 인코딩 총수의 최댓값으로 둔다. 이는 해당 kind에 적용되며 최소값은 1이다. 아직 사용할 코덱을 알 수 없으므로 이 값은 낙관적으로 정하는 것이 좋다.

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

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

    11. kind가 "video"이고 어느 인코딩에도 포함되어 있지 않은 scaleResolutionDownBy 멤버라면 각 인코딩에 scaleResolutionDownBy 멤버를 다음 값과 함께 추가한다: 2^(length of sendEncodings - encoding index - 1). 그 결과 해상도가 작은 것부터 큰 것 순으로 배치되며 마지막 인코딩에는 크기 조정이 적용되지 않는다. 예를 들어 길이가 3이면 4:2:1이 된다.

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

      참고
      하나의 기본 RTCRtpEncodingParameters를 sendEncodings에 제공하면 애플리케이션이 나중에 setParameters를 사용하여 인코딩 매개변수를 설정할 수 있다. 동시 전송을 사용하지 않는 경우에도 가능하다.
  9. RTCRtpSender를 생성한다. 이때 track, kind, streams 및 sendEncodings를 사용하고 그 결과를 sender로 둔다.

    sendEncodings가 설정되어 있으면 이후 createOffer 호출은 여러 RTP 인코딩을 전송하도록 구성된다. 이는 [RFC9429]의 ( 5.2.2절 및 5.2.1절)에 정의되어 있다. setRemoteDescription이 여러 RTP 인코딩을 수신할 수 있는 대응 원격 기술로 호출되었다고 하자. 이 기능은 [RFC9429]의 ( 3.7절)에 정의되어 있다. 이 경우 RTCRtpSender가 여러 RTP 인코딩을 전송할 수 있으며, 트랜시버의 sender.getParameters()를 통해 가져온 매개변수에는 협상된 인코딩이 반영된다.

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

  11. RTCRtpTransceiver를 생성한다. 이때 sender, receiver 및 direction을 사용하고 그 결과를 transceiver로 둔다.

  12. transceiver를 connection의 트랜시버 집합에 추가한다.

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

  14. transceiver를 반환한다.

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

딕셔너리 RTCRtpTransceiverInit 멤버

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

원격 RTCPeerConnection의 트랙 이벤트가 발생할 때, 추가되는 RTCRtpReceiver에 대응하여 이벤트에 포함될 스트림이다.

sendEncodings의 타입은 sequence<RTCRtpEncodingParameters>이다.

미디어의 RTP 인코딩을 전송하기 위한 매개변수를 포함하는 시퀀스이다.

WebIDLenum RTCRtpTransceiverDirection {
  "sendrecv",
  "sendonly",
  "recvonly",
  "inactive",
  "stopped"
};
RTCRtpTransceiverDirection 열거형 설명
열거형 값 설명
sendrecv RTCRtpTransceiver의 RTCRtpSender sender는 RTP 전송을 제안하며, 원격 피어가 이를 수락하고 sender.getParameters().encodings[i].active가 어떤 i 값에 대해서든 true이면 RTP를 전송한다. RTCRtpTransceiver의 RTCRtpReceiver는 RTP 수신을 제안하며, 원격 피어가 수락하면 RTP를 수신한다.
sendonly RTCRtpTransceiver의 RTCRtpSender sender는 RTP 전송을 제안하며, 원격 피어가 이를 수락하고 sender.getParameters().encodings[i].active가 어떤 i 값에 대해서든 true이면 RTP를 전송한다. RTCRtpTransceiver의 RTCRtpReceiver는 RTP 수신을 제안하지 않으며 RTP를 수신하지 않는다.
recvonly RTCRtpTransceiver의 RTCRtpSender는 RTP 전송을 제안하지 않으며 RTP를 전송하지 않는다. RTCRtpTransceiver의 RTCRtpReceiver는 RTP 수신을 제안하며, 원격 피어가 수락하면 RTP를 수신한다.
inactive RTCRtpTransceiver의 RTCRtpSender는 RTP 전송을 제안하지 않으며 RTP를 전송하지 않는다. RTCRtpTransceiver의 RTCRtpReceiver는 RTP 수신을 제안하지 않으며 RTP를 수신하지 않는다.
stopped RTCRtpTransceiver는 RTP를 송신하지도 수신하지도 않는다. 제안에서는 포트 0을 생성한다. 응답에서는 RTCRtpSender가 RTP 전송을 제안하지 않고, RTCRtpReceiver도 RTP 수신을 제안하지 않는다. 이는 종단 상태이다.

5.1.1 원격 MediaStreamTrack 처리

애플리케이션은 트랜시버의 방향을 양방향 모두 일시적으로 끄는 "inactive"로 설정하거나 수신 방향만 거부하는 "sendonly"로 설정하여 수신 미디어 기술을 거부할 수 있다. m-line을 재사용할 수 있게 하면서 영구적으로 거부하려면 애플리케이션이 RTCRtpTransceiver.stop()을 호출한 후 해당 측에서 협상을 시작해야 한다.

원격 트랙을 처리하려면 RTCRtpTransceiver transceiver, direction, msids, addList, removeList 및 trackEventInits가 주어졌을 때 다음 단계를 실행한다.

  1. 연결된 원격 스트림을 설정한다. 이때 transceiver.[[Receiver]], msids, addList 및 removeList를 사용한다.

  2. direction이 "sendrecv" 또는 "recvonly"이고 transceiver.[[FiredDirection]]이 "sendrecv"도 아니고 "recvonly"도 아니거나, 이전 단계에서 addList의 길이가 증가했다면 원격 트랙의 추가를 처리한다. 이때 transceiver와 trackEventInits를 사용한다.

  3. direction이 "sendonly" 또는 "inactive"이면 transceiver.[[Receptive]]를 false로 설정한다.

  4. direction이 "sendonly" 또는 "inactive"이고 transceiver.[[FiredDirection]]이 "sendrecv" 또는 "recvonly"이면 원격 트랙의 제거를 처리한다. 대상은 미디어 설명이며, transceiver와 muteTracks를 사용한다.

  5. transceiver.[[FiredDirection]]을 direction으로 설정한다.

원격 트랙의 추가를 처리하려면 다음 값이 주어진다: RTCRtpTransceiver transceiver 및 trackEventInits. 그런 다음 다음 단계를 실행한다.

  1. receiver를 transceiver.[[Receiver]]로 둔다.

  2. track을 receiver.[[ReceiverTrack]]으로 둔다.

  3. streams를 receiver.[[AssociatedRemoteMediaStreams]]로 둔다.

  4. 새 RTCTrackEventInit 딕셔너리를 생성한다. 그 멤버는 receiver, track, streams 및 transceiver이며, 이 딕셔너리를 trackEventInits에 추가한다.

원격 트랙의 제거를 처리하려면 RTCRtpTransceiver transceiver와 muteTracks를 사용하여 다음 단계를 실행한다.

  1. receiver를 transceiver.[[Receiver]]로 둔다.

  2. track을 receiver.[[ReceiverTrack]]으로 둔다.

  3. track.muted가 false이면 track을 muteTracks에 추가한다.

연결된 원격 스트림을 설정하려면 다음 값이 주어진다: RTCRtpReceiver receiver, msids, addList 및 removeList. 그런 다음 다음 단계를 실행한다.

  1. connection을 RTCPeerConnection 객체로 둔다. 이 객체는 receiver와 연결되어 있다.

  2. msids의 각 MSID에 대해 MediaStream 객체가 해당 id를 사용하여 이 connection에 대해 이전에 생성되지 않았다면 그 id를 가진 MediaStream 객체를 생성한다.

  3. streams를 MediaStream 객체의 목록으로 둔다. 이 객체들은 이 connection에 대해 id로 생성되었으며, 해당 ID는 msids에 대응한다.

  4. track을 receiver.[[ReceiverTrack]]으로 둔다.

  5. 각 stream에 대해, 해당 항목이 receiver.[[AssociatedRemoteMediaStreams]]에 있지만 streams에는 없다면 stream과 track을 한 쌍으로 removeList에 추가한다.

  6. streams에 있는 각 stream이 receiver.[[AssociatedRemoteMediaStreams]]에 없다면 stream과 track을 한 쌍으로 addList에 추가한다.

  7. receiver.[[AssociatedRemoteMediaStreams]]를 streams로 설정한다.

5.2 RTCRtpSender 인터페이스

RTCRtpSender 인터페이스는 애플리케이션이 주어진 MediaStreamTrack을 인코딩하여 원격 피어로 전송하는 방식을 제어할 수 있도록 한다. setParameters 가 RTCRtpSender 객체에서 호출되면 인코딩이 그에 맞게 변경된다.

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]] 내부 슬롯을 두고, 이 슬롯은 해당 sender와 연결할 MediaStream 객체의 ID 목록을 나타낸다. [[AssociatedMediaStreamIds]] 슬롯은 sender가 [RFC9429] (section 5.2.1.)에 설명된 대로 SDP로 표현될 때 사용한다.

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

  9. 각 stream에 대해, streams에 속하는 항목이라면 stream.id를 [[AssociatedMediaStreamIds]] 에 아직 없을 때 추가한다.

  10. sender에 [[SendEncodings]] 내부 슬롯을 두며, 이는 RTCRtpEncodingParameters 사전의 목록을 나타낸다.

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

    Note

    RTCRtpEncodingParameters 사전에는 active 멤버가 포함되며 그 기본값은 true이다.

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

    sender에 [[LastStableRidlessSendEncodings]] 내부 슬롯을 두고 null로 초기화한다.

  13. sender에 [[SendCodecs]] 내부 슬롯을 둔다. 이 슬롯은 RTCRtpCodecParameters 사전의 목록을 나타내며 빈 목록으로 초기화한다.

  14. sender에 [[LastReturnedParameters]] 내부 슬롯을 두며, 이는 getParameters와 setParameters 트랜잭션을 대응시키는 데 사용한다.

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

Attributes

track of type MediaStreamTrack, readonly, nullable

track 속성은 이 RTCRtpSender 객체와 연결된 트랙이다. track이 종료되었거나 트랙의 출력이 비활성화되었으면, 즉 트랙이 비활성화되거나 음소거되었으면, RTCRtpSender는 반드시 검은 프레임을 보내야 하고(비디오) 절대로 전송해서는 안 된다(오디오). 비디오의 경우 RTCRtpSender는 가급적 초당 하나의 검은 프레임을 보내야 한다. track이 null이면 RTCRtpSender는 전송하지 않는다. 값을 가져올 때 이 속성은 반드시 [[SenderTrack]] 슬롯의 값을 반환해야 한다.

transport of type RTCDtlsTransport, readonly, nullable

transport 속성은 track의 미디어를 RTP 패킷 형태로 보내는 전송이다. RTCDtlsTransport 객체가 생성되기 전에는 transport 속성이 null이다. 번들링을 사용하면 여러 RTCRtpSender 객체가 하나의 transport를 공유하며 모두 같은 전송으로 RTP와 RTCP를 보낸다.

값을 가져올 때 이 속성은 반드시 [[SenderTransport]] 슬롯의 값을 반환해야 한다.

Methods

getCapabilities, static

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

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

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

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

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

구현된 송신 코덱 목록은 주어진 kind에 대해 구현 정의 방식으로 정해지는 RTCRtpCodec 사전의 목록이며, 주어진 kind(비디오 또는 오디오)의 미디어를 보내기 위해 사용자 에이전트가 지원하는 코덱을 가장 낙관적으로 나타낸다.

구현된 송신용 헤더 확장 목록은 주어진 kind에 대해 구현 정의 방식으로 정해지는 RTCRtpHeaderExtensionCapability 사전의 목록이며, 주어진 kind(비디오 또는 오디오)의 미디어를 보내기 위해 사용자 에이전트가 지원하는 헤더 확장을 가장 낙관적으로 나타낸다.

이러한 기능은 일반적으로 오래 유지되며 출처를 넘어 이용할 수 있는 장치 정보를 제공하므로 애플리케이션의 핑거프린팅 가능 범위를 늘린다. 개인정보 보호에 민감한 상황에서 사용자 에이전트는 경우에 따라 기능의 공통 부분집합만 보고하는 등의 완화 조치를 고려할 수 있다. (This is a fingerprinting vector.)

Note

반환된 코덱 기능은 setCodecPreferences() 알고리즘과 이 알고리즘이 어떤 입력에 대해 InvalidModificationError를 던지는지에 영향을 준다. 개인정보 보호 완화 조치의 효과를 보장하려면, 이 정보는 createOffer()와 createAnswer()가 송신용으로 협상된 코덱에 관해 드러내는 정보와도 일관되어야 한다.

setParameters

setParameters 메서드는 track을 인코딩하여 원격 피어로 전송하는 방식을 갱신한다.

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

  1. parameters를 메서드의 첫 번째 인수로 둔다.
  2. sender를 RTCRtpSender 객체로 두며, 이 객체에서 setParameters 가 호출된다.
  3. transceiver를 RTCRtpTransceiver 객체로 두며, 이는 sender와 연결되어 있다(즉, sender는 transceiver.[[Sender]]이다).
  4. transceiver.[[Stopping]]가 true이면 거부된 상태인 프로미스를 반환한다. 이때 거부 사유는 새로 생성한 InvalidStateError이다.
  5. sender.[[LastReturnedParameters]]가 null이면 거부된 상태인 프로미스를 반환한다. 이때 거부 사유는 새로 생성한 InvalidStateError이다.
  6. 실행한다: parameters 를 검증하는 다음 단계인 setParameters 검증 단계:
    1. encodings를 parameters.encodings로 둔다.
    2. codecs를 parameters.codecs로 둔다.
    3. Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)

      choosableCodecs를 codecs로 둔다.

    4. Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)

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

    5. Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)

      choosableCodecs가 여전히 빈 목록이면 choosableCodecs를 구현된 송신 코덱 목록 중 transceiver의 종류에 해당하는 목록으로 설정한다.

    6. N을 RTCRtpEncodingParameters의 개수로 두며, 이는 sender.[[SendEncodings]]에 저장되어 있는 사전의 개수이다.
    7. 다음 조건 중 하나라도 충족되면 프로미스 를 반환한다. 그 프로미스 는 거부 되며 사유는 새로 생성한 InvalidModificationError이다:
      • encodings.length 가 N과 다르다.
      • encodings의 순서가 바뀌었다.
      • parameters의 어떤 매개변수가 읽기 전용 매개변수(예: RID)로 표시되어 있고 그 값이 sender.[[LastReturnedParameters]] 의 대응하는 매개변수 값과 다르다. 이는 transactionId에도 적용된다.
      • Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)
        encoding 중 encodings에 속한 항목이 코덱을 포함하며, 그 코덱이 choosableCodecs에 없다. 이때 코덱 사전 일치 알고리즘을 사용하고 ignoreLevels는 true로 설정한다.
    8. 트랜시버 종류가 "audio"이면 scaleResolutionDownBy와 maxFramerate 멤버를 모든 encodings에서 제거하되, 이들 중 하나라도 포함하는 항목에 대해 수행한다.

    9. 트랜시버 종류가 "video" 이면 encodings의 각 인코딩 중 멤버를 포함하지 않는 항목에 대해, 그 멤버는 scaleResolutionDownBy이다. 여기에 scaleResolutionDownBy 멤버를 추가하고 값을 1.0으로 설정한다.

    10. 트랜시버 종류가 "video" 이고 encodings의 어떤 인코딩이 포함하는 scaleResolutionDownBy 멤버의 값이 1.0보다 작으면, 거부된 상태인 프로미스를 반환한다. 거부 사유는 새로 생성한 RangeError이다.

    11. encodings의 각 인코딩에 값이 0.0 이상인 maxFramerate 멤버가 있는지 확인한다. maxFramerate 값 중 하나라도 이 요건을 충족하지 않으면, 거부된 상태인 프로미스를 반환한다. 이때 거부 사유는 새로 생성한 RangeError이다.

    12. Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)

      사용자 에이전트가 어느 인코딩의 코덱 설정이나 서로 다른 인코딩에 서로 다른 코덱 값을 혼합하는 것을 지원하지 않으면, 거부된 상태인 프로미스를 반환한다. 이때 거부 사유는 새로 생성한 OperationError이다.

  7. p를 새 프로미스로 둔다.
  8. 병렬 방식으로, 미디어 스택을 구성한다. 이때 사용할 매개변수는 parameters 이며송신할 대상은 sender.[[SenderTrack]]이다.
    1. 미디어 스택이 성공적으로 구성된 경우, 그때 사용한 매개변수가 parameters인 경우에는 다음 단계들을 실행하는 태스크 를 큐에 넣는다:
      1. sender.[[LastReturnedParameters]]를 null로 설정한다.
      2. sender.[[SendEncodings]]를 parameters.encodings로 설정한다.
      3. 결정 절차로 p를 undefined로 결정한다.
    2. 미디어 스택을 구성 하는 도중 어떠한 오류라도 발생했다면 다음 단계들 을 실행 하는 태스크 를 큐에 넣는다:
      1. 하드웨어 리소스를 사용할 수 없어 오류가 발생했으면, 거부 절차로 p를 거부한다. 이때 거부 사유는 새로 생성한 RTCError이며, 그 errorDetail은 " hardware-encoder-not-available "로 설정한다. 그리고 이 단계들을 중단한다.
      2. 하드웨어 인코더가 parameters를 지원하지 않아 오류가 발생했으면, 거부 절차로 p를 거부한다. 거부 사유는 새로 생성한 RTCError이며 그 errorDetail은 " hardware-encoder-error "로 설정한다. 그리고 이 단계들을 중단한다.
      3. 그 밖의 모든 오류에서는 거부 절차로 p를 거부하며, 거부 사유는 새로 생성한 OperationError이다.
  9. p를 반환한다.

setParameters 는 SDP 재협상을 유발하지 않으며, 제안/응답으로 협상된 엔벌로프 안에서 미디어 스택이 보내거나 받는 것을 변경하는 데만 사용할 수 있다. RTCRtpSendParameters 사전의 속성은 이 범위를 벗어나는 변경을 허용하지 않도록 설계되어 있으므로, cname처럼 변경할 수 없는 속성은 읽기 전용이다. 비트레이트 같은 다른 항목은 maxBitrate 등의 한도로 제어한다. 사용자 에이전트는 maxBitrate 가 지정하는 최대 비트레이트를 초과하지 않는 동시에 SDP 등 다른 곳에서 지정한 비트레이트 제약도 충족하도록 보장해야 한다.

getParameters

getParameters() 메서드는 RTCRtpSender 객체의 현재 매개변수를 반환한다. 이는 track을 인코딩하여 원격 RTCRtpReceiver로 전송하는 방식에 관한 매개변수이다.

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

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

  2. sender.[[LastReturnedParameters]]가 null이 아니면 sender.[[LastReturnedParameters]] 를 반환하고 이 단계들을 중단한다.

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

  4. sender.[[LastReturnedParameters]]를 result로 설정한다.

  5. sender.[[LastReturnedParameters]]를 null로 설정하는 태스크를 큐에 넣는다.

  6. result를 반환한다.

getParameters 는 setParameters 와 함께 다음 방식으로 매개변수를 변경하는 데 사용할 수 있다:

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

재협상 없이 RTCRtpSender의 현재 track을 제공된 다른 트랙(또는 null 트랙)으로 대체하려고 시도한다.

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

  1. sender를 RTCRtpSender 객체로 두며, 이 객체에서 replaceTrack가 호출된다.

  2. transceiver를 RTCRtpTransceiver 객체로 두며, 이 객체는 sender와 연결되어 있다.

  3. connection를 RTCPeerConnection 객체로 두며, 이 객체는 sender와 연결되어 있다.

  4. withTrack를 이 메서드의 인수로 둔다.

  5. withTrack가 null이 아니고 withTrack.kind가 트랜시버 종류, 즉 transceiver의 종류와 다르면, 거부된 상태인 프로미스를 반환한다. 거부 사유는 새로 생성한 TypeError이다.

  6. 작업을 연결하는 절차로 다음 단계를 connection의 작업 체인에 연결한 결과를 반환한다:

    1. transceiver.[[Stopping]]가 true이면 거부된 상태인 프로미스를 반환한다. 이때 거부 사유는 새로 생성한 InvalidStateError이다.

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

    3. sending를 true로 두되, 이는 transceiver.[[CurrentDirection]]가 "sendrecv" 또는 " sendonly"인 경우이다. 그렇지 않으면 false로 둔다.

    4. 다음 단계를 병렬로 실행한다:

      1. sending가 true이고 withTrack이 null이면 송신자의 전송을 중단시킨다.

      2. sending가 true이고 withTrack이 null 이 아니면, withTrack을 송신자가 이미 협상한 엔벌로프를 위반하지 않고 즉시 보낼 수 있는지 판단한다. 불가능하면:

        1. 전역 태스크를 큐에 넣는다. 소스는 네트워킹 태스크 소스이고 현재 렐름의 전역 객체를 global로 사용한다. 태스크는 거부 절차로 p를 거부하며, 사유는 새로 생성한 InvalidModificationError이다.
        2. 이 단계들을 중단한다.
      3. sending가 true이고 withTrack이 null 이 아니면, 송신자가 기존 트랙 대신 withTrack을 끊김 없이 전송하도록 전환시킨다.

      4. 다음 단계를 실행하는 태스크를 큐에 넣는다:

        1. connection.[[IsClosed]]가 true이면 이 단계들을 중단한다.

        2. sender.[[SenderTrack]]를 withTrack로 설정한다.

        3. 전역 태스크를 큐에 넣는다. 소스는 네트워킹 태스크 소스이고 현재 렐름의 전역 객체를 global로 사용한다. 태스크는 결정 절차로 p를 undefined로 결정한다.

    5. p를 반환한다.

Note

크기나 프레임 속도를 변경하는 데 협상이 필요하지 않을 수도 있다. 협상이 필요할 수 있는 경우는 다음과 같다:

  1. [ RFC6236 ]에 설명된 대로 협상된 imageattr 범위를 벗어나는 값으로 해상도를 변경하는 경우.
  2. 코덱의 블록 속도를 초과하게 되는 값으로 프레임 속도를 변경하는 경우.
  3. 원시 형식인지 사전 인코딩된 형식인지가 다른 비디오 트랙.
  4. 채널 수가 다른 오디오 트랙.
  5. 인코딩도 수행하는 소스(일반적으로 하드웨어 인코더)는 협상된 코덱을 생성하지 못할 수 있다. 마찬가지로 소프트웨어 소스는 인코딩 소스에 대해 협상된 코덱을 구현하지 않을 수 있다.
setStreams

이 송신자의 트랙과 연결할 MediaStream 객체들을 설정한다.

setStreams 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. sender를 이 메서드가 호출된 RTCRtpSender 객체로 둔다.

  2. connection를 이 메서드가 호출된 RTCPeerConnection 객체로 둔다.

  3. connection.[[IsClosed]]가 true이면 예외를 던지는 절차로 InvalidStateError를 던진다.

  4. streams을 메서드의 인수에서 구성한 MediaStream 객체 목록으로 두며, 인수 없이 호출되었으면 빈 목록으로 둔다.

  5. sender.[[AssociatedMediaStreamIds]]를 빈 집합으로 설정한다.

  6. 각 stream에 대해, streams에 속하는 항목이라면 stream.id를 [[AssociatedMediaStreamIds]]에 아직 없을 때 추가한다.

  7. 협상 필요 플래그를 갱신하는 절차를 connection에 대해 실행한다.

getStats

이 송신자에 대해서만 통계를 수집하고 결과를 비동기적으로 보고한다.

getStats() 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. selector를 메서드가 호출된 RTCRtpSender 객체로 둔다.

  2. p를 새 프로미스로 두고 다음 단계를 병렬로 실행한다:

    1. selector가 나타내는 통계를 통계 선택 알고리즘에 따라 수집한다.

    2. 전역 태스크를 큐에 넣는다. 이 태스크의 소스는 네트워킹 태스크 소스이고, 현재 렐름의 전역 객체를 global로 사용한다. 태스크는 결정 절차로 p를 결정하며, 그 값은 수집한 통계를 포함하는 결과 RTCStatsReport 객체이다.

  3. p를 반환한다.

5.2.1 RTCRtpParameters 딕셔너리

WebIDLdictionary RTCRtpParameters {
  required sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
  required RTCRtcpParameters rtcp;
  required sequence<RTCRtpCodecParameters> codecs;
};
Dictionary RTCRtpParameters Members
headerExtensions of type sequence<RTCRtpHeaderExtensionParameters>, required

RTP 헤더 확장의 매개변수를 포함하는 시퀀스이다. 읽기 전용 매개변수이다.

rtcp of type RTCRtcpParameters, required

RTCP에 사용하는 매개변수이다. 읽기 전용 매개변수이다.

codecs of type sequence<RTCRtpCodecParameters>, required

RTCRtpSender가 선택할 미디어 코덱과 RTX, RED 및 FEC 메커니즘의 항목을 포함하는 시퀀스이다. RTX를 통한 재전송이 활성화된 각 미디어 코덱에는 codecs의 대응 항목이 있으며, 이 항목의 mimeType 속성은 audio/rtx 또는 video/rtx를 통한 재전송을 나타내고, sdpFmtpLine 속성은 "apt"와 "rtx-time" 매개변수를 제공한다. 읽기 전용 매개변수이다.

5.2.2 RTCRtpSendParameters 딕셔너리

WebIDLdictionary RTCRtpSendParameters : RTCRtpParameters {
  required DOMString transactionId;
  required sequence<RTCRtpEncodingParameters> encodings;
};
Dictionary RTCRtpSendParameters Members
transactionId of type DOMString, required

마지막으로 적용된 매개변수 집합의 고유 식별자이다. setParameters가 이전의 getParameters 를 바탕으로만 호출되고 그 사이에 변경이 없도록 보장한다. 읽기 전용 매개변수이다.

encodings of type sequence<RTCRtpEncodingParameters>, required

미디어의 RTP 인코딩 매개변수를 포함하는 시퀀스이다.

5.2.3 RTCRtpReceiveParameters 딕셔너리

WebIDLdictionary RTCRtpReceiveParameters : RTCRtpParameters {
};

5.2.4 RTCRtpCodingParameters 딕셔너리

WebIDLdictionary RTCRtpCodingParameters {
  DOMString rid;
};
Dictionary RTCRtpCodingParameters Members
rid of type DOMString

설정되어 있으면 이 RTP 인코딩은 [RFC9429] (section 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;
};
Dictionary RTCRtpEncodingParameters Members
active of type boolean, defaulting to true

이 인코딩을 실제로 보내고 있음을 나타낸다. false로 설정하면 이 인코딩을 더 이상 보내지 않는다. true로 설정하면 이 인코딩을 보낸다. 값을 false로 설정해도 SSRC가 제거되지는 않으므로 RTCP BYE를 보내지 않는다.

Candidate Addition 49:Add codec to RTCRtpEncodingParameters (PR #2985)
codec of type RTCRtpCodec

이 인코딩의 RTP 스트림에 사용할 코덱을 선택하는 선택적 값이다. 없으면 사용자 에이전트는 송신용으로 협상된 코덱 중 어느 것이든 선택하여 사용할 수 있다.

codec이 설정되어 있고 [[SendCodecs]]가 협상되어 있으면, 사용자 에이전트는 가급적 [[SendCodecs]] 중 codec과 일치하는 첫 번째 항목을 송신에 사용해야 한다. 일치 여부는 코덱 사전 일치 알고리즘으로 판정하며, ignoreLevels는 true로 설정한다.

maxBitrate of type unsigned long

존재하면 이 인코딩을 보내는 데 사용할 수 있는 최대 비트레이트를 나타낸다. 사용자 에이전트는 maxBitrate 값을 초과하지 않는 한 인코딩 간에 대역폭을 자유롭게 할당할 수 있다. 인코딩은 전송별 또는 세션별 대역폭 한도 같은 다른 한도에 따라 여기서 지정한 최대값보다 낮게 제한될 수도 있다. maxBitrate는 [ RFC3890 ] 6.2.2절에 정의된 전송 독립적 애플리케이션별 최대(TIAS) 대역폭과 같은 방식으로 계산한다. 이는 IP 또는 TCP나 UDP 같은 다른 전송 계층을 계산에 넣지 않은, 필요한 최대 대역폭이다. maxBitrate의 단위는 초당 비트이다.

Note

비트레이트를 달성하는 방식은 미디어와 인코딩에 따라 다르다. 비디오에서는 항상 가능한 한 빨리 프레임을 보내지만, 비트레이트가 충분히 낮아질 때까지 프레임을 버릴 수 있다. 따라서 비트레이트가 0이어도 프레임 하나는 보낼 수 있다. 오디오에서는 비트레이트가 선택한 인코딩을 전송할 만큼 충분한 대역폭을 허용하지 않으면 재생을 중단해야 할 수도 있다.

maxFramerate of type double

이 멤버는 송신자의 kind가 "video" 일 때만 존재할 수 있다. 존재하면 이 인코딩을 보내는 데 사용할 수 있는 최대 프레임 속도를 초당 프레임 수로 나타낸다. 사용자 에이전트 는 maxFramerate 값을 초과하지 않는 한 인코딩 간에 대역폭을 자유롭게 할당할 수 있다.

setParameters() 로 변경하면 새 프레임 속도는 현재 그림이 완성된 뒤에 적용된다. 따라서 최대 프레임 속도를 0으로 설정하면 다음 프레임에서 비디오가 정지하는 효과가 있다.

scaleResolutionDownBy of type double

이 멤버는 송신자의 kind가 "video"일 때만 존재한다. 전송하기 전에 비디오 해상도의 각 차원을 주어진 값으로 나누어 축소한다. 예를 들어 값이 2.0이면 각 차원을 2배 축소하므로 크기가 4분의 1인 비디오를 보내게 된다. 값이 1.0이면 비디오에 영향을 주지 않는다. 값은 1.0 이상이어야 한다. 기본적으로 2배씩 축소하는 방식을 역순으로 적용하여 4:2:1처럼 낮은 해상도부터 높은 해상도까지의 순서를 만든다. 계층이 하나뿐이면 송신자는 기본적으로 축소하지 않는다(즉, scaleResolutionDownBy는 1.0이다).

5.2.6 RTCRtcpParameters 딕셔너리

WebIDLdictionary RTCRtcpParameters {
  DOMString cname;
  boolean reducedSize;
};
Dictionary RTCRtcpParameters Members
cname of type DOMString

RTCP가 사용하는 정규 이름(CNAME)이다(예: SDES 메시지에서 사용). 읽기 전용 매개변수이다.

reducedSize of type boolean

축소 크기 RTCP[ RFC5506 ]를 구성했는지(true일 때), 또는 [ RFC3550 ]에 지정된 복합 RTCP를 구성했는지(false일 때)를 나타낸다. 읽기 전용 매개변수이다.

5.2.7 RTCRtpHeaderExtensionParameters 딕셔너리

WebIDLdictionary RTCRtpHeaderExtensionParameters {
  required DOMString uri;
  required unsigned short id;
  boolean encrypted = false;
};
Dictionary RTCRtpHeaderExtensionParameters Members
uri of type DOMString, required

[ RFC5285 ]에 정의된 RTP 헤더 확장의 URI이다. 읽기 전용 매개변수이다.

id of type unsigned short, required

헤더 확장을 식별하도록 RTP 패킷에 넣는 값이다. 읽기 전용 매개변수이다.

encrypted of type boolean

헤더 확장이 암호화되는지를 나타낸다. 읽기 전용 매개변수이다.

Note

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().headerExtensions와 transceiver.receiver.getParameters().headerExtensions에 모두 포함된다.
  4. inactive: 헤더 확장은 transceiver.sender.getParameters().headerExtensions와 transceiver.receiver.getParameters().headerExtensions 어느 쪽에도 포함되지 않는다.

5.2.8 RTCRtpCodec 딕셔너리

WebIDLdictionary RTCRtpCodec {
  required DOMString mimeType;
  required unsigned long clockRate;
  unsigned short channels;
  DOMString sdpFmtpLine;
};
Dictionary RTCRtpCodec Members

RTCRtpCodec 사전은 코덱 객체에 관한 정보를 제공한다.

mimeType of type DOMString, required

코덱의 MIME 미디어 유형/하위 유형이다. 유효한 미디어 유형과 하위 유형은 [ IANA-RTP-2 ]에 나열되어 있다.

clockRate of type unsigned long, required

헤르츠 단위로 표현한 코덱 클록 속도이다.

channels of type unsigned short

존재하면 최대 채널 수를 나타낸다(mono=1, stereo=2).

sdpFmtpLine of type DOMString

코덱에 대응하는 SDP의 a=fmtp 행이 존재하면 그 행의 "형식별 매개변수" 필드이며, [RFC9429] (section 5.8.)에 정의되어 있다.

5.2.9 RTCRtpCodecParameters 딕셔너리

WebIDLdictionary RTCRtpCodecParameters : RTCRtpCodec {
  required octet payloadType;
};
Dictionary RTCRtpCodecParameters Members

RTCRtpCodecParameters 사전은 협상된 코덱에 관한 정보를 제공한다. RTCRtpCodec에서 상속한 필드는 반드시 모두 읽기 전용 매개변수여야 한다.

RTCRtpSender의 sdpFmtpLine 매개변수는 [[CurrentRemoteDescription]] 에서 가져오며, RTCRtpReceiver의 경우 로컬 설명에서 가져온다. 로컬 설명은 [[PendingLocalDescription]]이 null이 아니면 그 값이고, 그렇지 않으면 [[CurrentLocalDescription]]이다.

payloadType of type octet, required

이 코덱을 식별하는 RTP 페이로드 유형이다. 읽기 전용 매개변수이다.

5.2.10 RTCRtpCapabilities 딕셔너리

WebIDLdictionary RTCRtpCapabilities {
  required sequence<RTCRtpCodec> codecs;
  required sequence<RTCRtpHeaderExtensionCapability> headerExtensions;
};
Dictionary RTCRtpCapabilities Members
codecs of type sequence<RTCRtpCodec>, required

지원되는 미디어 코덱과 RTX, RED 및 FEC 메커니즘의 항목이다. 생성된 SDP 제안에서 서로 다른 페이로드 유형을 사용하는 조합만 제공해야 한다. 예를 들어:

  1. 지원되는 두 packetization-mode 값 각각에 대해 하나씩, 두 개의 H.264/AVC 코덱.
  2. 클록 속도가 서로 다른 두 CN 코덱.

반드시 codecs에는 RTX를 통한 재전송 항목이 하나만 있어야 하며, 그 항목에는 sdpFmtpLine이 없어야 한다.

headerExtensions of type sequence<RTCRtpHeaderExtensionCapability>, required

지원되는 RTP 헤더 확장이다.

5.2.11 RTCRtpHeaderExtensionCapability 딕셔너리

WebIDLdictionary RTCRtpHeaderExtensionCapability {
  required DOMString uri;
};
Dictionary RTCRtpHeaderExtensionCapability Members
uri of type DOMString, required

[ RFC5285 ]에 정의된 RTP 헤더 확장의 URI이다.

5.2.12 RTCSetParameterOptions 딕셔너리

WebIDLdictionary RTCSetParameterOptions {
};
Dictionary RTCSetParameterOptions Members

RTCSetParameterOptions는 확장 가능성을 허용하도록 빈 사전으로 정의된다.

5.3 RTCRtpReceiver 인터페이스

RTCRtpReceiver 인터페이스는 애플리케이션이 MediaStreamTrack의 수신을 검사할 수 있도록 한다.

RTCRtpReceiver를 생성하는 절차를 문자열 kind으로 실행하려면 다음 단계를 실행한다:

  1. receiver를 새 RTCRtpReceiver 객체로 둔다.

  2. track을 새 MediaStreamTrack 객체로 둔다[ GETUSERMEDIA]. track의 소스는 원격 소스이며 receiver가 제공한다. track.id 는 사용자 에이전트가 생성하며 원격 측의 트랙 ID와는 대응하지 않는다.

  3. track.kind를 kind로 초기화한다.

  4. track.label을 문자열 "remote "와 kind을 이어 붙인 결과로 초기화한다.

  5. track.readyState를 live로 초기화한다.

  6. track.muted를 true로 초기화한다. MediaStreamTrack 절에서 muted 속성이 MediaStreamTrack의 미디어 데이터 수신 여부를 어떻게 반영하는지 참조한다.

  7. receiver에 [[ReceiverTrack]] 내부 슬롯을 두고 track로 초기화한다.

  8. receiver에 [[ReceiverTransport]] 내부 슬롯을 두고 null로 초기화한다.

  9. receiver에 [[LastStableStateReceiverTransport]] 내부 슬롯을 두고 null로 초기화한다.

  10. receiver에 [[AssociatedRemoteMediaStreams]] 내부 슬롯을 둔다. 이는 MediaStream 객체의 목록을 나타내며, 이 수신자의 MediaStreamTrack 객체와 연결된 스트림들이다. 이 슬롯은 빈 목록으로 초기화한다.

  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;
};

Attributes

track of type MediaStreamTrack, readonly

track 속성은 이 RTCRtpReceiver 객체 receiver와 연결된 트랙이다.

track.stop()은 되돌릴 수 없지만 복제본에는 영향을 주지 않는다. receiver.track.stop()은 receiver를 암묵적으로 중지하지 않으므로 수신자 보고서를 계속 보낸다. 값을 가져올 때 이 속성은 반드시 [[ReceiverTrack]] 슬롯의 값을 반환해야 한다.

transport of type RTCDtlsTransport, readonly, nullable

transport 속성은 수신자의 track에 대한 미디어를 RTP 패킷 형태로 받는 전송이다. RTCDtlsTransport 객체가 생성되기 전에는 transport 속성이 null이다. 번들링을 사용하면 여러 RTCRtpReceiver 객체가 하나의 transport 를 공유하며 모두 같은 전송으로 RTP와 RTCP를 받는다.

값을 가져올 때 이 속성은 반드시 [[ReceiverTransport]] 슬롯의 값을 반환해야 한다.

jitterBufferTarget of type DOMHighResTimeStamp, nullable

이 속성을 사용하면 애플리케이션은 RTCRtpReceiver의 지터 버퍼에 보관할 미디어의 목표 지속 시간을 밀리초 단위로 지정할 수 있다. 이는 사용자 에이전트가 수행하는 버퍼링의 양에 영향을 주며, 다시 재전송과 패킷 손실 복구에 영향을 준다. 애플리케이션은 목표값을 변경하여 재생 지연과 네트워크 지터로 인해 오디오 또는 비디오 프레임이 부족해질 위험 사이의 균형을 제어할 수 있다.

사용자 에이전트는 반드시 허용되는 최소 목표와 허용되는 최대 목표를 가져야 한다. 이 값들은 사용자 에이전트 가 네트워크 상태와 메모리 제약에 따라 제공할 수 있거나 제공하려는 범위를 반영하며, 언제든지 변경될 수 있다.

Note

이는 목표값이다. 그에 따른 지연 변화는 시간에 걸쳐 점진적으로 관찰할 수 있다. 수신자의 평균 지터 버퍼 지연은 jitterBufferDelay의 변화량을 jitterBufferEmittedCount의 변화량으로 나누어 측정할 수 있다.

DTX를 사용하더라도 평균 지연이 생길 것으로 예상된다. 예를 들어 DTX를 사용하며 무음 후에 패킷이 흐르기 시작하면, 목표값이 클수록 사용자 에이전트 가 이 패킷을 재생하는 대신 버퍼링하도록 영향을 줄 수 있다.

값을 가져올 때 이 속성은 반드시 [[JitterBufferTarget]] 내부 슬롯의 값을 반환해야 한다.

값을 설정할 때 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. receiver를 설정자가 호출된 RTCRtpReceiver 객체로 둔다.

  2. target를 설정자의 인수로 둔다.

  3. target이 음수이거나 4000밀리초보다 크면 예외를 던지는 절차로 RangeError를 던진다.

  4. receiver의 [[JitterBufferTarget]]를 target으로 설정한다.

  5. track을 receiver의 [[ReceiverTrack]]으로 둔다.

  6. 병렬로 다음 단계를 실행하기 시작한다:

    1. 기반 시스템에 새 target 을 알리거나, target이 null이면 애플리케이션의 선호가 없음을 알린다.

      track이 다른 RTCRtpReceiver 의 트랙과 오디오/비디오 동기화 를 위해 동기화되어 있으면, 사용자 에이전트는 가급적 두 수신자의 [[JitterBufferTarget]] 중 더 큰 값을 두 수신자 모두에 사용해야 한다.

      기반 시스템은 지터 버퍼 목표를 적용할 때 실제 지터 버퍼 목표가 허용되는 최소 목표와 허용되는 최대 목표 사이로 제한되도록 계속 보장한다.

      Note

      사용자 에이전트가 결과적으로 요청된 값과 다른 목표를 사용하더라도(예: 네트워크 상태나 물리적 메모리 제약 때문에), 이는 [[JitterBufferTarget]] 내부 슬롯에 반영되지 않는다.

    2. 기반 시스템의 지터 버퍼 목표를 변경하면 가급적 사용자 경험을 해치지 않도록 내부 오디오 또는 비디오 버퍼링에 점진적으로 영향을 주어야 한다. 오디오 샘플이나 비디오 프레임은 가급적 재생 전에 가속하거나 감속해야 하며, 이는 오디오/비디오 동기화 또는 혼잡 제어에 대응할 때와 비슷한 방식으로 수행한다.

      가속 또는 감속 속도는 네트워크 상태나 수신한 오디오의 종류(예: 음성 또는 배경 소음)에 따라 달라질 수 있다. 경우에 따라 1초 분량의 버퍼링을 달성하는 데 몇 초가 걸릴 수 있으나, 가급적 패킷을 수신하고 있다는 가정하에 30초를 넘기지 않아야 한다. 속도는 경우에 따라 오디오와 비디오에서 다를 수 있다.

      Note

      오디오의 가속과 감속은 insertedSamplesForDeceleration와 removedSamplesForAcceleration 으로 측정할 수 있다. 비디오에서는 같은 프레임을 여러 번 렌더링하거나 프레임을 버리는 결과가 생길 수 있다.

Methods

getCapabilities, static

정적 RTCRtpReceiver.getCapabilities() 메서드는 리소스, 포트 또는 다른 상태를 예약하지 않고도 사용자 에이전트가 주어진 종류의 미디어를 받기 위해 지원하는 기능의 종류를 알아내는 방법을 제공한다.

getCapabilities 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. kind를 메서드의 첫 번째 인수로 둔다.

  2. kind가 "video"도 "audio"도 아니면 null을 반환한다.

  3. 새 RTCRtpCapabilities 사전을 반환한다. 이때 codecs 멤버는 구현된 수신 코덱 목록 중 kind에 해당하는 목록으로 초기화하고, headerExtensions 멤버는 구현된 수신용 헤더 확장 목록 중 kind에 해당하는 목록으로 초기화한다.

구현된 수신 코덱 목록은 주어진 kind에 대해 구현 정의 방식으로 정해지는 RTCRtpCodec 사전의 목록이며, 주어진 kind(비디오 또는 오디오)의 미디어를 받기 위해 사용자 에이전트가 지원하는 코덱을 가장 낙관적으로 나타낸다.

구현된 수신용 헤더 확장 목록은 주어진 kind에 대해 구현 정의 방식으로 정해지는 RTCRtpHeaderExtensionCapability 사전의 목록이며, 주어진 kind(비디오 또는 오디오)의 미디어를 받기 위해 사용자 에이전트가 지원하는 헤더 확장을 낙관적으로 나타낸다.

이러한 기능은 일반적으로 오래 유지되며 출처를 넘어 이용할 수 있는 장치 정보를 제공하므로 애플리케이션의 핑거프린팅 가능 범위를 늘린다. 개인정보 보호에 민감한 상황에서 사용자 에이전트는 경우에 따라 기능의 공통 부분집합만 보고하는 등의 완화 조치를 고려할 수 있다. (This is a fingerprinting vector.)

Note

반환된 코덱 기능은 setCodecPreferences() 알고리즘과 이 알고리즘이 어떤 입력에 대해 InvalidModificationError를 던지는지에 영향을 준다. 개인정보 보호 완화 조치의 효과를 보장하려면, 이 정보는 createOffer()와 createAnswer()가 수신용으로 협상된 코덱에 관해 드러내는 정보와도 일관되어야 한다.

getParameters

getParameters() 메서드는 RTCRtpReceiver 객체의 현재 매개변수를 반환한다. 이는 track을 디코딩하는 방식에 관한 매개변수이다.

getParameters 가 호출되면 RTCRtpReceiveParameters 사전은 다음과 같이 구성된다:

  • headerExtensions 시퀀스는 수신자가 현재 수신할 준비가 된 헤더 확장을 바탕으로 채운다.
  • codecs 는 [[ReceiveCodecs]] 내부 슬롯의 값으로 설정한다.

    Note
    로컬 설명과 원격 설명은 모두 이 코덱 목록에 영향을 줄 수 있습니다. 예를 들어 세 코덱이 제안되면 수신자는 각 코덱을 받을 준비를 하며, 이들을 모두 반환하는 메서드는 getParameters입니다. 그러나 원격 엔드포인트가 둘만 포함해 응답하면, 빠진 코덱을 더 이상 반환하지 않는 메서드는 getParameters 입니다. 수신자가 그 코덱을 받을 준비를 할 필요가 없어졌기 때문입니다.
  • rtcp.reducedSize는 수신자가 현재 축소 크기 RTCP 패킷을 수신할 준비가 되어 있으면 true로, 그렇지 않으면 false로 설정한다. rtcp.cname는 생략한다.
getContributingSources

RTCRtpContributingSource를 각 고유 CSRC 식별자에 대해 반환한다. 이는 이 RTCRtpReceiver가 직전 10초 동안 수신한 식별자이며, timestamp의 내림차순으로 반환한다.

getSynchronizationSources

RTCRtpSynchronizationSource를 각 고유 SSRC 식별자에 대해 반환한다. 이는 이 RTCRtpReceiver가 직전 10초 동안 수신한 식별자이며, timestamp의 내림차순으로 반환한다.

getStats

이 수신자에 대해서만 통계를 수집하고 결과를 비동기적으로 보고한다.

getStats() 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. selector를 메서드가 호출된 RTCRtpReceiver 객체로 둔다.

  2. p를 새 프로미스로 두고 다음 단계를 병렬로 실행한다:

    1. selector가 나타내는 통계를 통계 선택 알고리즘에 따라 수집한다.

    2. 전역 태스크를 큐에 넣는다. 이 태스크의 소스는 네트워킹 태스크 소스이고, 현재 렐름의 전역 객체를 global로 사용한다. 태스크는 결정 절차로 p를 결정하며, 그 값은 수집한 통계를 포함하는 결과 RTCStatsReport 객체이다.

  3. p를 반환한다.

RTCRtpContributingSource와 RTCRtpSynchronizationSource 사전은 각각 주어진 기여 소스(CSRC) 또는 동기화 소스(SSRC)의 정보를 포함한다. 하나 이상의 RTP 패킷에서 나온 오디오 또는 비디오 프레임이 RTCRtpReceiver의 MediaStreamTrack에 전달되면, 사용자 에이전트는 반드시 태스크를 큐에 넣어 RTCRtpContributingSource와 RTCRtpSynchronizationSource 사전의 관련 정보를 해당 패킷 내용에 따라 갱신해야 한다. RTCRtpSynchronizationSource 사전 중 SSRC 식별자에 대응하는 관련 정보는 매번 갱신되며, RTP 패킷에 CSRC 식별자가 포함되어 있으면 RTCRtpContributingSource 사전 중 해당 CSRC 식별자들에 대응하는 관련 정보도 갱신한다. 사용자 에이전트는 반드시 RTP 타임스탬프의 오름차순으로 RTP 패킷을 처리해야 한다. 사용자 에이전트는 반드시 직전 10초 동안 RTCRtpReceiver의 MediaStreamTrack에 전달된 RTP 패킷의 정보를 보관해야 한다.

Note
설령 해당 트랙인 MediaStreamTrack 이 재생을 위한 어떤 싱크에도 연결되지 않은 경우에도, getSynchronizationSources 및 getContributingSources 는 트랙이 아직 종료되지 않은 상태인 동안 최신 정보를 반환한다. 싱크는 RTP 패킷을 디코딩하기 위해서 반드시 있어야 하는 전제조건이 아니다.
Note
이 사안에 관해서는 해당 적합성 절에 명시되어 있는 바와 같이, 알고리즘의 형태로 제시된 요구사항은 그것을 구현하는 방식이 무엇이든 최종적으로 얻는 결과가 서로 동등하다면 구현할 수 있다. 따라서 구현 과정에서 매 프레임을 처리할 때마다 실제로 태스크 하나를 큐에 넣는 작업까지 문자 그대로 수행해야 하는 것은 아니다. 다만 단일 이벤트 루프 태스크가 실행되는 동안에 반환되는 다음의 모든 RTCRtpSynchronizationSource 및 RTCRtpContributingSource 딕셔너리는 특정한 수신기 객체인 RTCRtpReceiver 에 대해서 RTP 스트림의 단일 시점에서 가져온 정보를 담아야 한다.
WebIDLdictionary RTCRtpContributingSource {
  required DOMHighResTimeStamp timestamp;
  required unsigned long source;
  double audioLevel;
  required unsigned long rtpTimestamp;
};

Dictionary RTCRtpContributingSource Members

timestamp of type DOMHighResTimeStamp, required

timestamp는 이 소스에서 발생한 RTP 패킷의 프레임이 가장 최근에 RTCRtpReceiver의 MediaStreamTrack에 전달된 시각을 나타낸다. timestamp 는 그 시점의 Performance.timeOrigin + Performance.now()로 정의한다.

source of type unsigned long, required

기여 소스 또는 동기화 소스의 CSRC 또는 SSRC 식별자이다.

audioLevel of type double

오디오 수신자에만 존재한다. 이는 0..1 사이의 선형 값이며, 1.0은 0 dBov를, 0은 무음을, 0.5는 0 dBov에서 음압 수준이 약 6 dBSPL만큼 변한 것을 나타낸다.

CSRC의 경우 이 값은 반드시 RFC 6465 헤더 확장이 존재하면 [ RFC6465 ]에 정의된 레벨 값에서 변환해야 하고, 그렇지 않으면 이 멤버는 반드시 없어야 한다.

SSRC의 경우 이 값은 반드시 [ RFC6464 ]에 정의된 레벨 값에서 변환해야 한다. 수신한 패킷에 RFC 6464 헤더 확장이 없으면(예: 다른 끝점이 사용자 에이전트가 아니거나 레거시 끝점인 경우), 이 값은 가급적 없어야 한다.

두 RFC 모두 시스템이 인코딩할 수 있는 가장 큰 신호를 기준으로 음수 데시벨로 표현한 오디오 레벨을 0부터 127까지의 정수 값으로 정의한다. 따라서 0은 시스템이 인코딩할 수 있는 가장 큰 신호를 나타내고, 127은 무음을 나타낸다.

이 값들을 선형 0..1 범위로 변환하려면 127은 0으로 변환하고 다른 모든 값은 10^(-rfc_level/20) 식으로 변환한다.

rtpTimestamp of type unsigned long, required

[ RFC3550 ] 5.1절에 정의된 RTP 타임스탬프로서, timestamp 시점에 재생된 미디어에 해당한다.

WebIDLdictionary RTCRtpSynchronizationSource : RTCRtpContributingSource {};

RTCRtpSynchronizationSource 사전은 SSRC에서만 사용할 수 있는 데이터를 명세가 노출하기 위한 확장 지점으로 사용될 것으로 예상된다.

5.4 RTCRtpTransceiver 인터페이스

RTCRtpTransceiver 인터페이스는 RTCRtpSender와 RTCRtpReceiver가 공통의 미디어 스트림 "identification-tag"를 공유하는 조합을 나타낸다. [RFC9429] (section 3.4.1.)에 정의된 대로, RTCRtpTransceiver는 다음 조건을 만족할 때 연결된 상태로 간주된다. 그 대상은 미디어 설명이며, 조건은 "mid" 속성이 null이 아니고 미디어 스트림 "identification-tag"와 일치하는 것이다. 이 태그는 해당 미디어 설명에 있어야 한다. 그렇지 않으면 해당 미디어 설명과 연결 해제된 것으로 간주한다.

Note

RTCRtpTransceiver는 현재 설명과는 계속 연결 해제된 상태인 채 RFC9429의 새 보류 중인 설명과 연결될 수 있다. 이는 협상이 필요한지 확인하는 절차에서 발생할 수 있다.

트랜시버 종류은 RTCRtpTransceiver 에 대해 연결된 RTCRtpReceiver의 MediaStreamTrack 객체의 종류로 정의된다.

RTCRtpTransceiver를 생성하는 절차를 RTCRtpReceiver 객체 receiver, RTCRtpSender 객체 sender 및 RTCRtpTransceiverDirection 값 direction으로 실행하려면 다음 단계를 실행한다:

  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] (section 5.2.1. and section 5.3.1.) 에 정의된 "RtpTransceiver mid property"이며 거기에서만 수정된다.

  12. transceiver에 [[Mid]] 내부 슬롯을 두고 null로 초기화한다.

  13. transceiver를 반환한다.

Note
트랜시버를 생성하는 동작만으로 다음의 기저 객체들이 생성되지는 않는다: RTCDtlsTransport 및 RTCIceTransport 객체. 이러한 객체들은 세션 설명을 설정하는 과정의 일부로만 생성된다. 해당 과정은 세션 설명 설정 처리.
WebIDL[Exposed=Window]
interface RTCRtpTransceiver {
  readonly attribute DOMString? mid;
  [SameObject] readonly attribute RTCRtpSender sender;
  [SameObject] readonly attribute RTCRtpReceiver receiver;
  attribute RTCRtpTransceiverDirection direction;
  readonly attribute RTCRtpTransceiverDirection? currentDirection;
  undefined stop();
  undefined setCodecPreferences(sequence<RTCRtpCodec> codecs);
};

Attributes

mid of type DOMString, readonly, nullable

mid 속성은 협상되어 로컬 및 원격 설명에 존재하는 미디어 스트림 "identification-tag"이다. 값을 가져올 때 이 속성은 반드시 [[Mid]] 슬롯의 값을 반환해야 한다.

sender of type RTCRtpSender, readonly

sender 속성은 RTCRtpSender를 노출하며, 이는 mid = [[Mid]]로 보낼 수 있는 RTP 미디어에 대응한다. 값을 가져올 때 이 속성은 반드시 [[Sender]] 슬롯의 값을 반환해야 한다.

receiver of type RTCRtpReceiver, readonly

receiver 속성은 RTCRtpReceiver이며, 이는 mid = [[Mid]]로 받을 수 있는 RTP 미디어에 대응한다. 값을 가져올 때 이 속성은 반드시 [[Receiver]] 슬롯의 값을 반환해야 한다.

direction of type RTCRtpTransceiverDirection

[RFC9429] (section 4.2.4.)에 정의된 대로, direction 속성은 이 트랜시버의 선호 방향을 나타내며, createOffer와 createAnswer 호출에 사용된다. 방향을 갱신해도 즉시 적용되지는 않는다. 대신 이후의 createOffer와 createAnswer 호출은 대응하는 미디어 설명을 sendrecv, sendonly, recvonly 또는 inactive 로 표시한다. 이는 [RFC9429] (section 5.2.2. and section 5.3.2.)에 정의되어 있다.

값을 가져올 때 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. transceiver를 getter가 호출된 RTCRtpTransceiver 객체로 둔다.

  2. transceiver.[[Stopping]]가 true이면 " stopped"을 반환한다.

  3. 그렇지 않으면 [[Direction]] 슬롯의 값을 반환한다.

값을 설정할 때 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. transceiver를 설정자가 호출된 RTCRtpTransceiver 객체로 둔다.

  2. connection를 RTCPeerConnection 객체로 두며, 이 객체는 transceiver와 연결되어 있다.

  3. transceiver.[[Stopping]]가 true이면 예외를 던지는 절차로 InvalidStateError를 던진다.

  4. newDirection를 설정자의 인수로 둔다.

  5. newDirection이 transceiver.[[Direction]]와 같으면 이 단계들을 중단한다.

  6. newDirection이 " stopped"와 같으면 예외를 던지는 절차로 TypeError를 던진다.

  7. transceiver.[[Direction]]를 newDirection로 설정한다.

  8. 협상 필요 플래그를 갱신하는 절차를 connection에 대해 실행한다.

currentDirection of type RTCRtpTransceiverDirection, readonly, nullable

[RFC9429] (section 4.2.5.)에 정의된 대로, currentDirection 속성은 이 트랜시버에 대해 현재 협상된 방향을 나타낸다. currentDirection의 값은 RTCRtpEncodingParameters.active의 값과 독립적이며, 한쪽에서 다른 쪽을 추론할 수 없다. 이 트랜시버가 제안/응답 교환에 한 번도 나타나지 않았으면 값은 null이다. 트랜시버가 stopped 상태이면 값은 "stopped"이다.

값을 가져올 때 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. transceiver를 getter가 호출된 RTCRtpTransceiver 객체로 둔다.

  2. transceiver.[[Stopped]]가 true이면 " stopped"을 반환한다.

  3. 그렇지 않으면 [[CurrentDirection]] 슬롯의 값을 반환한다.

Methods

stop

트랜시버를 stopping 상태로 되돌릴 수 없게 표시한다. 단, 이미 stopped 상태이면 수행하지 않는다. 이로 인해 트랜시버의 송신자는 즉시 전송을 중단하고 수신자는 즉시 수신을 중단한다. stop() 호출은 협상 필요 플래그를 갱신하는 절차도 수행하며, 그 대상은 RTCRtpTransceiver 와 연결된 RTCPeerConnection이다.

중지 중 상태인 트랜시버가 있으면 이후의 createOffer 호출은 대응하는 트랜시버의 미디어 설명 에서 포트를 0으로 생성한다. 이는 [RFC9429] (section 4.2.1.)에 정의되어 있다(사용자 에이전트는 반드시 이 경우에만 RFC9429의 목적상 stopping 상태인 트랜시버를 stopped 상태로 취급해야 한다). 그러나 [ RFC8843 ]와 관련된 문제를 피하기 위해, stopping 상태이지만 stopped 상태가 아닌 트랜시버는 createAnswer에 영향을 주지 않는다.

중지됨 상태인 트랜시버가 있으면 이후 createOffer 또는 createAnswer 호출은 대응하는 트랜시버의 미디어 설명 에서 포트를 0으로 생성한다. 이는 [RFC9429] (section 4.2.1.)에 정의되어 있다.

트랜시버는 stopping 상태를 유지한다. 단, stopped 상태가 되면 그렇지 않으며, 이는 setRemoteDescription가 원격 제안 또는 응답에서 거부된 m행을 처리한 결과이다.

Note

stopping 상태이지만 stopped 상태가 아닌 트랜시버에는 항상 협상이 필요하다. 실제로 이는 트랜시버에서 stop()을 호출하면, 양쪽 끝에서 협상이 완료되도록 허용되는 한 해당 트랜시버가 결국 stopped 상태가 된다는 뜻이다.

stop 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. transceiver를 메서드가 호출된 RTCRtpTransceiver 객체로 둔다.

  2. connection를 RTCPeerConnection 객체로 두며, 이 객체는 transceiver와 연결되어 있다.

  3. connection.[[IsClosed]]가 true이면 예외를 던지는 절차로 InvalidStateError를 던진다.

  4. transceiver.[[Stopping]]가 true이면 이 단계들을 중단한다.

  5. 송수신을 중단하는 절차를 transceiver로 실행한다.

  6. 협상 필요 플래그를 갱신하는 절차를 connection에 대해 실행한다.

송수신을 중단하는 알고리즘은 transceiver 및 선택적인 불리언 disappear를 입력으로 받으며 기본값은 false이다. 알고리즘은 다음과 같다:

  1. sender를 transceiver.[[Sender]]로 둔다.

  2. receiver를 transceiver.[[Receiver]]로 둔다.

  3. 병렬로 sender 의 미디어 전송을 중단하고 sender가 보내던 각 RTP 스트림에 대해 [ RFC3550 ]에 지정된 대로 RTCP BYE를 보낸다.

  4. 병렬로 receiver의 미디어 수신을 중단한다.

  5. disappear가 false 이면 receiver.[[ReceiverTrack]]을 종료된 상태로 만드는 단계를 실행한다. 이로 인해 이벤트가 발생한다.

  6. transceiver.[[Direction]]를 "inactive"로 설정한다.

  7. transceiver.[[Stopping]]를 true로 설정한다.

RTCRtpTransceiver를 중지하는 알고리즘은 transceiver 및 선택적인 불리언 disappear를 입력으로 받으며 기본값은 false이다. 알고리즘은 다음과 같다:

  1. transceiver.[[Stopping]]이 false이면 송수신을 중단하는 절차를 transceiver와 disappear로 실행한다.

  2. transceiver.[[Stopped]]를 true로 설정한다.

  3. transceiver.[[Receptive]]를 false로 설정한다.

  4. transceiver.[[CurrentDirection]]를 null로 설정한다.

setCodecPreferences
Candidate Addition 51:setCodecPreferences supports both send and receive codecs (filtered by direction) (PR #3018)

setCodecPreferences 메서드는 사용자 에이전트가 사용하는 협상 입력용 기본 코덱 선호를 재정의한다. 세션 설명을 생성할 때 사용하는 메서드가 createOffer 또는 createAnswer 이면, 사용자 에이전트는 반드시 반드시 지정된 코덱을 선호 코덱을 direction에 따라 필터링해야 하며 그 결과가 비어 있지 않은 목록이면 반드시 지정된 코덱을 codecs 인수의 순서대로, 미디어 섹션 섹션 중 이 이 RTCRtpTransceiver에 대응하는 섹션에서 사용해야 한다.

이 메서드는 특정 코덱(RTX/RED/FEC 포함)의 협상을 비활성화할 수 있게 한다. 또한 원격 피어가 목록의 첫 번째 코덱을 선호하도록 할 수 있으며, 그 용도는 다음과 같다. 이를 위해 모든 코덱을 나열하되 다음은 제외한다: 송신비활성화할 코덱.

Note

m= 섹션을 수신에 사용하면 SDP(제안과 응답 모두)에 나열된 코덱의 순서는 로컬 끝점이 어떤 코덱으로 수신하기를 선호하는지 원격 끝점에 알려 준다. m= 섹션을 수신에 사용하지 않더라도, 자체적인 코덱 선호가 없는 응답자는 기본적으로 SDP 응답에 같은 순서를 사용한다.

Note

RTCRtpSender는 기본적으로 원격 끝점이 수신하기를 선호한다고 나타낸 코덱으로 보내지만, 애플리케이션은 협상된 codecs 중에서 송신할 코덱을 변경할 수 있다. 이를 위해 setParameters를 호출하여 송신할 codec을 지정한다. RTCRtpReceiver 는 협상된 모든 코덱을 수신할 준비가 되어 있다.

코덱 선호는 createOffer와 createAnswer 중 이 RTCRtpTransceiver를 포함하는 모든 호출에 대해 이 메서드를 다시 호출할 때까지 유지된다. codecs를 빈 시퀀스로 설정하면 코덱 선호가 시퀀스 또는 direction에 따라 필터링한 뒤 비게 되는 시퀀스로 설정하면 기본 값으로 재설정된다코덱 선호가 적용된다.

Note

코덱의 페이로드 유형은 SDP의 각 m= 섹션 아래에 나열되어 페이로드 유형과 코덱 사이의 매핑을 정의한다. 이 페이로드 유형은 m=video 또는 m=audio 행에서 선호 순서대로 참조되며, 협상되지 않은 코덱은 [ RFC8829RFC9429 ] 5.2.1절에 정의된 대로 이 목록에 나타나지 않는다. 이전에 협상되었다가 제거된 코덱은 m=video 또는 m=audio 행에서 사라진다. 해당 코덱 페이로드 유형은 이후 제안이나 응답에서 재사용해서는 안 되며, 그 페이로드 유형을 SDP의 페이로드 유형 매핑에서도 제거할 수 있다.

codecs 시퀀스를 입력으로 받는 setCodecPreferences 는 이 시퀀스에 다음 코덱만 허용한다. 는 codecs를 설정할 때 다음 코덱과 일치하지 않는 입력을 거부한다. 해당 코덱을 반환하는 API는 다음과 같다: 비교할 코덱은 다음 API 중 하나에 있는 항목이다: RTCRtpSender.getCapabilities(kind) 또는 RTCRtpReceiver.getCapabilities(kind). 여기서 kind는 RTCRtpTransceiver 의 종류이며, 이 객체에서 메서드가 호출된다. 또한 RTCRtpCodecCapability 사전 멤버는 수정할 수 없다. codecs가 이 요건을 충족하지 않으면 사용자 에이전트는 반드시 예외를 던지는 절차로 InvalidModificationError를 던져야 한다.

Note

[ SDP]의 권고에 따라 createAnswer 호출은 가급적 코덱 선호 목록과 제안에 나타난 코덱의 공통 부분집합만 사용해야 한다. 예를 들어 코덱 선호가 "C, B, A"이지만 "A, B" 코덱만 제안되었다면 응답에는 "B, A" 코덱만 포함하는 것이 좋다. 그러나 [RFC8829] (section 5.3.1.)은 제안에 없던 코덱을 추가하는 것을 허용하므로 구현에 따라 다르게 동작할 수 있다.

setCodecPreferences() 가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. transceiver를 이 메서드가 호출된 RTCRtpTransceiver 객체로 둔다.

  2. codecs를 첫 번째 인수로 둔다.

  3. codecs가 빈 목록이면 transceiver.[[PreferredCodecs]]를 codecs로 설정하고 이 단계들을 중단한다.

  4. codecs에서 중복 값을 모두 제거한다. 코덱의 우선순위를 유지하도록 목록의 뒤에서부터 시작한다. 목록에서 코덱이 처음 나타나는 인덱스는 이 단계 전후에 동일하다.

  5. 중복된 값을 codecs에서 제거하되 각 값이 처음 나타나는 위치는 유지하도록 한다.

  6. kind를 transceiver의 트랜시버 종류로 둔다.

  7. codecs와 RTCRtpSender.getCapabilities(kind).codecs의 교집합 또는 codecs와 RTCRtpReceiver.getCapabilities(kind).codecs의 교집합이 RTX, RED 또는 FEC 코덱만 포함하거나 공집합이면 InvalidModificationError 를 던진다. 이로써 transceiver.direction과 관계없이 항상 제안할 항목이 있도록 보장한다.

  8. codecCapabilities를 RTCRtpSender.getCapabilities(kind).codecs와 RTCRtpReceiver.getCapabilities(kind).codecs의 합집합으로 둔다.

  9. 각 codec에 대해, codecs에 속하는 항목마다 다음을 수행한다:

    1. codec이 codecCapabilities에 없으면 InvalidModificationError를 던진다.
  10. 각 codec에 대해, codecs에 속하는 항목마다 다음을 수행한다:

    1. codec의 불일치 조건이 codecCapabilities의 모든 코덱에 대해 성립하면 InvalidModificationError를 던진다.

  11. codecs가 RTX, RED, FEC 또는 Comfort Noise 항목만 포함하거나 공집합이면 InvalidModificationError 를 던진다. 이로써 transceiver.direction과 관계없이 항상 제안할 항목이 있도록 보장한다.

  12. transceiver.[[PreferredCodecs]]를 codecs로 설정한다.

코덱 사전 일치 알고리즘은 두 RTCRtpCodec 사전 first와 second 및 불리언 ignoreLevels를 입력으로 받는다. 이 불리언은 지정되지 않으면 기본값이 false이다. 알고리즘은 다음과 같다:

  1. first.mimeType가 ASCII 대소문자 비구분 비교로 second.mimeType와 일치하지 않으면 false를 반환한다.

  2. first.clockRate 가 second.clockRate와 다르면 false를 반환한다.

  3. first.channels와 second.channels 중 한쪽만 누락 상태이거나, 둘 다 존재하고 first.channels가 second.channels와 다르면 false를 반환한다.

  4. first.sdpFmtpLine와 second.sdpFmtpLine 중 한쪽만 누락 상태이면 false를 반환한다.

  5. first.sdpFmtpLine와 second.sdpFmtpLine가 모두 존재하면 다음 단계를 실행한다:

    1. first.sdpFmtpLine와 second.sdpFmtpLine 중 하나라도 키-값 형식이 아니면 first.sdpFmtpLine와 second.sdpFmtpLine의 동등 비교 결과를 반환한다.

    2. firstMediaFormat을 first.sdpFmtpLine에서 구성한 미디어 형식의 키-값 맵으로 두고, secondMediaFormat을 second.sdpFmtpLine에서 구성한 미디어 형식의 키-값 맵으로 둔다.

      Note

      어떤 FMTP 매개변수가 미디어 형식을 구성하는지는 코덱에 따라 다르다. 경우에 따라 매개변수를 생략해도 추론할 수 있으며, 이때 해당 매개변수도 그 코덱의 미디어 형식에 포함된다.

    3. firstMediaFormat이 secondMediaFormat과 같지 않으면 false를 반환한다.

    4. Candidate Correction 52:Two codecs are considered the same even if level-id is not (PR #3023)

      ignoreLevels가 false 이고 first.sdpFmtpLine와 second.sdpFmtpLine에서 추론한 최대 적합 비트스트림 레벨이 다르면 false를 반환한다.

      Note

      ignoreLevels가 true 이어도 일부 코덱(예: H.264)은 미디어 형식에 레벨을 포함하므로, 레벨을 무시하려면 코덱별 파싱이 필요하다.

  6. true를 반환한다.

Note

설정되어 있으면 제안자의 수신 코덱 선호가 제안에 나열되는 코덱의 순서를 결정한다. 응답자에게 코덱 선호가 없으면 응답에도 같은 순서를 사용한다. 그러나 응답자에게도 코덱 선호가 있으면 그 선호가 응답의 순서를 재정의한다. 이 경우 제안자의 선호는 어떤 코덱을 제안하는지에는 영향을 주지만 최종 순서에는 영향을 주지 않는다.

5.4.1 동시 전송 기능

동시 송출 기능은 addTransceiver 메서드의 sendEncodings 인수 또는 동시 송출을 수신하겠다는 원격 제안을 사용하는 setRemoteDescription 메서드로 활성화한다. 두 메서드는 모두 RTCPeerConnection 객체의 메서드이다. 또한 각 setParameters 메서드를 해당 RTCRtpSender 객체에서 사용하여 이 기능을 확인하고 수정할 수 있다.

RTCRtpSender의 동시 송출 엔벌로프 는 해당 송신자가 유니캐스트 대신 동시 송출을 수행하는 최초의 성공적인 협상에서 설정된다. 여기에는 보낼 수 있는 동시 송출 스트림의 최대 수와 encodings의 순서가 포함된다. 이 동시 송출 엔벌로프는 이후 재협상에서 좁힐 수 있지만(계층 수를 줄임), 다시 넓힐 수는 없다. 개별 동시 송출 스트림의 특성은 setParameters 메서드로 수정할 수 있지만 동시 송출 엔벌로프 자체는 이 메서드로 변경할 수 없다.

동시 송출을 구성하는 한 가지 방법은 sendEncodings 옵션을 addTransceiver() 에 사용하는 것이다. addTrack() 메서드에는 동시 송출 구성에 필요한 sendEncodings 인수가 없지만, 사용자 에이전트가 응답자이면 송신자를 동시 송출로 승격할 수 있다. setRemoteDescription 메서드를 동시 송출을 수신하겠다는 원격 제안으로 호출하면, 제안된 엔벌로프 를 RTCRtpSender에 구성하여 지정된 세션 설명의 계층들을 포함시킨다. 이 설명이 롤백되지 않는 한 제안된 엔벌로프는 협상이 완료될 때 RTCRtpSender의 동시 송출 엔벌로프가 된다. 앞서 설명한 대로 이 동시 송출 엔벌로프는 이후 재협상에서 좁힐 수 있지만 다시 넓힐 수는 없다.

Candidate Correction 12:Mark RTP Pause/Resume as not supported (PR #2755)

setParameters 는 동시 송출 동시 송출 엔벌로프를 변경할 수 없지만,, 보내는 스트림의 수와 해당 스트림들의 특성은 여전히 제어할 수 있다. setParameters를 사용하여 동시 송출 스트림의 active 멤버를 false로 설정하면 비활성화할 수 있고, active 멤버를 true로 설정하면 다시 활성화할 수 있다. [ RFC7728](RTP 일시 중지/재개)는 지원하지 않으며, SDP 제안/응답을 통한 일시 중지/재개 시그널링도 지원하지 않는다. setParameters를 사용하여 스트림의 특성을 변경할 수 있으며, 이를 위해 maxBitrate 같은 속성을 수정한다.

Note

동시 송출은 여러 인코딩을 SFU에 보내는 데 자주 사용되며, SFU는 그중 하나의 동시 송출 스트림을 최종 사용자에게 전달한다. 따라서 사용자 에이전트는 모든 동시 송출 스트림이 각각 독립적으로 사용 가능하도록 인코딩 간에 대역폭을 할당할 것으로 예상된다. 예를 들어 두 동시 송출 스트림의 maxBitrate가 같다면 두 스트림의 비트레이트도 비슷할 것으로 예상된다. 모든 동시 송출 스트림을 사용 가능한 형태로 보내기에 대역폭이 부족하면, 사용자 에이전트는 일부 동시 송출 스트림의 전송을 중단할 것으로 예상된다.

[RFC9429] (section 3.7.) 에 정의된 대로, 사용자 에이전트의 제안은 a=simulcast 행에 "send" 설명만 포함하고 "recv" 설명은 포함하지 않는다. 대안과 제한([ RFC8853 ]에 설명됨)은 지원하지 않는다.

이 명세는 createOffer, createAnswer 또는 addTransceiver로 여러 RTP 인코딩의 수신을 구성하는 방법을 정의하지 않는다. 그러나 setRemoteDescription 이 [RFC9429]에 정의된 대로 여러 RTP 인코딩을 보낼 수 있는 대응하는 원격 설명으로 호출되고 브라우저가 여러 RTP 인코딩의 수신을 지원하면, RTCRtpReceiver 는 여러 RTP 인코딩을 수신할 수 있으며 트랜시버의 receiver.getParameters()로 가져온 매개변수는 협상된 인코딩을 반영한다.

Note

RTCRtpReceiver는 선택적 전달 장치(SFU)가 사용자 에이전트에서 받은 동시 송출 스트림을 전환하는 상황에서 여러 RTP 스트림을 수신할 수 있다. SFU가 전달 전에 전환된 스트림들을 하나의 RTP 스트림으로 정리하도록 RTP 헤더를 다시 쓰지 않으면, RTCRtpReceiver는 각각 자체 SSRC와 시퀀스 번호 공간을 가진 서로 다른 RTP 스트림의 패킷을 받는다. SFU는 어느 시점에서든 하나의 RTP 스트림만 전달할 수 있지만, 순서가 바뀌면서 여러 RTP 스트림의 패킷이 수신자에서 뒤섞일 수 있다. 따라서 여러 RTP 스트림을 수신할 수 있는 RTCRtpReceiver는 받은 패킷을 올바른 순서로 정렬하고 잠재적인 손실 사건을 인식하여 대응할 수 있어야 한다. 이 상황에서 올바르게 동작하는 것은 간단하지 않으므로 이 명세의 구현에서 선택 사항이다.

5.4.1.1 인코딩 매개변수 예제

이 절은 비규범적이다.

인코딩 매개변수로 구현한 동시 송출 시나리오의 예:

// Example of 3-layer spatial simulcast with all but the lowest resolution layer disabled
var encodings = [
  {rid: 'q', active: true, scaleResolutionDownBy: 4.0}
  {rid: 'h', active: false, scaleResolutionDownBy: 2.0},
  {rid: 'f', active: false},
];

5.4.2 "보류" 기능

이 절은 비규범적이다.

direction 속성과 replaceTrack 메서드를 함께 사용하면 개발자가 "보류" 시나리오를 구현할 수 있다.

피어에게 음악을 보내고 수신한 오디오의 렌더링을 중단하려면(통화 보류 음악):

async function playMusicOnHold() {
  try {
    // Assume we have an audio transceiver and a music track named musicTrack
    await audio.sender.replaceTrack(musicTrack);
    // Mute received audio
    audio.receiver.track.enabled = false;
    // Set the direction to send-only (requires negotiation)
    audio.direction = 'sendonly';
  } catch (err) {
    console.error(err);
  }
}

원격 피어의 "sendonly" 제안에 응답하려면:

async function handleSendonlyOffer() {
  try {
    // Apply the sendonly offer first,
    // to ensure the receiver is ready for ICE candidates.
    await pc.setRemoteDescription(sendonlyOffer);
    // Stop sending audio
    await audio.sender.replaceTrack(null);
    // Align our direction to avoid further negotiation
    audio.direction = 'recvonly';
    // Call createAnswer and send a recvonly answer
    await doAnswer();
  } catch (err) {
    // handle signaling error
  }
}

음악 전송을 중단하고 마이크에서 캡처한 오디오를 보내며 수신한 오디오도 렌더링하려면:

async function stopOnHoldMusic() {
  // Assume we have an audio transceiver and a microphone track named micTrack
  await audio.sender.replaceTrack(micTrack);
  // Unmute received audio
  audio.receiver.track.enabled = true;
  // Set the direction to sendrecv (requires negotiation)
  audio.direction = 'sendrecv';
}

원격 피어가 통화 보류를 해제한 것에 응답하려면:

async function onOffHold() {
  try {
    // Apply the sendrecv offer first, to ensure receiver is ready for ICE candidates.
    await pc.setRemoteDescription(sendrecvOffer);
    // Start sending audio
    await audio.sender.replaceTrack(micTrack);
    // Set the direction sendrecv (just in time for the answer)
    audio.direction = 'sendrecv';
    // Call createAnswer and send a sendrecv answer
    await doAnswer();
  } catch (err) {
    // handle signaling error
  }
}

5.5 RTCDtlsTransport 인터페이스

RTCDtlsTransport 인터페이스는 RTCRtpSender와 RTCRtpReceiver 객체가 RTP 및 RTCP 패킷을 보내고 받으며, 데이터 채널의 SCTP 패킷 같은 다른 데이터도 보내고 받는 데이터그램 전송 계층 보안(DTLS) 전송에 관한 정보에 애플리케이션이 접근할 수 있도록 한다. 특히 DTLS는 기반 전송에 보안을 추가하며, RTCDtlsTransport 인터페이스는 기반 전송과 추가된 보안에 관한 정보에 접근할 수 있도록 한다. RTCDtlsTransport 객체는 setLocalDescription()과 setRemoteDescription() 호출의 결과로 생성된다. 각 RTCDtlsTransport 객체는 RTP 또는 RTCP component의 DTLS 전송 계층을 나타낸다. 이는 특정 RTCRtpTransceiver에 속하거나, 여러 RTCRtpTransceiver의 그룹이 [RFC8843]을 통해 협상되었다면 그 그룹에 속한다.

Note
여기서 표현할 대상은 새로운 DTLS 연결이며, 기존의 RTCRtpTransceiver 에 대한 연결을 표현하는 객체는 기존 RTCDtlsTransport 객체이며, 해당 state 는 그 연결에 따라 갱신되며, 이때 새 객체를 만들어 연결을 표현하는 것은 아니다.

RTCDtlsTransport에는 [[DtlsTransportState]] 내부 슬롯이 있으며 "new"로 초기화한다. 또한 [[RemoteCertificates]] 슬롯이 있으며 빈 목록으로 초기화한다.

기반 DTLS 전송에서 인증서 검증 실패나 치명적 경고([RFC5246 ] 7.2절 참조) 같은 오류가 발생하면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. transport를 상태 갱신과 오류 알림을 받을 RTCDtlsTransport 객체로 둔다.

  2. transport의 상태가 이미 " failed"이면 이 단계들을 중단한다.

  3. transport.[[DtlsTransportState]]를 "failed"로 설정한다.

  4. 이벤트를 발생시킨다. 이름은 error이며 RTCErrorEvent 인터페이스를 사용하고, errorDetail 속성은 적절하게 "dtls-failure" 또는 "fingerprint-failure "로 설정한다. 다른 필드는 RTCErrorDetailType 열거형의 설명에 지정된 대로 설정하며, 이벤트의 대상은 transport이다.

  5. 이벤트를 발생시킨다. 이름은 statechange이며 대상은 transport이다.

다른 이유로 기반 DTLS 전송이 대응하는 RTCDtlsTransport 객체의 상태를 갱신해야 하면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. transport를 상태 갱신을 받을 RTCDtlsTransport 객체로 둔다.

  2. newState를 새 상태로 둔다.

  3. transport.[[DtlsTransportState]]를 newState로 설정한다.

  4. newState가 connected이면 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;
};

Attributes

iceTransport of type RTCIceTransport, readonly

iceTransport 속성은 패킷을 보내고 받는 데 사용하는 기반 전송이다. 기반 전송은 여러 활성 RTCDtlsTransport 객체 사이에서 공유될 수 없다.

state of type RTCDtlsTransportState, readonly

state 속성은 반드시 값을 가져올 때 [[DtlsTransportState]] 슬롯의 값을 반환해야 한다.

onstatechange of type EventHandler
이 이벤트 핸들러의 이벤트 유형은 statechange이다.
onerror of type EventHandler
이 이벤트 핸들러의 이벤트 유형은 error이다.

Methods

getRemoteCertificates

[[RemoteCertificates]]의 값을 반환한다.

5.5.1 RTCDtlsTransportState 열거형

WebIDLenum RTCDtlsTransportState {
  "new",
  "connecting",
  "connected",
  "closed",
  "failed"
};
RTCDtlsTransportState Enumeration description
Enum value Description
new DTLS has not started negotiating yet.
connecting DTLS는 보안 연결을 협상하는 과정에 있으며 원격 측의 지문을 검증하는 절차도 진행 하고 있는 상태이다.
connected DTLS는 보안 연결 을 위한 협상 을 완료하였으며 원격 측의 지문도 검증한 상태이다.
closed 전송은 close_notify 경고 를 수신한 결과 또는 다음 메서드 를 호출한 결과 로 의도적 으로 닫힌 상태이다: close().
failed 전송은 오류 때문 에 실패한 상태이다. 예를 들면 오류 경고 를 수신한 경우나 원격 측의 지문 을 검증하지 못한 경우 가 이에 해당 한다.

5.5.2 RTCDtlsFingerprint 딕셔너리

RTCDtlsFingerprint 사전은 [ RFC4572 ]에 설명된 해시 함수 알고리즘과 인증서 지문을 포함한다.

WebIDLdictionary RTCDtlsFingerprint {
  DOMString algorithm;
  DOMString value;
};
Dictionary RTCDtlsFingerprint Members
algorithm of type DOMString

'Hash function Textual Names' 레지스트리 [ IANA-HASH-FUNCTION ]에 정의된 해시 함수 알고리즘 중 하나이다.

value of type DOMString

[ RFC4572 ] 5절의 'fingerprint' 문법을 사용하여 표현한 소문자 16진수 문자열 형식의 인증서 지문 값이다.

5.6 RTCIceTransport 인터페이스

RTCIceTransport 인터페이스는 패킷을 보내고 받는 ICE 전송에 관한 정보에 애플리케이션이 접근할 수 있도록 한다. 특히 ICE는 애플리케이션이 접근하려는 상태를 포함하는 피어 간 연결을 관리한다. RTCIceTransport 객체는 setLocalDescription()과 setRemoteDescription() 호출의 결과로 생성된다. 기반 ICE 상태는 ICE 에이전트가 관리한다. 따라서 RTCIceTransport의 상태는 아래에 설명된 대로 ICE 에이전트가 사용자 에이전트에 알림을 제공할 때 바뀐다. 각 RTCIceTransport 객체는 RTP 또는 RTCP component의 ICE 전송 계층을 나타낸다. 이는 특정 RTCRtpTransceiver에 속하거나, 여러 RTCRtpTransceiver의 그룹이 [RFC8843]을 통해 협상되었다면 그 그룹에 속한다.

Note
여기서 표현할 대상은 ICE 재시작이며, 기존의 RTCRtpTransceiver 에 대한 재시작을 표현하는 객체는 기존 RTCIceTransport 객체이며, 해당 state 는 그 재시작에 따라 갱신되며, 이때 새 객체를 만들어 재시작을 표현하는 것은 아니다.
Candidate Correction 24:Queue two tasks upon finishing ICE gathering, and fire gatheringstatechange & icegatheringstatechange in same task (PR #2894)

ICE 에이전트가 후보 세대의 수집을 시작했다고 알리고 그 대상이 RTCIceTransport transport(연결된 객체: RTCPeerConnection connection)이면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. connection를 이 객체와 연결된 RTCPeerConnection 객체로 둔다. 이때 이 객체는 ICE 에이전트이다.

  2. connection.[[IsClosed]]가 true이면 이 단계들을 중단한다.

  3. transport를 후보 수집이 시작된 RTCIceTransport로 둔다.

  4. transport.[[IceGathererState]]를 gathering로 설정한다.

    .

  5. connection.[[IceGatheringState]]를 RTCIceGatheringState 열거형의 설명에 따라 새 상태 값을 도출한 값으로 설정한다.

  6. connectionIceGatheringStateChanged를 true로 두되, 이는 connection.[[IceGatheringState]]가 이전 단계에서 바뀐 경우이다. 그렇지 않으면 false로 둔다.

  7. 이 지점 이후에는 상태를 읽거나 변경하지 않는다.

  8. 이벤트를 발생시킨다. 이름은 gatheringstatechange이며 대상은 transport이다.

  9. ICE 수집 상태를 갱신하는 절차를 connection에 대해 수행한다.

  10. connectionIceGatheringStateChanged가 true이면 이벤트를 발생시키는. 이름은 icegatheringstatechange이며 대상은 connection이다.

ICE 에이전트가 후보 세대의 수집을 완료하고 그 대상이 RTCIceTransport transport(연결된 객체: RTCPeerConnection connection)이며 해당 후보들이 애플리케이션에 노출되었으면, 사용자 에이전트는 반드시 다음 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. connection를 이 객체와 연결된 RTCPeerConnection 객체로 둔다. 이때 이 객체는 ICE 에이전트이다.

  2. connection.[[IsClosed]]가 true이면 이 단계들을 중단한다.

  3. transport를 후보 수집이 완료된 RTCIceTransport로 둔다.

  4. connection.[[PendingLocalDescription]]가 null이 아니고 수집이 완료된 ICE 세대를 나타내면, a=end-of-candidates를 connection.[[PendingLocalDescription]].sdp에 추가한다.

  5. connection.[[CurrentLocalDescription]]가 null이 아니고 수집이 완료된 ICE 세대를 나타내면, a=end-of-candidates를 connection.[[CurrentLocalDescription]].sdp에 추가한다.

  6. newCandidateendOfGatheringCandidate를 RTCIceCandidate를 생성하는 절차의 결과로 둔다. 이때 새 사전의 sdpMid와 sdpMLineIndex는 다음 객체와 연결된 값으로 설정한다: 이 RTCIceTransport. usernameFragment 는 후보 수집을 완료한 세대의 사용자 이름 조각으로 설정하고, candidate는 빈 문자열""로 설정한다.

  7. 이벤트를 발생시킨다. 이름은 icecandidate이고 RTCPeerConnectionIceEvent 인터페이스를 사용하며 candidate 속성은 newCandidateendOfGatheringCandidate로 설정한다. 대상은 connection이다.

  1. 다른 세대의 후보를 아직 수집 중이면 이 단계들을 중단한다.

    Note
    이 현상은 ICE 에이전트가 이전 세대의 후보를 아직 수집하고 있는 동안 ICE 재시작이 시작되면 발생할 수 있습니다.
  2. transport.[[IceGathererState]]를 complete로 설정한다.

  3. 이벤트를 발생시킨다. 이름은 gatheringstatechange이며 대상은 transport이다.

  4. ICE 수집 상태를 갱신하는 절차를 connection에 대해 수행한다.

ICE 에이전트가 위의 태스크를 큐에 넣었고 다른 세대의 후보를 수집하고 있지 않으면, 사용자 에이전트는 반드시 다음 단계를 실행하는 두 번째 태스크도 큐에 넣어야 한다:

Note
다른 세대 의 후보가 여전히 수집 중일 수도 있다. 이는 ICE 재시작이 시작될 당시 해당 ICE 에이전트가 여전히 수집하던 후보들의 세대가 바로 이전 세대 였던 경우이다.
  1. connection.[[IsClosed]]가 true이면 이 단계들을 중단한다.

  2. transport.[[IceGathererState]]를 complete로 설정한다.

  3. connection.[[IceGatheringState]]를 RTCIceGatheringState 열거형의 설명에 따라 새 상태 값을 도출한 값으로 설정한다.

  4. connectionIceGatheringStateChanged를 true로 두되, 이는 connection.[[IceGatheringState]]가 이전 단계에서 바뀐 경우이다. 그렇지 않으면 false로 둔다.

  5. 이 지점 이후에는 상태를 읽거나 변경하지 않는다.

  6. 이벤트를 발생시킨다. 이름은 gatheringstatechange이며 대상은 transport이다.

  7. connectionIceGatheringStateChanged가 true이면 이벤트를 발생시키는. 이름은 icegatheringstatechange이며 대상은 connection이다.

  8. 이벤트를 발생시킨다. 이름은 icecandidate이고 RTCPeerConnectionIceEvent 인터페이스를 사용하며 candidate 속성은 null로 설정한다. 대상은 connection이다.

    Note
    null 후보 이벤트는 기존 동작과의 호환성을 위해 발생합니다. 새 코드에서는 수집 상태를 감시하는 것이 좋으며, 그 대상은 RTCIceTransport 및/또는 RTCPeerConnection입니다.

ICE 에이전트가 RTCIceTransport에 사용할 새 ICE 후보를 ICE 후보 풀에서 가져오거나 처음부터 수집하여 사용할 수 있게 되었음을 나타내면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. candidate를 사용 가능해진 ICE 후보로 둔다.

  2. connection를 이 객체와 연결된 RTCPeerConnection 객체로 둔다. 이때 이 객체는 ICE 에이전트이다.

  3. connection.[[IsClosed]]가 true이면 이 단계들을 중단한다.

  4. connection.[[PendingLocalDescription]] 또는 connection.[[CurrentLocalDescription]] 중 하나가 null이 아니고, 후보가 수집된 ICE 세대를 나타내는 설명이라면, 여기서 그 후보는 candidate이다. 후보를 노출하는 절차를 candidate와 connection으로 실행하고 이 단계들을 중단한다.

  5. 그렇지 않으면 candidate를 connection.[[EarlyCandidates]]에 추가한다.

ICE 에이전트가 [RFC8445 ] 7.3.1.1절에 따른 역할 충돌이 있는 ICE 바인딩 요청으로 인해 ICE 역할이 변경되었음을 알리면, UA는 [[IceRole]]의 값을 새 값으로 설정하는 태스크를 큐에 넣는다.

초기 후보를 해제하는 절차를 connection 에 대해 실행하려면 다음 단계를 실행한다:

  1. 각 후보 candidate에 대해, connection.[[EarlyCandidates]]에 속한 항목마다 태스크를 큐에 넣어 후보를 노출하는 절차를 candidate와 connection로 실행한다.

  2. connection.[[EarlyCandidates]]를 빈 목록으로 설정한다.

후보를 노출하는 절차를 candidate와 connection로 실행하려면 다음 단계를 실행한다:

  1. connection.[[IsClosed]]가 true이면 이 단계들을 중단한다.

  2. transport를 RTCIceTransport로 두며, 이는 candidate가 사용 가능해진 전송이다.

  3. connection.[[PendingLocalDescription]] 가 null이 아니고 해당 ICE 세대를 나타내며 그 세대에서 candidate가 수집되었으면, candidate를 connection.[[PendingLocalDescription]].sdp에 추가한다.

  4. connection.[[CurrentLocalDescription]] 가 null이 아니고 해당 ICE 세대를 나타내며 그 세대에서 candidate가 수집되었으면, candidate를 connection.[[CurrentLocalDescription]].sdp에 추가한다.

  5. newCandidate를 RTCIceCandidate를 생성하는 절차의 결과로 둔다. 이때 새 사전을 사용하며, 그 sdpMid와 sdpMLineIndex 는 이 RTCIceTransport와 연결된 값으로 설정하고, usernameFragment 는 후보의 사용자 이름 조각으로 설정한다. candidate는 candidate-attribute 문법을 사용하여 candidate를 나타내도록 인코딩한 문자열로 설정한다.

  6. newCandidate를 transport의 로컬 후보 집합에 추가한다.

  7. 이벤트를 발생시킨다. 이름은 icecandidate이고 RTCPeerConnectionIceEvent 인터페이스를 사용하며 candidate 속성은 newCandidate로 설정한다. 대상은 connection이다.

RTCIceTransportState는 RTCIceTransport에서 사용 가능한 연결을 가진 후보 쌍을 찾아 선택했기 때문에 바뀔 수도 있고, 선택된 후보 쌍이 바뀌지 않아도 바뀔 수 있다. 선택된 쌍과 RTCIceTransportState는 서로 관련이 있으며 같은 태스크에서 처리한다.

ICE 에이전트가 RTCIceTransport 의 선택된 후보 쌍, RTCIceTransportState 또는 둘 모두가 바뀌었음을 나타내면, 사용자 에이전트는 반드시 선택된 후보 쌍과 상태를 변경하는 절차를 실행하는 태스크를 큐에 넣어야 한다:

  1. connection를 이 객체와 연결된 RTCPeerConnection 객체로 둔다. 이때 이 객체는 ICE 에이전트이다.

  2. connection.[[IsClosed]]가 true이면 이 단계들을 중단한다.

  3. transport를 상태가 변경되는 RTCIceTransport로 둔다.

  4. selectedCandidatePairChanged를 false로 둔다.

  5. transportIceConnectionStateChanged를 false로 둔다.

  6. connectionIceConnectionStateChanged를 false로 둔다.

  7. connectionStateChanged를 false로 둔다.

  8. transport의 선택된 후보 쌍이 변경되었으면 다음 단계를 실행한다:

    1. newCandidatePair를 RTCIceCandidatePair를 생성하는 절차의 결과로 둔다. 이때 local과 remote는 쌍이 선택되어 있으면 해당 쌍의 로컬 및 원격 후보를 나타내고, 그렇지 않으면 null이다.

    2. transport.[[SelectedCandidatePair]]를 newCandidatePair로 설정한다.

    3. selectedCandidatePairChanged를 true로 설정한다.

  9. transport의 RTCIceTransportState가 변경되었으면 다음 단계를 실행한다:

    1. transport.[[IceTransportState]]를 새로 표시된 RTCIceTransportState로 설정한다.

    2. transportIceConnectionStateChanged를 true로 설정한다.

    3. connection.[[IceConnectionState]] 를 RTCIceConnectionState 열거형의 설명에 따라 새 상태 값을 도출한 값으로 설정한다.

    4. connection.[[IceConnectionState]]가 이전 단계에서 바뀌었으면 connectionIceConnectionStateChanged를 true로 설정한다.

    5. connection.[[ConnectionState]] 를 RTCPeerConnectionState 열거형의 설명에 따라 새 상태 값을 도출한 값으로 설정한다.

    6. connection.[[ConnectionState]]가 이전 단계에서 바뀌었으면 connectionStateChanged를 true로 설정한다.

  10. selectedCandidatePairChanged가 true이면 이벤트를 발생시키는. 이름은 selectedcandidatepairchange이며 대상은 transport이다.

  11. transportIceConnectionStateChanged가 true이면 이벤트를 발생시키는. 이름은 statechange이며 대상은 transport이다.

  12. connectionIceConnectionStateChanged가 true이면 이벤트를 발생시키는. 이름은 iceconnectionstatechange이며 대상은 connection이다.

  13. connectionStateChanged가 true이면 이벤트를 발생시키는. 이름은 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;
};

Attributes

role of type RTCIceRole, readonly

role 속성은 반드시 값을 가져올 때 [[IceRole]] 내부 슬롯의 값을 반환해야 한다.

component of type RTCIceComponent, readonly

component 속성은 반드시 전송의 ICE 구성요소를 반환해야 한다. RTCP mux를 사용하면 하나의 RTCIceTransport가 RTP와 RTCP를 모두 전송하며 component는 "rtp"로 설정된다.

state of type RTCIceTransportState, readonly

state 속성은 반드시 값을 가져올 때 [[IceTransportState]] 슬롯의 값을 반환해야 한다.

gatheringState of type RTCIceGathererState, readonly

gatheringState 속성은 반드시 값을 가져올 때 [[IceGathererState]] 슬롯의 값을 반환해야 한다.

onstatechange of type EventHandler
이 이벤트 핸들러의 이벤트 유형은 statechange이며, 반드시 RTCIceTransport의 state가 바뀔 때마다 발생해야 한다.
ongatheringstatechange of type EventHandler
이 이벤트 핸들러의 이벤트 유형은 gatheringstatechange이며, 반드시 RTCIceTransport의 [[IceGathererState]]가 바뀔 때마다 발생해야 한다.
onselectedcandidatepairchange of type EventHandler
이 이벤트 핸들러의 이벤트 유형은 selectedcandidatepairchange이며, 반드시 RTCIceTransport의 선택된 후보 쌍이 바뀔 때마다 발생해야 한다.

Methods

getLocalCandidates

로컬 ICE 후보를 설명하는 시퀀스를 반환한다. 이는 이 RTCIceTransport에 대해 수집되어 onicecandidate으로 전송된 후보들이다.

getRemoteCandidates

원격 ICE 후보를 설명하는 시퀀스를 반환한다. 이는 이 RTCIceTransport가 addIceCandidate()로 받은 후보들이다.

Note
getRemoteCandidates 는 피어 반사 후보를 노출하지 않습니다. 이러한 후보는 addIceCandidate()를 통해 수신되지 않기 때문입니다.
getSelectedCandidatePair

패킷을 보내는 데 사용하는 선택된 후보 쌍을 반환한다. 이 메서드는 반드시 [[SelectedCandidatePair]] 슬롯의 값을 반환해야 한다. RTCIceTransport.state가 "new" 또는 "closed"이면 getSelectedCandidatePair는 null을 반환한다.

getLocalParameters

로컬 ICE 매개변수를 반환한다. 이는 이 RTCIceTransport가 setLocalDescription으로 받은 값이며 아직 받지 않았으면 null을 반환한다.

getRemoteParameters

원격 ICE 매개변수를 반환한다. 이는 이 RTCIceTransport가 setRemoteDescription으로 받은 값이며 아직 받지 않았으면 null을 반환한다.

5.6.1 RTCIceParameters 딕셔너리

WebIDLdictionary RTCIceParameters {
  DOMString usernameFragment;
  DOMString password;
};
Dictionary RTCIceParameters Members
usernameFragment of type DOMString

[ RFC5245 ] 7.1.2.3절에 정의된 ICE 사용자 이름 조각이다.

password of type DOMString

[ RFC5245 ] 7.1.2.3절에 정의된 ICE 비밀번호이다.

Candidate Addition 45:Convert RTCIceCandidatePair dictionary to an interface (PR #2961)

5.6.2 RTCIceCandidatePair Dictionary

5.6.2 RTCIceCandidatePair Interface

이 인터페이스는 [ RFC8445 ] 4절에 설명된 ICE 후보 쌍을 나타낸다. RTCIceCandidatePair는 로컬 및 원격 RTCIceCandidate를 쌍으로 묶은 것이다.

RTCIceCandidatePair를 생성하는 절차를 RTCIceCandidate 객체 local 및 remote 로 실행하려면 다음 단계를 실행한다:

  1. candidatePair를 새로 생성한 RTCIceCandidatePair 객체로 둔다.
  2. candidatePair에 [[Local]] 내부 슬롯을 두고 local로 초기화한다.
  3. candidatePair에 [[Remote]] 내부 슬롯을 두고 remote로 초기화한다.
  4. candidatePair를 반환한다.
dictionary [Exposed=Window]
interface RTCIceCandidatePair {
  [SameObject] readonly attribute RTCIceCandidate local;
  [SameObject] readonly attribute RTCIceCandidate remote;
};
Dictionary RTCIceCandidatePair Members
Attributes
local of type RTCIceCandidate , readonly

로컬 ICE 후보이다.

local 속성은 반드시 값을 가져올 때 [[Local]] 내부 슬롯의 값을 반환해야 한다.

remote of type RTCIceCandidate , readonly

원격 ICE 후보이다.

remote 속성은 반드시 값을 가져올 때 [[Remote]] 내부 슬롯의 값을 반환해야 한다.

5.6.3 RTCIceGathererState 열거형

WebIDLenum RTCIceGathererState {
  "new",
  "gathering",
  "complete"
};
RTCIceGathererState Enumeration description
Enum value Description
new 해당 RTCIceTransport 는 방금 생성되었으며 아직 후보 를 수집하기 시작하지 않은 상태이다.
gathering 해당 RTCIceTransport 는 현재 후보를 수집하는 과정에 있는 상태이다.
complete 해당 RTCIceTransport 는 후보 수집 을 완료했으며 이 전송 에 대한 end-of-candidates 표시도 이미 전송되었다. ICE 재시작 으로 인해 다시 시작하기 전 까지 는 후보 를 다시 수집하지 않는다.

5.6.4 RTCIceTransportState 열거형

WebIDLenum RTCIceTransportState {
  "closed",
  "failed",
  "disconnected",
  "new",
  "checking",
  "completed",
  "connected"
};
RTCIceTransportState Enumeration description
Enum value Description
closed 해당 RTCIceTransport 는 종료되었으며 이제 더 이상 STUN 요청 에 응답하지 않는 상태이다.
failed
RTCIceTransport는 수집을 완료했고, 더 이상 원격 후보가 없다는 알림을 받았으며, 모든 후보 쌍의 검사를 완료했고, 모든 쌍이 연결 검사에 실패했거나 동의(consent)를 상실했으며, 수집된 로컬 후보가 없거나 PAC 타이머가 만료되었습니다 [RFC8863]. 이 상태는 ICE가 재시작될 때까지의 종료 상태입니다. ICE 재시작으로 연결이 재개될 수 있으므로, "failed" 상태가 되어도 DTLS 전송, SCTP 연결 또는 그 위에서 실행되는 데이터 채널이 닫히거나 트랙이 음소거되지는 않습니다.
disconnected 해당 ICE 에이전트 는 다음 전송의 연결 이 현재 끊어졌다고 판단한 상태이다: RTCIceTransport. 이는 불안정한 네트워크에서 간헐적으로 발생할 수 있는 일시적인 상태이며 아무런 조치 없이도 저절로 해소될 수 있다. 이 상태를 판단하는 방식은 구현에 따라 다르다. 예를 들면 다음과 같은 경우가 있다:
  • 사용 중인 연결의 네트워크 인터페이스가 사라지는 경우.
  • STUN 요청에 대한 응답을 반복해서 받지 못하는 경우.
또는 해당 RTCIceTransport 가기존의 모든후보 쌍에 대한 검사를 끝냈지만 연결을 찾지 못한 상태일 수도 있다. 또는 다음 동의 검사[RFC7675]가 이전에는 성공했지만 이제는 실패했을 수도있다. 다만전송은 여전히 후보를 수집하고 있거나 추가적인 원격 후보를 기다리고 있는 상태이다.
new 해당 RTCIceTransport 는 후보를 수집 하고 있거나 원격 후보가 제공되기 를 기다리고 있으며 아직 검사 를 시작하지 않은 상태이다.
checking 해당 RTCIceTransport 는하나 이상의원격 후보를받은 상태이다. 이후보는 다음 메서드를 사용하여 받은 것이거나: addIceCandidate() STUN 바인딩 요청 을 받을 때 peer-reflexive 후보 로 발견한 것이다. 전송 은 후보 쌍을 검사 하고 있으며 아직 연결 을 찾지 못했 거나 다음 동 의 검사 [RFC7675]가 이전에 성공했던 모든후보 쌍에서 실패한 상태이다. 후보 쌍에 대한 검사를 수행하는 동시에 여전히 후보를 수집하고 있을 수도 있다.
completed 해당 RTCIceTransport 는 후보 수집을 마쳤고 더 이상 원격 후보가 없다는 표시 를 받았으며 모든 후보 쌍에 대한 검사도 끝내고 연결 을 찾은 상태이다. 이후 동의 검사 [RFC7675] 가 성공했던 모든 후보 쌍에서 실패하게 되면 상태가 다음 값으로 바뀐다: "failed".
connected 해당 RTCIceTransport 는 사용할 수 있는 연결을 찾았지만 더 나은 연결이 있는지 확인하기 위해 다른 후보 쌍도 계속 검사 하는 상태이다. 또한 후보를 수집 하고 있 거나 추가적인 원격 후보 를 기다리고 있을 수도 있다. 동의 검사 [RFC7675] 가 사용 중인 연결 에서 실패 하고 사용할 수 있는 다른 성공한 후보 쌍도 없다면 상태가 다음 값 으로 바뀐다: "checking"이다. 이는아직 검사할 후보쌍이 남아 있는 경우이다. 또는 다음 값으로 바뀐다: "disconnected" 이다. 이는 검사할 후보 쌍이 없지만 피어가 여전히 후보를 수집 하고 있 거나 추가적인 원격 후보 를 기다리고 있는 경우이다.
Note

성공적인 호출에서 가장 흔한 전이는 new -> checking -> connected -> completed이지만, 특정 상황(마지막으로 확인한 후보만 성공하고, 후보 수집과 더 이상 후보가 없다는 알림이 모두 성공 전에 발생한 경우)에서는 상태가 " checking"에서 " completed"로 직접 전이할 수 있다.

ICE 재시작은 후보 수집과 연결성 검사를 새로 시작하게 하며, " connected" 상태로 전이하게 한다. 이는 " completed" 상태에서 재시작한 경우이다. 일시적인 "disconnected" 상태에서 재시작하면 "checking" 상태로 전이하여, 이전에 연결성이 상실되었다는 사실을 사실상 잊는다.

" failed"와 " completed" 상태에는 추가 원격 후보가 없다는 알림이 필요하다. 이는 addIceCandidate 를 candidate 속성이 빈 문자열인 후보 값으로 호출하거나, canTrickleIceCandidates를 false로 설정하여 나타낼 수 있다.

상태 전이의 예는 다음과 같다:

ICE transport state transition diagram
Figure 2 Non-normative ICE transport state transition diagram

5.6.5 RTCIceRole 열거형

WebIDLenum RTCIceRole {
  "unknown",
  "controlling",
  "controlled"
};
RTCIceRole Enumeration description
Enum value Description
unknown 에이전트 의 역할은 다음 문헌을 기준으로 판단한다: [RFC5245], 제3절에 정의된 그 역할이 아직 정해지지 않았다.
controlling 제어하는 에이전트로서 다음 문헌에 정의되어 있다: [RFC5245], 제3절의 정의이다.
controlled 제어받는 에이전트로서 다음 문헌에 정의되어 있다: [RFC5245], 제3절의 정의이다.

5.6.6 RTCIceComponent 열거형

WebIDLenum RTCIceComponent {
  "rtp",
  "rtcp"
};
RTCIceComponent Enumeration description
Enum value Description
rtp ICE 전송은 RTP 또는 RTCP 다중화에 사용된다. 이는 다음 문헌에 정의 되어 있다: [RFC5245], 제4.1.1.1절이다. RTP와 다중화되 는 프로토콜도 같은 컴포넌트 ID를 공유한다. 데이터 채널이 그 예이다. 이는 다음 필드의 component-id 값이 1 임을나타낸다. 인코딩형식은 다음과같다: candidate-attribute.
rtcp ICE 전송 은 다음 문헌 에 정의된 RTCP에 사용 된다: [RFC5245], 제4.1.1.1절이다. 이는 다음 필드 의 component-id 값이 2 임을나타낸다. 인코딩형식은 다음과같다: candidate-attribute.

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;
};

Constructors

RTCTrackEvent.constructor()

Attributes

receiver of type RTCRtpReceiver, readonly

receiver 속성은 이벤트와 연결된 RTCRtpReceiver 객체를 나타낸다.

track of type MediaStreamTrack, readonly

track 속성은 MediaStreamTrack 객체를 나타내며, 이는 RTCRtpReceiver와 연결된 트랙이다. 해당 수신자는 receiver로 식별한다.

streams of type FrozenArray<MediaStream>, readonly

streams 속성은 MediaStream 객체의 배열을 반환한다. 이는 MediaStream들 중 이 이벤트의 track이 속하는 스트림들을 나타낸다.

transceiver of type RTCRtpTransceiver, readonly

transceiver 속성은 이벤트와 연결된 RTCRtpTransceiver 객체를 나타낸다.

WebIDLdictionary RTCTrackEventInit : EventInit {
  required RTCRtpReceiver receiver;
  required MediaStreamTrack track;
  sequence<MediaStream> streams = [];
  required RTCRtpTransceiver transceiver;
};

Dictionary RTCTrackEventInit Members

receiver of type RTCRtpReceiver, required

receiver 멤버는 이벤트와 연결된 RTCRtpReceiver 객체를 나타낸다.

track of type MediaStreamTrack, required

track 멤버는 MediaStreamTrack 객체를 나타내며, 이는 RTCRtpReceiver와 연결된 트랙이다. 해당 수신자는 receiver로 식별한다.

streams of type sequence<MediaStream>, defaulting to []

streams 멤버는 MediaStream 객체의 배열이며, 이는 MediaStream들 중 이 이벤트의 track이 속하는 스트림들을 나타낸다.

transceiver of type RTCRtpTransceiver, required

transceiver 속성은 이벤트와 연결된 RTCRtpTransceiver 객체를 나타낸다.

6. 피어 투 피어 데이터 API

피어 간 데이터 API는 웹 애플리케이션이 일반 애플리케이션 데이터를 피어 간에 보내고 받을 수 있도록 한다. 데이터 송수신 API는 Web Sockets의 동작을 본뜬다.

6.1 RTCPeerConnection 인터페이스 확장

피어 간 데이터 API는 아래에 설명된 대로 RTCPeerConnection 인터페이스를 확장한다.

WebIDL          partial interface RTCPeerConnection {
  readonly attribute RTCSctpTransport? sctp;
  RTCDataChannel createDataChannel(USVString label,
                                   optional RTCDataChannelInit dataChannelDict = {});
  attribute EventHandler ondatachannel;
};

Attributes

sctp of type RTCSctpTransport, readonly, nullable

SCTP 데이터를 보내고 받는 SCTP 전송이다. SCTP가 협상되지 않았으면 값은 null이다. 이 속성은 반드시 RTCSctpTransport 객체를 반환해야 하며, 이 객체는 [[SctpTransport]] 내부 슬롯에 저장되어 있다.

ondatachannel of type EventHandler
이 이벤트 핸들러의 이벤트 유형은 datachannel이다.

Methods

createDataChannel

주어진 레이블로 새 RTCDataChannel 객체를 생성한다. RTCDataChannelInit 사전을 사용하여 데이터 신뢰성과 같은 기반 채널의 속성을 구성할 수 있다.

createDataChannel 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다.

  1. connection를 메서드가 호출된 RTCPeerConnection 객체로 둔다.

  2. connection.[[IsClosed]]가 true이면 예외를 던지는 절차로 InvalidStateError를 던진다.

  3. RTCDataChannel을 생성하는 절차로 channel을 생성한다.

  4. channel.[[DataChannelLabel]] 을 첫 번째 인수의 값으로 초기화한다.

  5. [[DataChannelLabel]] 의 UTF-8 표현이 65535바이트보다 길면 예외를 던지는 절차로 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바이트보다 길면 예외를 던지는 절차로 TypeError를 던진다.

  12. channel.[[Negotiated]]를 option.negotiated로 초기화한다.

  13. channel.[[DataChannelId]]를 option.id가 존재하고 [[Negotiated]]가 true이면 그 값으로, 그렇지 않으면 null로 초기화한다.

    Note
    이는 id 멤버가 데이터 채널을 대역 내에서 협상할 때 무시된다는 뜻이며, 이는 의도된 동작입니다. 대역 내에서 협상되는 데이터 채널의 ID는 DTLS 역할에 따라 선택하는 것이 좋습니다. 이에 관해서는 [RFC8832]를 참조하십시오.
  14. [[Negotiated]]가 true이고 [[DataChannelId]]가 null이면 예외를 던지는 절차로 TypeError를 던진다.

  15. [[MaxPacketLifeTime]]와 [[MaxRetransmits]] 속성이 모두 설정되어 있으면(null이 아니면) 예외를 던지는 절차로 TypeError를 던진다.

  16. [[MaxPacketLifeTime]] 또는 [[MaxRetransmits]] 중 한 설정이 비신뢰 모드를 나타내도록 설정되었고 그 값이 사용자 에이전트가 지원하는 최대값을 초과하면, 그 값은 반드시 사용자 에이전트의 최대값으로 설정해야 한다.

  17. [[DataChannelId]]가 65535와 같으면, 이는 허용되는 최대 ID 65534보다 크지만 unsigned short 범위에는 여전히 속하므로, 예외를 던지는 절차로 TypeError를 던진다.

  18. [[DataChannelId]] 슬롯이 null이고( createDataChannel에 ID가 전달되지 않았거나 [[Negotiated]] 가 false이기 때문에), SCTP 전송의 DTLS 역할이 이미 협상되었으면, [[DataChannelId]] 를 사용자 에이전트가 [RFC8832 ]에 따라 생성한 값으로 초기화하고 다음 단계로 넘어간다. 사용 가능한 ID를 생성할 수 없거나 [[DataChannelId]] 슬롯의 값을 기존 RTCDataChannel이 사용하고 있으면, 예외를 던지는 절차로 OperationError 예외를 던진다.

    Note
    이 단계 이후에도 [[DataChannelId]] 슬롯의 값이 null 이면, 해당 슬롯의 값은 다음 RTCSctpTransport connected 절차 중에 설정됩니다.
  19. transport를 connection.[[SctpTransport]]로 둔다.

    [[DataChannelId]] 슬롯이 null이 아니고 transport가 " connected " 상태이며 [[DataChannelId]] 가 transport.[[MaxChannels]] 이상이면 예외를 던지는 절차로 OperationError를 던진다.

  20. channel이 RTCDataChannel에서 처음 생성된 connection이면 협상 필요 플래그를 갱신하는 절차를 connection에 대해 실행한다.

  21. 추가하는 절차로 channel을 connection.[[DataChannels]]에 추가한다.

  22. channel을 반환하고 다음 단계를 병렬로 계속한다.

  23. channel과 연결된 기반 데이터 전송 을 생성하고 channel의 관련 속성에 따라 구성한다.

6.1.1 RTCSctpTransport 인터페이스

RTCSctpTransport 인터페이스는 특정 SCTP 연결에 연결된 SCTP 데이터 채널 정보에 애플리케이션이 접근할 수 있도록 한다.

6.1.1.1 인스턴스 생성

RTCSctpTransport를 생성하는 절차를 초기 상태 initialState로 실행하려면 다음 단계를 실행한다:

  1. transport를 새 RTCSctpTransport 객체로 둔다.

  2. transport에 [[SctpTransportState]] 내부 슬롯을 두고 initialState로 초기화한다.

  3. transport에 [[MaxMessageSize]] 내부 슬롯을 두고 데이터 최대 메시지 크기를 갱신하는로 표시된 단계를 실행하여 초기화한다.

  4. transport에 [[MaxChannels]] 내부 슬롯을 두고 null로 초기화한다.

  5. transport를 반환한다.

6.1.1.2 최대 메시지 크기 업데이트

데이터 최대 메시지 크기를 갱신하는 절차를 RTCSctpTransport에 대해 실행하려면 다음 단계를 실행한다:

  1. transport를 갱신할 RTCSctpTransport 객체로 둔다.

  2. remoteMaxMessageSize를 max-message-size SDP 속성의 값으로 둔다. 이는 [ RFC8841 ] 6절에 설명된 대로 원격 설명에서 읽은 값이며, 속성이 없으면 65536으로 둔다.

  3. canSendSize를 이 클라이언트가 보낼 수 있는 바이트 수(즉 로컬 송신 버퍼 크기)로 두며, 구현이 모든 크기의 메시지를 처리할 수 있으면 0으로 둔다.

  4. remoteMaxMessageSize와 canSendSize가 모두 0이면 [[MaxMessageSize]]를 양의 Infinity 값으로 설정한다.

  5. 그렇지 않고 remoteMaxMessageSize 또는 canSendSize 중 하나가 0이면 [[MaxMessageSize]]를 둘 중 더 큰 값으로 설정한다.

  6. 그렇지 않으면 [[MaxMessageSize]]를 remoteMaxMessageSize와 canSendSize 중 더 작은 값으로 설정한다.

6.1.1.3 연결 완료 절차

SCTP 전송이 연결된 상태가 되면, 즉 RTCSctpTransport의 SCTP 연결이 설정되면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣는 절차를 수행해야 한다:

  1. transport를 RTCSctpTransport 객체로 둔다.

  2. connection를 RTCPeerConnection 객체로 두며, 이 객체는 transport와 연결되어 있다.

  3. [[MaxChannels]]를 협상된 수신 및 송신 SCTP 스트림 수 중 더 작은 값으로 설정한다.

  4. connection의 각 RTCDataChannel에 대해:

    1. channel를 RTCDataChannel 객체로 둔다.

    2. channel.[[DataChannelId]]가 null이면 [[DataChannelId]]를 기반 SCTP 데이터 채널이 [ RFC8832 ]에 따라 생성한 값으로 초기화한다.

    3. channel.[[DataChannelId]] 가 transport.[[MaxChannels]] 이상이거나 이전 단계에서 ID를 할당하지 못했으면, 실패로 인해 연결을 닫는 절차로 channel 을 닫는다. 그렇지 않으면 채널이 열렸음을 알리는 절차를 실행한다.

  5. 이벤트를 발생시킨다. 이름은 statechange이며 대상은 transport이다.

    Note

    이 이벤트는 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;
};
Attributes
transport of type RTCDtlsTransport, readonly

데이터 채널의 모든 SCTP 패킷을 보내고 받는 전송이다.

state of type RTCSctpTransportState, readonly

SCTP 전송의 현재 상태이다. 값을 가져올 때 이 속성은 반드시 [[SctpTransportState]] 슬롯의 값을 반환해야 한다.

maxMessageSize of type unrestricted double, readonly

데이터의 최대 크기로서 RTCDataChannel의 send() 메서드에 전달할 수 있는 한도이다. 값을 가져올 때 이 속성은 반드시 [[MaxMessageSize]] 슬롯의 값을 반환해야 한다.

maxChannels of type unsigned short , readonly, nullable

동시에 사용할 수 있는 RTCDataChannel의 최대 수이다. 값을 가져올 때 이 속성은 반드시 [[MaxChannels]] 슬롯의 값을 반환해야 한다.

Note
이 속성의 값은 null 이며, SCTP 전송이 "connected" 상태가 될 때까지 유지됩니다.
onstatechange of type EventHandler

이 이벤트 핸들러의 이벤트 유형은 statechange이다.

6.1.2 RTCSctpTransportState 열거형

RTCSctpTransportState는 SCTP 전송의 상태를 나타낸다.

WebIDLenum RTCSctpTransportState {
  "connecting",
  "connected",
  "closed"
};
RTCSctpTransportState Enumeration description
Enum value Description
connecting

RTCSctpTransport 는 연결을 협상하는 중이다. 이는 RTCSctpTransport가 생성될 때 [[SctpTransportState]] 슬롯의 초기 상태이다.

connected

연결 협상이 완료되면 [[SctpTransportState]] 슬롯을 " connected"로 갱신하는 태스크를 큐에 넣는다.

closed

다음 경우 [[SctpTransportState]] 슬롯을 " closed"로 갱신하는 태스크를 큐에 넣는다:

  • SHUTDOWN 또는 ABORT 청크를 수신한 경우.
  • 피어 연결을 닫거나, 데이터를 거부하거나 SCTP 포트를 변경하는 원격 설명을 적용하는 등 SCTP 연결을 의도적으로 닫은 경우.
  • 기반 DTLS 연결이 " closed" 상태로 전이한 경우.

마지막 전이는 SCTP 연결에 이미 설정된 DTLS 연결이 필요하다는 점에서 자연스럽다. [RFC8261 ] 6.1절은 DTLS 위의 SCTP가 단일 홈 방식이라고 명시하며, 이 API는 다른 전송으로 전환하는 방법을 정의하지 않는다.

6.2 RTCDataChannel

RTCDataChannel 인터페이스는 두 피어 사이의 양방향 데이터 채널을 나타낸다. RTCDataChannel 은 RTCPeerConnection 객체의 팩터리 메서드로 생성한다. 브라우저 사이에 전송되는 메시지는 [RFC8831]과 [ RFC8832]에 설명되어 있다.

RTCDataChannel 로 연결을 설정하는 방법에는 두 가지가 있다. 첫 번째 방법은 한쪽 피어에서 RTCDataChannel을 생성하되, negotiated라는 RTCDataChannelInit 사전 멤버를 설정하지 않거나 기본값 false로 설정하는 것이다. 이렇게 하면 새 채널을 대역 내에서 알리고 다른 피어에서 RTCDataChannelEvent를 대응하는 RTCDataChannel 객체와 함께 발생시킨다. 두 번째 방법은 애플리케이션이 RTCDataChannel을 협상하도록 하는 것이다. 이를 위해 RTCDataChannel 객체를 생성하되 negotiated라는 RTCDataChannelInit 사전 멤버를 true로 설정하고, 대역 외 신호(예: 웹 서버를 통해)로 다른 쪽에 알린다. 다른 쪽은 가급적 대응하는 RTCDataChannel을 생성하되 negotiated라는 RTCDataChannelInit 사전 멤버를 true로 설정하고 같은 id를 사용해야 한다. 이렇게 하면 별도로 생성한 두 RTCDataChannel 객체가 연결된다. 두 번째 방법을 사용하면 비대칭 속성을 가진 채널을 만들거나, 일치하는 id를 지정하여 선언적인 방식으로 채널을 만들 수 있다.

각 RTCDataChannel에는 다른 피어로 실제 데이터를 전송하는 데 사용하는 기반 데이터 전송이 연결되어 있다. SCTP 연결의 상태를 나타내는 RTCSctpTransport를 사용하는 SCTP 데이터 채널에서는 기반 데이터 전송이 SCTP 스트림 쌍이다. 기반 데이터 전송의 전송 속성(순서대로 전달하는 설정이나 신뢰성 모드 등)은 채널을 생성할 때 피어가 구성한다. 채널을 생성한 뒤에는 채널의 속성을 변경할 수 없다. 피어 사이에서 실제로 사용하는 통신 프로토콜은 WebRTC DataChannel Protocol 명세 [RFC8831]에 지정되어 있다.

RTCDataChannel은 서로 다른 신뢰성 모드로 동작하도록 구성할 수 있다. 신뢰 채널은 재전송을 통해 데이터가 다른 피어에 전달되도록 보장한다. 비신뢰 채널은 재전송 횟수를 제한하거나( maxRetransmits), 재전송을 포함한 전송이 허용되는 시간을 설정하도록( maxPacketLifeTime) 구성한다. 이 속성들은 동시에 사용할 수 없으며 그렇게 하려고 하면 오류가 발생한다. 이 속성들을 모두 설정하지 않으면 신뢰 채널이 된다.

RTCDataChannel은 createDataChannel로 생성되거나 RTCDataChannelEvent를 통해 전달되었을 때 반드시 처음에는 " connecting" 상태여야 한다. RTCDataChannel 객체의 기반 데이터 전송이 준비되면 사용자 에이전트는 반드시 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이 열렸음을 알리는 절차를 실행해야 하면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. 연결된 RTCPeerConnection 객체의 [[IsClosed]] 슬롯이 true이면 이 단계들을 중단한다.

  2. channel를 열렸음을 알릴 RTCDataChannel 객체로 둔다.

  3. channel.[[ReadyState]]가 "closing" 또는 "closed"이면 이 단계들을 중단한다.

  4. channel.[[ReadyState]]를 "open"로 설정한다.

  5. 이벤트를 발생시킨다. 이름은 open이며 대상은 channel이다.

6.2.3 데이터 채널 인스턴스 알리기

기반 데이터 전송을 알려야 하면(다른 피어가 negotiated를 설정하지 않거나 false로 설정하여 채널을 생성한 경우), 생성 프로세스를 시작하지 않은 피어의 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. connection을 RTCPeerConnection 객체로 두며, 이는 기반 데이터 전송과 연결되어 있다.

  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. 추가하는 절차로 channel을 connection.[[DataChannels]]에 추가한다.

  8. channel.[[ReadyState]]를 "open "으로 설정한다(그러나 open 이벤트는 아직 발생시키지 않는다).

    Note
    This allows to start sending messages inside of the datachannel event handler prior to the open event being fired.
  9. 이벤트를 발생시킨다. 이름은 datachannel이고 RTCDataChannelEvent 인터페이스를 사용하며 channel 속성은 channel로 설정한다. 대상은 connection이다.

  10. 데이터 채널이 열렸음을 알리는 절차를 실행한다.

Candidate Correction 38:Prevent GC of non-closed RTCDataChannels (PR #2902)

6.2.4 닫기 절차

6.2.4 Closing procedure

RTCDataChannel 객체의 기반 데이터 전송 은 닫기 절차를 실행하여 갑작스럽지 않은 방식으로 해제할 수 있다. 이 경우 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. channel를 RTCDataChannel 객체로 두며, 이 객체의 기반 데이터 전송가 닫힌 것이다.

  2. connection를 RTCPeerConnection 객체로 두며, 이 객체는 channel와 연결되어 있다.

  3. 제거하는 절차로 channel을 connection.[[DataChannels]]에서 제거한다.

  4. 프로세스가 channel.close에 의해 시작된 것이 아니면 channel.[[ReadyState]]를 "closing"으로 설정하고 이벤트를 발생시키는 절차를 실행한다. 이름은 closing이며 대상은 channel이다.

  5. 다음 단계를 병렬 병렬로 실행한다:

    1. channel에서 현재 보류 중인 모든 메시지의 전송을 마친다.

    2. channel의 기반 데이터 전송에 대해 정의된 닫기 절차를 따른다:

      1. SCTP 기반 transport 의 경우 [ RFC8831 ] 6.7절을 따른다.

    3. channel의 데이터 전송을 closed 상태로 만든다 을 닫는다 . 이를 위해 연결된 절차를 따른다.

6.2.5 데이터 채널이 닫혔음을 알리기

RTCDataChannel 객체의 기반 데이터 전송이 닫힌 상태가 되면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. channel를 RTCDataChannel 객체로 두며, 이 객체의 기반 데이터 전송가 닫힌 것이다.

  2. channel.[[ReadyState]]가 "closed "이면 이 단계들을 중단한다.
  3. channel.[[ReadyState]]를 "closed"로 설정한다.

  4. 제거하는 절차로 channel을 connection.[[DataChannels]]에서 아직 그 안에 있으면 제거한다.

  5. transport가 오류 발생 상태로 닫혔으면 이벤트를 발생시키는 절차를 실행한다. 이름은 error이고 RTCErrorEvent 인터페이스를 사용하며 errorDetail 속성은 " sctp-failure"로 설정한다. 대상은 channel이다.

  6. 이벤트를 발생시킨다. 이름은 연결을 닫는이며 대상은 channel이다.

6.2.6 데이터 채널 전송

RTCDataChannel의 이전 단계는 value와 dataHolder가 주어지면 다음과 같다:

  1. value.[[IsTransferable]]가 false이면 DataCloneError DOMException을 던진다.

  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의 이전 수신 단계는 dataHolder와 channel가 주어지면 다음과 같다:

  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의 기반 데이터 전송을 생성할 수 없다고 판단하면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. channel을 RTCDataChannel 객체로 두며, 이는 사용자 에이전트가 기반 데이터 전송을 생성할 수 없었던 채널이다.

  2. channel.[[ReadyState]]를 "closed"로 설정한다.

  3. 이벤트를 발생시킨다. 이름은 error이고 RTCErrorEvent 인터페이스를 사용하며 errorDetail 속성은 "data-channel-failure"로 설정한다. 대상은 channel이다.

  4. 이벤트를 발생시킨다. 이름은 연결을 닫는이며 대상은 channel이다.

6.2.8 데이터 채널에서 메시지 수신

RTCDataChannel 메시지를 기반 데이터 전송으로 수신하였고 그 유형이 type이며 데이터가 rawData이면, 사용자 에이전트는 반드시 다음 단계를 실행하는 태스크를 큐에 넣어야 한다:

  1. channel을 사용자 에이전트가 메시지를 수신한 RTCDataChannel 객체로 둔다.

  2. connection를 RTCPeerConnection 객체로 두며, 이 객체는 channel와 연결되어 있다.

  3. channel.[[ReadyState]]가 " open "이 아니면 이 단계들을 중단하고 rawData를 버린다.

  4. type와 channel.binaryType에 따라 분기하여 하위 단계를 실행한다:

    • type이 rawData의 string 형식을 나타내면:

      data를 DOMString 으로 두며, 이는 rawData를 UTF-8로 디코딩한 결과를 나타낸다.

    • type가 rawData의 이진 형식을 나타내고 binaryType가 "blob"이면:

      data를 새 Blob 객체로 두며, 원시 데이터 소스로 rawData를 포함한다.

    • type가 rawData의 이진 형식을 나타내고 binaryType가 "arraybuffer"이면:

      data를 새 ArrayBuffer 객체로 두며, 원시 데이터 소스로 rawData를 포함한다.

  5. 이벤트를 발생시킨다. 이름은 message이며 MessageEvent 인터페이스를 사용하고, 그 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);
};

Attributes

label of type USVString, readonly

label 속성은 이 RTCDataChannel 객체를 다른 RTCDataChannel 객체와 구별하는 데 사용할 수 있는 레이블을 나타낸다. 스크립트는 같은 레이블을 가진 여러 RTCDataChannel 객체를 생성할 수 있다. 값을 가져올 때 이 속성은 반드시 [[DataChannelLabel]] 슬롯의 값을 반환해야 한다.

ordered of type boolean, readonly

ordered 속성은 RTCDataChannel이 순서대로 전달되면 true를, 순서가 바뀐 전달이 허용되면 false를 반환한다. 값을 가져올 때 이 속성은 반드시 [[Ordered]] 슬롯의 값을 반환해야 한다.

maxPacketLifeTime of type unsigned short, readonly, nullable

maxPacketLifeTime 속성은 비신뢰 모드에서 전송과 재전송이 일어날 수 있는 시간 범위의 길이를 밀리초 단위로 반환한다. 값을 가져올 때 이 속성은 반드시 [[MaxPacketLifeTime]] 슬롯의 값을 반환해야 한다.

maxRetransmits of type unsigned short, readonly, nullable

maxRetransmits 속성은 비신뢰 모드에서 시도하는 최대 재전송 횟수를 반환한다. 값을 가져올 때 이 속성은 반드시 [[MaxRetransmits]] 슬롯의 값을 반환해야 한다.

protocol of type USVString, readonly

protocol 속성은 이 RTCDataChannel과 함께 사용하는 하위 프로토콜의 이름을 반환한다. 값을 가져올 때 이 속성은 반드시 [[DataChannelProtocol]] 슬롯의 값을 반환해야 한다.

negotiated of type boolean, readonly

negotiated 속성은 이 RTCDataChannel을 애플리케이션이 협상했으면 true를, 그렇지 않으면 false를 반환한다. 값을 가져올 때 이 속성은 반드시 [[Negotiated]] 슬롯의 값을 반환해야 한다.

id of type unsigned short, readonly, nullable

id 속성은 이 RTCDataChannel의 ID를 반환한다. 초기값은 null이며, 채널 생성 시 ID를 제공하지 않았고 SCTP 전송의 DTLS 역할도 아직 협상되지 않았으면 이 값을 반환한다. 그렇지 않으면 스크립트가 선택하거나 사용자 에이전트가 [RFC8832]에 따라 생성한 ID를 반환한다. ID를 null이 아닌 값으로 설정한 뒤에는 변경되지 않는다. 값을 가져올 때 이 속성은 반드시 [[DataChannelId]] 슬롯의 값을 반환해야 한다.

readyState of type RTCDataChannelState, readonly

readyState 속성은 RTCDataChannel 객체의 상태를 나타낸다. 값을 가져올 때 이 속성은 반드시 [[ReadyState]] 슬롯의 값을 반환해야 한다.

bufferedAmount of type unsigned long, readonly

bufferedAmount 속성은 반드시 값을 가져올 때 [[BufferedAmount]] 슬롯의 값을 반환해야 한다. 이 속성은 send()로 큐에 넣은 애플리케이션 데이터(UTF-8 텍스트와 이진 데이터)의 바이트 수를 노출한다. 데이터 전송이 병렬로 일어날 수 있더라도, 반환되는 값은 절대로 경쟁 상태를 방지하기 위해 현재 태스크가 이벤트 루프에 제어를 돌려주기 전에 감소해서는 안 된다. 이 값에는 프로토콜의 프레이밍 오버헤드나 운영체제 또는 네트워크 하드웨어의 버퍼링은 포함되지 않는다. [[BufferedAmount]] 슬롯의 값은 send() 메서드를 호출할 때마다 증가하며, 이는 [[ReadyState]] 슬롯이 " open"인 동안에만 해당한다. 그러나 채널이 닫혀도 슬롯은 0으로 재설정되지 않는다. 기반 데이터 전송이 큐에서 데이터를 보내면, 사용자 에이전트는 반드시 [[BufferedAmount]]를 전송한 바이트 수만큼 줄이는 태스크를 큐에 넣어야 한다.

bufferedAmountLowThreshold of type unsigned long

bufferedAmountLowThreshold 속성은 bufferedAmount 가 낮다고 간주되는 임계값을 설정한다. bufferedAmount가 이 임계값보다 큰 값에서 임계값 이하로 감소하면 bufferedamountlow 이벤트가 발생한다. bufferedAmountLowThreshold는 새 RTCDataChannel마다 처음에는 0이지만, 애플리케이션은 언제든지 그 값을 변경할 수 있다.

onopen of type EventHandler
이 이벤트 핸들러의 이벤트 유형은 open이다.
onbufferedamountlow of type EventHandler
이 이벤트 핸들러의 이벤트 유형은 bufferedamountlow이다.
onerror of type EventHandler

이 이벤트 핸들러의 이벤트 유형은 RTCErrorEvent이다. errorDetail은 "sctp-failure"를 포함하고, sctpCauseCode는 SCTP Cause Code 값을 포함하며, message는 SCTP Cause-Specific-Information을 포함하고 추가 텍스트가 있을 수도 있다.

onclosing of type EventHandler

이 이벤트 핸들러의 이벤트 유형은 closing이다.

onclose of type EventHandler

이 이벤트 핸들러의 이벤트 유형은 연결을 닫는이다.

onmessage of type EventHandler

이 이벤트 핸들러의 이벤트 유형은 message이다.

binaryType of type BinaryType

binaryType 속성은 마지막으로 설정된 값을 반환한다. RTCDataChannel 객체가 생성되면 binaryType 속성은 반드시 문자열 "arraybuffer"로 초기화해야 한다.

이 속성은 이진 데이터를 스크립트에 노출하는 방식을 제어한다. Web Socket의 binaryType을 참조한다.

Methods

close()

RTCDataChannel을 닫는다. 해당 RTCDataChannel 객체를 이 피어가 생성했는지 원격 피어가 생성했는지와 관계없이 호출할 수 있다.

close 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. channel을 닫으려는 RTCDataChannel 객체로 둔다.

  2. channel.[[ReadyState]]가 "closing" 또는 "closed"이면 이 단계들을 중단한다.

  3. channel.[[ReadyState]]를 "closing"로 설정한다.

  4. 닫기 절차가 아직 시작되지 않았으면 시작한다.

send

send() 알고리즘에 설명된 단계를 실행하며, 인수 유형은 string 객체이다.

send

send() 알고리즘에 설명된 단계를 실행하며, 인수 유형은 Blob 객체이다.

send

send() 알고리즘에 설명된 단계를 실행하며, 인수 유형은 ArrayBuffer 객체이다.

send

send() 알고리즘에 설명된 단계를 실행하며, 인수 유형은 ArrayBufferView 객체이다.

send() 메서드는 서로 다른 데이터 인수 유형을 처리하도록 오버로드되어 있다. 어떤 버전의 메서드든 호출되면 사용자 에이전트는 반드시 다음 단계를 실행하는 절차를 실행해야 한다:

  1. channel을 데이터를 전송할 RTCDataChannel 객체로 둔다.

  2. channel.[[IsTransferable]]를 false로 설정한다.

  3. channel.[[ReadyState]]가 " open"이 아니면 예외를 던지는 절차로 InvalidStateError를 던진다.

  4. 메서드 인수의 유형에 해당하는 하위 단계를 실행한다:

    • string object:

      data를 메서드의 인수를 UTF-8로 인코딩한 결과를 나타내는 바이트 버퍼로 둔다.

    • Blob object:

      data를 Blob 객체가 나타내는 원시 데이터로 둔다.

      Note
      실제로 data 를 Blob 객체에서 가져오는 작업은 비동기로 이루어질 수 있지만, 사용자 에이전트가 큐에 넣을 때 사용하는 대상은 channel의 기저 데이터 전송 입니다. 데이터는 send 메서드의 호출 순서와 동일한 순서로 큐에 넣습니다. 바이트 단위로 나타낸 data 의 크기는 동기적으로 알아야 합니다.
    • ArrayBuffer object:

      data를 ArrayBuffer 객체가 설명하는 버퍼에 저장된 데이터로 둔다.

    • ArrayBufferView object:

      data를 ArrayBuffer 객체가 설명하는 버퍼 중 ArrayBufferView 객체가 참조하는 부분에 저장된 데이터로 둔다.

    Note
    이 메서드가 오버로드로 지원하지 않는 data 인수 타입은 모두 TypeError를 발생시킵니다. 여기에는 null 및 undefined도 포함됩니다.
  5. data의 바이트 크기가 maxMessageSize 값을 초과하면, 이는 channel 와 연결된 RTCSctpTransport의 값이다. 이 경우 예외를 던지는 절차로 TypeError를 던진다.

  6. data를 channel의 기반 데이터 전송으로 전송하도록 큐에 넣는다. data를 넣기에 버퍼 공간이 부족하여 큐에 넣을 수 없으면 예외를 던지는 절차로 OperationError를 던진다.

    Note
    실제 데이터 전송은 병렬로 수행됩니다. 데이터를 보내는 과정에서 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;
};

Dictionary RTCDataChannelInit Members

ordered of type boolean, defaulting to true

false로 설정하면 데이터가 순서와 다르게 전달되어도 된다. 기본값 true는 데이터가 순서대로 전달되도록 보장한다.

maxPacketLifeTime of type unsigned short

확인 응답을 받지 못했을 때 채널이 데이터를 전송하거나 재전송할 수 있는 시간을 밀리초 단위로 제한한다. 이 값이 사용자 에이전트가 지원하는 최대값을 초과하면 제한될 수 있다.

maxRetransmits of type unsigned short

성공적으로 전달되지 않았을 때 채널이 데이터를 재전송하는 횟수를 제한한다. 사용자 에이전트가 지원하는 최대값을 초과하면 이 값이 제한될 수 있다.

protocol of type USVString, defaulting to ""

이 채널에서 사용하는 하위 프로토콜 이름이다.

negotiated of type boolean, defaulting to false

기본값 false는 사용자 에이전트가 채널을 대역 내에서 알리고 다른 피어가 대응하는 RTCDataChannel 객체를 전달하도록 지시한다. true로 설정하면 애플리케이션이 채널을 협상하고 다른 피어에서 RTCDataChannel 객체를 같은 id로 생성해야 한다.

Note
true로 설정한 경우, 애플리케이션은 상대 피어가 메시지를 받을 데이터 채널을 생성하기 전까지 메시지를 보내지 않도록 주의해야 합니다. 연결된 데이터 채널이 없는 SCTP 스트림에서 메시지를 수신하는 동작은 정의되지 않았으며, 메시지가 아무런 알림 없이 버려질 수 있습니다. 두 엔드포인트가 모두 첫 offer/answer 교환이 완료되기 전에 각자의 데이터 채널을 생성하면 이런 일이 발생하지 않습니다.
id of type unsigned short

negotiated 가 true이면 채널 ID를 설정한다. negotiated가 false이면 무시한다.

WebIDLenum RTCDataChannelState {
  "connecting",
  "open",
  "closing",
  "closed"
};
RTCDataChannelState Enumeration description
Enum value Description
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;
};

Constructors

RTCDataChannelEvent.constructor()

Attributes

channel of type RTCDataChannel, readonly

channel 속성은 이벤트와 연결된 RTCDataChannel 객체를 나타낸다.

WebIDLdictionary RTCDataChannelEventInit : EventInit {
  required RTCDataChannel channel;
};

Dictionary RTCDataChannelEventInit Members

channel of type RTCDataChannel, required

이 이벤트가 알릴 RTCDataChannel 객체이다.

6.4 가비지 컬렉션

RTCDataChannel 객체는 반드시 다음 조건 중 하나를 만족하면 가비지 컬렉션으로 수거되어서는 안 된다:

7. 피어 투 피어 DTMF

이 절은 RTCRtpSender 에서 RTCPeerConnection을 통해 DTMF(전화 키패드) 값을 보내는 인터페이스를 설명한다. DTMF를 다른 피어로 보내는 세부 사항은 [ RFC7874 ]에 설명되어 있다.

7.1 RTCRtpSender 인터페이스 확장

피어 간 DTMF API는 아래에 설명된 대로 RTCRtpSender 인터페이스를 확장한다.

WebIDL          partial interface RTCRtpSender {
  readonly attribute RTCDTMFSender? dtmf;
};

Attributes

dtmf of type RTCDTMFSender, readonly, nullable

값을 가져올 때 dtmf 속성은 [[Dtmf]] 내부 슬롯의 값을 반환한다. 이 값은 DTMF를 보내는 데 사용할 수 있는 RTCDTMFSender를 나타내며, 설정되지 않았으면 null이다. [[Dtmf]] 내부 슬롯은 RTCRtpSender의 [[SenderTrack]]의 종류가 "audio"일 때 설정된다.

7.2 RTCDTMFSender

RTCDTMFSender를 생성하는 절차를 실행하려면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  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;
};

Attributes

ontonechange of type EventHandler

이 이벤트 핸들러의 이벤트 유형은 tonechange이다.

canInsertDTMF of type boolean, readonly

RTCDTMFSender dtmfSender 가 DTMF를 보낼 수 있는지 나타낸다. 값을 가져올 때 사용자 에이전트는 반드시 DTMF 송신 가능 여부를 판단하는 절차를 dtmfSender에 대해 실행한 결과를 반환해야 한다.

toneBuffer of type DOMString, readonly

toneBuffer 속성은 반드시 재생할 톤의 남은 목록을 반환해야 한다. 이 목록의 문법, 내용 및 해석은 insertDTMF를 참조한다.

Methods

insertDTMF

RTCDTMFSender 객체의 insertDTMF 메서드는 DTMF 톤을 보내는 데 사용한다.

tones 매개변수는 일련의 문자로 취급한다. 0부터 9, A부터 D, # 및 * 문자는 대응하는 DTMF 톤을 생성한다. a부터 d 문자는 반드시 입력 시 대문자로 정규화해야 하며 A부터 D와 동등하다. [RTCWEB-AUDIO ] 3절에 설명된 대로 0부터 9, A부터 D, # 및 * 문자의 지원은 필수이다. ',' 문자는 반드시 지원해야 하며, tones 매개변수의 다음 문자를 처리하기 전에 2초 지연을 나타낸다. 그 밖의 모든 문자(그리고 오직 그 밖의 문자만)는 반드시 인식되지 않는 문자로 간주해야 한다.

duration 매개변수는 tones 매개변수로 전달된 각 문자에 사용할 지속 시간을 ms 단위로 나타낸다. 지속 시간은 6000 ms를 초과하거나 40 ms 미만일 수 없다. 기본 지속 시간은 각 톤마다 100 ms이다.

interToneGap 매개변수는 톤 사이의 간격을 ms 단위로 나타낸다. 사용자 에이전트는 최소 30 ms, 최대 6000 ms로 제한한다. 기본값은 70 ms이다.

브라우저는 경우에 따라 duration과 interToneGap 시간을 늘려 DTMF의 시작 및 종료 시점이 RTP 패킷 경계에 맞도록 할 수 있다. 그러나 반드시 어느 쪽도 단일 RTP 오디오 패킷의 지속 시간보다 더 많이 늘려서는 안 된다.

insertDTMF() 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. sender를 DTMF 송신에 사용하는 RTCRtpSender로 둔다.
  2. transceiver를 RTCRtpTransceiver 객체로 두며, 이 객체는 sender와 연결되어 있다.

  3. dtmf를 RTCDTMFSender로 두며, 이는 sender와 연결되어 있다.
  4. DTMF 송신 가능 여부를 판단하는 절차가 dtmf에 대해 false를 반환하면 예외를 던지는 절차로 InvalidStateError를 던진다.
  5. tones를 메서드의 첫 번째 인수로 둔다.
  6. duration를 메서드의 두 번째 인수로 둔다.
  7. interToneGap를 메서드의 세 번째 인수로 둔다.
  8. tones에 unrecognized 문자가 하나라도 포함되어 있으면 예외를 던지는 절차로 InvalidCharacterError를 던진다.
  9. 객체의 [[ToneBuffer]] 슬롯을 tones로 설정한다.
  10. dtmf.[[Duration]] 를 duration의 값으로 설정한다.
  11. dtmf.[[InterToneGap]]를 interToneGap의 값으로 설정한다.
  12. duration의 값이 40 ms보다 작으면 dtmf.[[Duration]]를 40 ms로 설정한다.
  13. duration 매개변수의 값이 6000 ms보다 크면 dtmf.[[Duration]]를 6000 ms로 설정한다.
  14. interToneGap의 값이 30 ms보다 작으면 dtmf.[[InterToneGap]]를 30 ms로 설정한다.
  15. interToneGap의 값이 6000 ms보다 크면 dtmf.[[InterToneGap]]를 6000 ms로 설정한다.
  16. [[ToneBuffer]] 슬롯이 빈 문자열이면 이 단계들을 중단한다.
  17. 다음 절차를 실행 하는 태스크 가 DTMF 재생 태스크 단계 로서 이미 실행되도록 예약되어 있으면 이 단계들을 중단한다. 그렇지 않으면 다음 절차를 실행하는 태스크를 큐에 넣는다: DTMF 재생 태스크 단계:
    1. transceiver.[[CurrentDirection]]가 DTMF 송신 가능 여부를 판단하는 절차가 "sendrecv "도 "sendonly"도 아니 dtmf에 대해 false를 반환하면 이 단계들을 중단한다.
    2. [[ToneBuffer]] 슬롯이 빈 문자열을 포함하면 이벤트를 발생시키는 절차를 실행한다. 이름은 tonechange이고 RTCDTMFToneChangeEvent 인터페이스를 사용하며 tone 속성을 빈 문자열로 설정하고 대상은 RTCDTMFSender 객체로 한다. 그리고 이 단계들을 중단한다.
    3. [[ToneBuffer]] 슬롯에서 첫 문자를 제거하고 그 문자를 tone으로 둔다.
    4. tone이 ","이면 연결된 RTP 미디어 스트림에서 톤 전송을 2000 ms 동안 지연시키고, 현재부터 2000 ms 뒤에 DTMF 재생 태스크 단계를 실행할 태스크를 큐에 넣는다.
    5. tone이 ","가 아니면 대응하는 RTP 미디어 스트림에서 적절한 코덱을 사용하여 tone을 [[Duration]] ms 동안 재생하기 시작한다. 그런 다음 현재부터 [[Duration]] + [[InterToneGap]] ms 뒤에 실행될 태스크를 큐에 넣으며, 이 태스크는 DTMF 재생 태스크 단계를 실행한다.
    6. 이벤트를 발생시킨다. 이름은 tonechange이고 RTCDTMFToneChangeEvent 인터페이스를 사용하며 tone 속성을 tone으로 설정한다. 대상은 RTCDTMFSender 객체이다.

insertDTMF는 톤 버퍼를 대체하므로, 재생 중인 DTMF 톤에 톤을 추가하려면 insertDTMF 를 호출할 때 남은 톤([[ToneBuffer]] 슬롯에 저장됨)과 새 톤을 이어 붙인 문자열을 전달해야 한다. insertDTMF를 빈 tones 매개변수로 호출하면 현재 재생 중인 톤 이후에 재생하도록 큐에 넣은 모든 톤을 취소할 수 있다.

7.3 canInsertDTMF 알고리즘

DTMF 송신 가능 여부를 판단하는 절차를 RTCDTMFSender 인스턴스 dtmfSender에 대해 실행하려면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. sender를 RTCRtpSender로 두며, 이는 dtmfSender와 연결되어 있다.
  2. transceiver를 RTCRtpTransceiver로 두며, 이는 sender와 연결되어 있다.
  3. connection를 RTCPeerConnection로 두며, 이는 transceiver와 연결되어 있다.
  4. connection의 RTCPeerConnectionState가 " connected"가 아니면 false를 반환한다.
  5. transceiver.[[Stopping]]가 true이면 false를 반환한다.
  6. sender.[[SenderTrack]]가 null이면 false를 반환한다.
  7. transceiver.[[CurrentDirection]]가 " sendrecv"도 " sendonly "도 아니면 false를 반환한다.
  8. sender.[[SendEncodings]][0].active가 false이면 false를 반환한다.
  9. mimetype이 "audio/telephone-event" 인 코덱이 이 sender의 송신용으로 협상되지 않았으면 false를 반환한다.
  10. 그렇지 않으면 true를 반환한다.

7.4 RTCDTMFToneChangeEvent

tonechange 이벤트는 RTCDTMFToneChangeEvent 인터페이스를 사용한다.

WebIDL[Exposed=Window]
interface RTCDTMFToneChangeEvent : Event {
  constructor(DOMString type, optional RTCDTMFToneChangeEventInit eventInitDict = {});
  readonly attribute DOMString tone;
};

Constructors

RTCDTMFToneChangeEvent.constructor()

Attributes

tone of type DOMString, readonly

tone 속성은 방금 재생을 시작한 톤의 문자("," 포함)를 포함한다( insertDTMF 참조). 값이 빈 문자열이면 [[ToneBuffer]] 슬롯이 빈 문자열이고 이전 톤들의 재생이 완료되었음을 나타낸다.

WebIDL          dictionary RTCDTMFToneChangeEventInit : EventInit {
  DOMString tone = "";
};

Dictionary RTCDTMFToneChangeEventInit Members

tone of type DOMString, defaulting to ""

tone 속성은 방금 재생을 시작한 톤의 문자("," 포함)를 포함한다( insertDTMF 참조). 값이 빈 문자열이면 [[ToneBuffer]] 슬롯이 빈 문자열이고 이전 톤들의 재생이 완료되었음을 나타낸다.

8. 통계 모델

8.1 소개

기본 통계 모델은 브라우저가 모니터링되는 객체의 통계 집합을 통계 객체 형태로 유지하는 것이다.

관련 객체들의 그룹은 선택자로 참조할 수 있다. 예를 들어 선택자는 MediaStreamTrack일 수 있다. 트랙이 유효한 선택자이려면 반드시 MediaStreamTrack이어야 하며, 통계 요청이 발행된 RTCPeerConnection 객체에서 송신하거나 수신하는 트랙이어야 한다. 호출하는 웹 애플리케이션은 선택자를 getStats() 메서드에 제공하며, 브라우저는 통계 선택 알고리즘에 따라 선택자와 관련된 통계 집합을 JavaScript로 내보낸다. 이 알고리즘은 선택자의 송신자 또는 수신자를 입력으로 받는다.

통계 객체에서 반환하는 통계는 반복된 질의를 RTCStats의 id 사전 멤버로 연결할 수 있도록 설계되어 있다. 따라서 웹 애플리케이션은 주어진 기간의 시작과 끝에서 측정을 요청하여 그 기간에 걸친 측정을 수행할 수 있다.

일부 예외를 제외하면 모니터링되는 객체는 생성된 뒤 연결된 RTCPeerConnection이 존재하는 동안 유지된다. 따라서 해당 피어 연결이 닫힌 뒤에도 getStats() 결과에서 그 통계를 사용할 수 있다. 여기서 연결을 닫는 것은 close 절차를 뜻한다.

일부 모니터링되는 객체만 더 짧은 수명을 가진다. 이러한 객체의 통계는 이후 getStats() 결과에서 더 이상 사용할 수 없다. [ WEBRTC-STATS]의 객체 설명에는 이러한 모니터링되는 객체가 언제 삭제되는지 설명되어 있다.

8.2 RTCPeerConnection 인터페이스 확장

통계 API는 아래에 설명된 대로 RTCPeerConnection 인터페이스를 확장한다.

WebIDL          partial interface RTCPeerConnection {
  Promise<RTCStatsReport> getStats(optional MediaStreamTrack? selector = null);
};

Methods

getStats

주어진 선택자에 대한 통계를 수집하고 결과를 비동기적으로 보고한다.

getStats() 메서드가 호출되면 사용자 에이전트는 반드시 다음 단계를 실행해야 한다:

  1. selectorArg를 메서드의 첫 번째 인수로 둔다.

  2. connection를 메서드가 호출된 RTCPeerConnection 객체로 둔다.

  3. selectorArg가 null이면 selector를 null로 둔다.

  4. selectorArg가 MediaStreamTrack이면 selector를 RTCRtpSender 또는 RTCRtpReceiver로 두되, connection에 속하며 track 속성이 selectorArg와 일치하는 것으로 한다. 그러한 송신자나 수신자가 없거나 이 조건에 맞는 송신자 또는 수신자가 둘 이상이면, 거부된 상태인 프로미스를 반환한다. 이때 거부 사유는 새로 생성한 InvalidAccessError이다.

  5. p를 새 프로미스로 둔다.

  6. 다음 단계를 병렬로 실행한다:

    1. selector가 나타내는 통계를 통계 선택 알고리즘에 따라 수집한다.

    2. 전역 태스크를 큐에 넣는다. 이 태스크의 소스는 네트워킹 태스크 소스이고, 현재 렐름의 전역 객체를 global로 사용한다. 태스크는 결정 절차로 p를 결정하며, 그 값은 수집한 통계를 포함하는 결과 RTCStatsReport 객체이다.

  7. p를 반환한다.

8.3 RTCStatsReport 객체

getStats() 메서드는 성공 결과를 RTCStatsReport 객체 형태로 전달한다. RTCStatsReport 객체는 검사한 객체를 식별하는 문자열(id 속성으로서 RTCStats 인스턴스에 존재함)과 대응하는 RTCStats 파생 사전 사이의 맵이다.

RTCStatsReport 는 여러 RTCStats 파생 사전으로 구성될 수 있으며, 각 사전은 구현이 선택자와 관련 있다고 판단한 기반 객체 하나의 통계를 보고한다. 선택자에 대한 합계는 특정 유형의 통계를 모두 더하여 구한다. 예를 들어 RTCRtpSender가 네트워크로 트랙을 전달하는 데 여러 SSRC를 사용하면, RTCStatsReport에는 SSRC마다 하나의 RTCStats 파생 사전이 포함될 수 있다( ssrc 통계 속성의 값으로 구별할 수 있음).

WebIDL[Exposed=Window]
interface RTCStatsReport {
  readonly maplike<DOMString, object>;
};

이들을 사용하여 이 통계 보고서를 구성하는 다양한 RTCStats 파생 사전을 가져온다. 지원되는 속성 이름의 집합[WEBIDL]은 이 통계 보고서에 대해 생성된 모든 RTCStats 파생 사전의 ID로 정의된다.

8.4 RTCStats 딕셔너리

RTCStats 사전은 통계 객체를 나타내며, 이 객체는 특정 모니터링되는 객체를 검사하여 구성된다. RTCStats 사전은 timestamp와 type 같은 기본 속성의 집합을 지정하는 기반 유형이다. 구체적인 통계는 RTCStats 사전을 확장하여 추가한다.

통계 이름은 표준화되어 있지만, 특정 구현은 실험적인 값이나 웹 애플리케이션이 아직 알지 못하는 값을 사용할 수 있다. 따라서 애플리케이션은 반드시 알 수 없는 통계를 처리할 준비가 되어 있어야 한다.

계산에서 타당한 값을 얻으려면 통계가 서로 동기화되어야 한다. 예를 들어 bytesSent와 packetsSent를 모두 보고한다면, "평균 패킷 크기"를 "바이트 / 패킷"으로 계산할 수 있도록 둘 다 같은 구간에 대해 보고해야 한다. 구간이 다르면 오류가 생긴다. 따라서 구현은 반드시 RTCStats 파생 사전의 모든 통계에 대해 동기화된 값을 반환해야 한다.

WebIDLdictionary RTCStats {
  required DOMHighResTimeStamp timestamp;
  required RTCStatsType type;
  required DOMString id;
};

Dictionary RTCStats Members

timestamp of type DOMHighResTimeStamp
Candidate Correction 50:Use Performance.timeOrigin + Performance.now() for stats timestamps (PR #3005)

timestamp 의 유형은 타임스탬프는 DOMHighResTimeStamp 이며, 이 객체와 연결된 타임스탬프이다. 시각은 UNIX 에포크(1월 1일, [HIGHRES-TIME]1970년, 로 표현되며 다음 값으로 정의한다: Performance.timeOrigin UTC)를 기준으로 한다 + Performance.now() (정보를 수집하는 시점에 평가한 값). 원격 소스에서 온 통계(예: 수신한 RTCP 패킷에서 온 통계)의 경우, timestamp는 정보가 로컬 끝점에 도착한 시각을 나타낸다. 해당되는 경우 원격 타임스탬프는 RTCStats 파생 사전의 추가 필드에서 찾을 수 있다.

type of type RTCStatsType

이 객체의 유형이다.

type 속성은 반드시 이 RTCStats 사전이 나타내는 가장 구체적인 유형의 이름으로 초기화해야 한다.

id of type DOMString

고유 id로서, 이 RTCStats 객체를 생성하기 위해 검사한 객체와 연결되어 있다. 서로 다른 두 RTCStats 객체를 서로 다른 두 RTCStatsReport 객체에서 가져왔을 때, 반드시 같은 기반 객체를 검사하여 생성된 것이라면 같은 ID를 가져야 한다.

통계 ID는 절대로 애플리케이션이 예측할 수 있어서는 안 된다. 이는 애플리케이션이 특정 사용자 에이전트의 ID 생성 방식에 의존하지 못하게 한다. 특정 통계 객체의 ID를 이미 읽지 않았다면 그 ID로 통계 객체를 가져올 수 없기 때문이다.

사용자 에이전트는 위 요건을 충족하는 한 ID의 형식을 자유롭게 선택할 수 있다.

Note

사용자 에이전트는 피어 연결마다 고유한 솔트를 사용하는 한 해시 함수로 예측 가능하게 생성된 문자열을 예측할 수 없는 문자열로 바꿀 수 있다. 따라서 구현은 내부적으로 예측 가능한 ID를 사용할 수 있으며, 이는 getStats() 호출 전반에 걸쳐 통계 객체가 안정적인 ID를 유지하도록 보장하기 쉽게 만들 수 있다.

RTCStatsType의 유효한 값 집합과 그 값이 나타내는 RTCStats 파생 사전은 [ WEBRTC-STATS ]에 문서화되어 있다.

8.5 통계 선택 알고리즘

통계 선택 알고리즘은 다음과 같다:

  1. result를 빈 RTCStatsReport로 둔다.
  2. selector가 null 이면 전체 connection의 통계를 수집하여 result에 추가하고 result를 반환한 다음 이 단계들을 중단한다.
  3. 만약 selector 가다음 형식이면: RTCRtpSender, 다음 객체들에 대한 통계를 수집하여 다음 결과에 추가 한다: result:
  4. 만약 selector 가다음 형식이면: RTCRtpReceiver, 다음 객체들에 대한 통계를 수집하여 다음 결과에 추가 한다: result:
  5. result를 반환한다.

8.6 구현 필수 통계

[ WEBRTC-STATS ]에 나열된 통계는 다양한 사용 사례를 다루기 위한 것이다. 모든 WebRTC 구현이 그 전부를 구현해야 하는 것은 아니다.

구현은 반드시 다음 type의 통계 생성을 지원해야 한다. 이는 대응하는 객체가 RTCPeerConnection 에 존재할 때 적용되며, RTCStats 사전에 정의된 일반 필드 외에 해당 객체에 유효한 경우 나열된 필드들도 포함해야 한다:

RTCStatsType Dictionary Fields
"codec" RTCCodecStats payloadType, mimeType, clockRate, channels, sdpFmtpLine
"inbound-rtp" RTCRtpStreamStats ssrc, kind, transportId, codecId
RTCReceivedRtpStreamStats packetsReceived, packetsLost, jitter,
RTCInboundRtpStreamStats trackIdentifier, remoteId, framesDecoded, framesDropped nackCount, framesReceived, bytesReceived, totalAudioEnergy, totalSamplesDuration packetsDiscarded,
"outbound-rtp" RTCRtpStreamStats ssrc, kind, transportId, codecId
RTCSentRtpStreamStats packetsSent, bytesSent
RTCOutboundRtpStreamStats remoteId, framesEncoded, nackCount, framesSent
"remote-inbound-rtp" RTCRtpStreamStats ssrc, kind, transportId, codecId
RTCReceivedRtpStreamStats packetsReceived, packetsLost, jitter
RTCRemoteInboundRtpStreamStats localId, roundTripTime
"remote-outbound-rtp" RTCRtpStreamStats ssrc, kind, transportId, codecId
RTCSentRtpStreamStats packetsSent, bytesSent
RTCRemoteOutboundRtpStreamStats localId, remoteTimestamp
"media-source" RTCMediaSourceStats trackIdentifier, kind
RTCAudioSourceStats totalAudioEnergy, totalSamplesDuration (송신기에 연결된 오디오 트랙에 대한 항목)
RTCVideoSourceStats width, height, framesPerSecond (송신기에 연결된 비디오 트랙에 대한 항목)
"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 ]에 정의된 다른 어떤 통계의 생성도 지원할 수 있으며, 경우에 따라 문서화되지 않은 통계를 생성할 수도 있다.

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. 네트워크 사용을 위한 Media Stream API 확장

9.1 소개

MediaStreamTrack 인터페이스는 [ GETUSERMEDIA] 명세에 정의된 대로 일반적으로 오디오 또는 비디오 데이터의 스트림을 나타낸다. 하나 이상의 MediaStreamTrack 을 MediaStream에 모을 수 있다(엄밀히 말하면, MediaStream은 [GETUSERMEDIA]에 정의된 대로 0개 이상의 MediaStreamTrack 객체를 포함할 수 있다).

MediaStreamTrack은 예를 들어 로컬 카메라뿐 아니라 원격 피어에서 오거나 원격 피어로 보내는 미디어 흐름도 나타내도록 확장할 수 있다. 이 절에서는 MediaStreamTrack 객체에서 이 기능을 활성화하는 데 필요한 확장을 설명한다. 미디어를 피어로 전송하는 방식은 [ RFC8834], [RFC7874] 및 [RFC8835]에 설명되어 있다.

다른 피어로 전송된 MediaStreamTrack은 수신자에게 정확히 하나의 MediaStreamTrack으로 나타난다. 피어는 이 명세를 지원하는 사용자 에이전트로 정의된다. 또한 송신 측 애플리케이션은 어떤 MediaStream 객체에 해당 MediaStreamTrack이 속하는지 나타낼 수 있다. 수신 측의 대응하는 MediaStream 객체는 아직 없으면 생성되며 그에 따라 내용이 채워진다.

이 문서의 앞부분에서도 설명한 대로, 애플리케이션은 RTCRtpSender와 RTCRtpReceiver 객체를 사용하여 MediaStreamTrack의 전송과 수신을 더 세밀하게 제어할 수 있다.

채널은 Media Capture and Streams 명세에서 다루는 가장 작은 단위이다. 채널들은 함께 인코딩되어 예를 들어 하나의 RTP 페이로드 유형으로 전송되도록 의도되어 있다. 코덱이 함께 인코딩해야 하는 모든 채널은 반드시 같은 MediaStreamTrack에 있어야 하며, 코덱은 가급적 트랙의 모든 채널을 인코딩하거나 버릴 수 있어야 한다.

주어진 MediaStreamTrack의 입력과 출력이라는 개념은 네트워크로 전송되는 MediaStreamTrack 객체에도 적용된다. MediaStreamTrack이 RTCPeerConnection 객체에 의해 생성되면(이 문서의 앞부분에 설명된 대로), 원격 피어에서 받은 데이터를 입력으로 사용한다. 마찬가지로 로컬 소스에서 온 MediaStreamTrack(예: [GETUSERMEDIA]를 통한 카메라)은 RTCPeerConnection 객체와 함께 사용되면 원격 피어로 전송되는 것을 나타내는 출력을 갖는다.

MediaStream과 MediaStreamTrack 객체의 복제라는 개념은 [GETUSERMEDIA]에 설명된 대로 여기에도 적용된다. 예를 들어 화상 회의에서 이 기능을 사용하면 사용자의 카메라와 마이크에서 온 로컬 비디오를 로컬 모니터에 표시하면서 원격 피어에는 오디오만 전송할 수 있다(예: 사용자가 "비디오 음소거" 기능을 사용한 경우). 서로 다른 MediaStreamTrack 객체를 새로운 MediaStream 객체로 조합하는 것은 특정 상황에서 유용하다.

Note

이 문서에서는 다음 객체들에 대해 RTCPeerConnection 과 함께 사용할 때 관련된 측면만 지정한다. [ GETUSERMEDIA] 문서에 있는 객체의 원래 정의에서 MediaStream과 MediaStreamTrack의 사용에 관한 일반 정보를 참조하기 바란다.

9.2 MediaStream

9.2.1 id

id 속성은 MediaStream에 지정되어 있으며 이 스트림에 고유한 ID를 반환한다. 따라서 RTCPeerConnection API의 원격 끝점에서 스트림을 알아볼 수 있다.

MediaStream이 원격 피어에서 얻은 스트림을 나타내기 위해 생성되면 id 속성은 원격 소스가 제공한 정보로 초기화한다.

Note

id는 MediaStream 객체에서 스트림의 소스에 대해 고유하지만, 그렇다고 중복이 생길 수 없다는 뜻은 아니다. 예를 들어 로컬에서 생성된 스트림의 트랙을 한 사용자 에이전트에서 원격 피어로 RTCPeerConnection을 사용하여 보낸 다음, 같은 방식으로 원래 사용자 에이전트에 돌려보낼 수 있다. 그러면 원래 사용자 에이전트에는 같은 id를 가진 여러 스트림(로컬에서 생성한 스트림과 원격 피어에서 받은 스트림)이 존재한다.

9.3 MediaStreamTrack

MediaStreamTrack 객체의 MediaStream 에 대한 참조는 비로컬 미디어 소스의 경우 항상 강한 참조이다. 이는 MediaStreamTrack마다 존재하는 RTP 소스의 경우이며 해당 트랙은 RTCRtpReceiver와 연결되어 있다.

RTCRtpReceiver가 RTP 소스에서 데이터를 받을 때마다, 대응하는 MediaStreamTrack이 음소거되어 있으나 종료되지는 않았고, [[Receptive]] 슬롯이 해당 RTCRtpTransceiver 객체에서, 즉 이 RTCRtpReceiver가 속하는 객체에서 true이면, 반드시 태스크를 큐에 넣어 음소거 상태를 설정하는 절차로 대응하는 MediaStreamTrack의 음소거 상태를 false로 설정해야 한다.

RTCRtpReceiver가 수신하는 RTP 소스 미디어 스트림의 SSRC 중 하나가 BYE 수신이나 시간 초과로 제거되면, 반드시 태스크를 큐에 넣어 음소거 상태를 설정하는 절차로 대응하는 MediaStreamTrack의 음소거 상태를 true로 설정해야 한다. setRemoteDescription 도 음소거 상태 설정을 유발할 수 있으며, 이때 track의 음소거 상태를 true로 설정한다.

트랙을 추가하는, 트랙을 제거하는 및 트랙의 음소거 상태를 설정하는 절차는 [ GETUSERMEDIA ]에 지정되어 있다.

MediaStreamTrack인 track이 RTCRtpReceiver receiver에 의해 생성되었고 ended 상태가 되면[GETUSERMEDIA](예: receiver.track.stop 호출을 통해), 사용자 에이전트는 경우에 따라 수신 스트림에 할당한 리소스를 해제하도록 선택할 수 있다. 예를 들어 receiver의 디코더를 끌 수 있다.

9.3.1 MediaTrackSupportedConstraints, MediaTrackCapabilities, MediaTrackConstraints 및 MediaTrackSettings

제약 및 제약 가능한 속성의 개념은 MediaTrackConstraints(MediaStreamTrack.getConstraints(), MediaStreamTrack.applyConstraints())와 MediaTrackSettings( MediaStreamTrack.getSettings())를 포함하여 [GETUSERMEDIA]에 개략적으로 설명되어 있다. 그러나 피어 연결에서 온 트랙의 제약 가능한 속성은 getUserMedia()에서 온 트랙의 속성과 다르다. MediaStreamTrack 중 원격 소스에서 온 트랙에 적용되는 제약과 설정은 여기에서 정의한다. 원격 트랙의 설정은 가장 최근에 받은 프레임을 나타낸다.

MediaStreamTrack.getCapabilities()는 반드시 항상 빈 집합을 반환해야 하며, MediaStreamTrack.applyConstraints()는 반드시 여기에서 정의한 제약에 대해 원격 트랙에서 항상 OverconstrainedError 로 거부되어야 한다.

다음의 제약 가능한 속성은 비디오 MediaStreamTrack 중 원격 소스에서 온 트랙에 적용되도록 정의된다:

Property Name Values Notes
width ConstrainULong 설정으로서 는 가장 최근에 수신한 프레임의 너비를 나타내 는 값이며 이 너비의 단위는 픽셀이다.
height ConstrainULong 설정으로서 는 가장 최근에 수신한 프레임의 높이를 나타내 는 값이며 이 높이의 단위는 픽셀이다.
frameRate ConstrainDouble 설정으로서 는 최근에 수신된 프레임들 을 기준 으로 계산한 프레임 속도의 추정값 을 나타내 는 설정값이다.
aspectRatio ConstrainDouble 설정으로서 는 가장 최근 프레임 의 종횡비 를 나타낸다. 이는 픽셀 단위의 너비를 픽셀 단위 의 높이 로 나눈 값이며 소수점 아래 열 번째 자리 까지 반올림한 double 값 으로 표현 된다.

이 문서는 오디오 MediaStreamTrack 중 원격 소스에서 온 트랙에 적용되는 제약 가능한 속성을 정의하지 않는다.

10. 예제 및 호출 흐름

이 절은 비규범적이다.

10.1 간단한 피어 투 피어 예제

두 피어가 서로 연결을 설정하기로 결정하면 양쪽 모두 다음 단계를 거친다. STUN/TURN 서버 구성은 공개 IP 주소 등을 알아내거나 NAT 통과를 설정하는 데 사용할 수 있는 서버를 설명한다. 또한 두 피어는 처음에 통신하기로 합의하는 데 사용한 것과 같은 대역 외 메커니즘을 사용하여 시그널링 채널의 데이터를 서로에게 보내야 한다.

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 예제

예제들은 sender가 RTCRtpSender라고 가정한다.

DTMF 신호 "1234"를 각 톤당 500 ms의 지속 시간으로 전송한다:

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 완벽한 협상 예제

완전 협상은 이 비대칭 작업을 애플리케이션의 다른 부분에서 추상화하여 협상을 투명하게 관리하기 위한 권장 패턴이다. 이 패턴은 한쪽이 항상 제안자인 방식보다 장점이 있다. 충돌(glare, " stable" 상태가 아닐 때 제안이 들어오는 것)의 위험 없이 애플리케이션이 양쪽 피어 연결 객체에서 동시에 작업할 수 있기 때문이다. 애플리케이션의 다른 부분은 시그널링 상태의 경쟁을 걱정하지 않고 모든 수정 메서드와 속성을 사용할 수 있다.

두 피어에 서로 다른 역할을 부여하고 그 사이의 시그널링 충돌을 해결하는 동작을 지정한다:

  1. 양보 측 피어는 수신 제안과의 충돌을 피하기 위해 롤백을 사용한다.

  2. 비양보 측 피어는 자신의 제안과 충돌하는 수신 제안을 무시한다.

두 피어는 함께 애플리케이션의 다른 부분을 위해 교착 상태가 생기지 않도록 시그널링을 관리한다. 예제는 지정된 역할을 나타내는 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 변수는 비양보 측의 RTCPeerConnection 객체에 무시된 제안을 알리지 않기 때문에 필요하다. 따라서 그러한 제안에 속한 수신 후보에서 발생하는 오류를 억제해야 한다.

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. DOMException 생성자를 e에 대해 호출하며, message 인수는 message로, name 인수는 "OperationError"로 설정한다.

    Note

    이 이름은 레거시 코드에 대응하지 않으므로 e.code는 0을 반환한다.

  5. 모든 RTCError 속성을 e에 대해 설정한다. 대응하는 속성이 init 에 있으면 그 값으로 설정하고, 그렇지 않으면 null로 설정한다.

  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 경고의 값이다.

(Feature at Risk) Issue 1

RTCError에 정의된 모든 속성은 구현 부족으로 인해 제거될 수 있는 항목(at risk)으로 표시되어 있다(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, receivedAlert 및 sentAlert는 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 Enumeration description
Enum value Description
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 객체에서 발생한다:

Event name Interface Fired when...
open Event 해당 RTCDataChannel 객체의 기반 데이터 전송 연결이 수립되었 거나 다시 수립되었다.
message MessageEvent [html] 메시지를 성공적으로 수신한 상태가 되었다.
bufferedamountlow Event 해당 RTCDataChannel 객체의 bufferedAmount 값이다음 임계값보다 높은상태에서 감소한다: bufferedAmountLowThreshold 그 결과 다음 임계값 이하 가 된다: bufferedAmountLowThreshold.
error RTCErrorEvent 데이터 채널 에서 오류가 발생한 상태가 되었다.
closing Event 해당 RTCDataChannel 객체가 다음 상태로 전이한다. 그값은"closing" 상태이다
close Event 해당 RTCDataChannel 객체의 기반 데이터 전송 이 닫힌 상태이다.

다음 이벤트는 RTCPeerConnection 객체에서 발생한다:

Event name Interface Fired when...
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 해당 RTCPeerConnection.connectionState 가 변경되었다.
icecandidateerror RTCPeerConnectionIceErrorEvent ICE 후보를 수집하는 도중 실패가 발생한 상태이다.
datachannel RTCDataChannelEvent 새로운 한 RTCDataChannel 이 다른 피어 의 채널 생성 에 대한 응답 으 로 스크립트 에 전달되었다.

다음 이벤트는 RTCDTMFSender 객체에서 발생한다:

Event name Interface Fired when...
tonechange RTCDTMFToneChangeEvent 해당 RTCDTMFSender 객체 가 방금 톤 의 재생 을 시작했으며 그 톤 은 다음 tone 속성으로 반환된다. 또는다음 버퍼에 들어 있는 톤들의 재생을 방금 끝냈으며: toneBuffer 이 경우에는 다음 속성에서 빈 값이 반환된다: tone 속성이다.

다음 이벤트는 RTCIceTransport 객체에서 발생한다:

Event name Interface Fired when...
statechange Event 해당 RTCIceTransport 상태가 변경된다.
gatheringstatechange Event 해당 RTCIceTransport 후보수집 상태가 변경된다.
selectedcandidatepairchange Event 해당 RTCIceTransport에서 선택된 후보 쌍이 변경된다.

다음 이벤트는 RTCDtlsTransport 객체에서 발생한다:

Event name Interface Fired when...
statechange Event 해당 RTCDtlsTransport 상태가 변경된다.
error RTCErrorEvent 다음 전송에서 오류가 발생 했다: RTCDtlsTransport (유형은 "dtls-failure" 또는 "fingerprint-failure"이다).

다음 이벤트는 RTCSctpTransport 객체에서 발생한다:

Event name Interface Fired when...
statechange Event 해당 RTCSctpTransport 상태가 변경된다.

13. 개인정보 보호 및 보안 고려 사항

이 절은 비규범적이다.

이 절은 비규범적이다. 새로운 동작을 지정하지 않고 명세의 다른 부분에 이미 있는 정보를 요약한다. WebRTC에서 사용하는 일반적인 API 및 프로토콜 집합의 전반적인 보안 고려 사항은 [ RFC8827]에 설명되어 있다.

13.1 동일 출처 정책에 미치는 영향

이 문서는 브라우저와 다른 장치(다른 브라우저 포함) 사이에 실시간 직접 통신을 설정하는 기능으로 웹 플랫폼을 확장한다.

이는 서로 다른 브라우저에서 실행되는 애플리케이션 사이 또는 같은 브라우저에서 실행되는 애플리케이션과 브라우저가 아닌 대상 사이에서 데이터와 미디어를 공유할 수 있다는 뜻이다. 이는 출처가 다른 주체 사이의 데이터 전송을 제한하는 웹 모델의 일반적인 경계를 넘어서는 것이다.

WebRTC 명세는 통신에 대한 사용자 프롬프트나 브라우저 UI 표시를 제공하지 않는다. 웹 페이지가 미디어 접근을 허용받으면 그 미디어를 원하는 다른 주체와 자유롭게 공유할 수 있다고 가정한다. 따라서 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.getCapabilities와 RTCRtpReceiver.getCapabilities 메서드로 기반 미디어 시스템의 정보를 노출한다. 여기에는 시스템이 생성하고 소비할 수 있는 코덱의 상세하고 순서가 있는 정보가 포함된다. 그 정보의 부분집합은 세션 협상 중에 생성되고 노출되며 전송되는 SDP 세션 설명에 표현될 가능성이 크다. 이 정보는 대부분 시간과 출처를 넘어 지속되며 해당 장치의 핑거프린팅 가능 범위를 늘린다.

DTLS 연결을 설정할 때 WebRTC API는 애플리케이션이 예를 들어 IndexedDB에 지속적으로 저장할 수 있는 인증서를 생성할 수 있다. 이러한 인증서는 출처 간에 공유되지 않으며 해당 출처의 영구 저장소를 지우면 함께 지워진다.

13.6 원격 엔드포인트의 SDP 설정

setRemoteDescription은 예외를 던져 잘못된 형식의 SDP와 유효하지 않은 SDP를 방어하지만, 애플리케이션이 예상하지 못할 수 있는 SDP를 방어하려고 하지는 않는다. 원격 설명을 설정하면 이미지 버퍼와 네트워크 포트를 비롯한 상당한 리소스가 할당되거나 미디어가 흐르기 시작하는 등 여러 결과가 생길 수 있으며, 개인정보 보호와 대역폭에 영향을 줄 수 있다. 악의적인 SDP에 대비하지 않은 애플리케이션은 리소스 고갈이나 의도치 않은 수신 미디어 허용의 위험에 노출될 수 있고, 다른 끝점이 송신을 협상하지 않으면 ontrack 같은 특정 이벤트가 발생하지 않을 위험도 있다. 애플리케이션은 악의적인 SDP에 대비해야 한다.

14. 접근성 고려 사항

이 절은 비규범적이다.

WebRTC 1.0 명세는 실시간 오디오, 비디오 및 데이터 교환을 설정하는 데 필요한 프로토콜(IETF에서 정의됨)을 제어하는 API를 노출한다.

청각장애인용 통신 장치(TDD/TTY)는 청각 또는 언어 장애가 있는 사람 등을 포함한 사용자가 전화선을 통해 통신할 수 있도록 한다. [ 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 작업 그룹에서는 WebRTC 데이터 채널을 통한 실시간 텍스트 전송을 가능하게 하는 작업이 진행 중이다. 이를 통해 SCTP 데이터 채널 프로토콜과 RFC 4103 실시간 텍스트 사이를 변환하는 게이트웨이를 배포할 수 있다. 이 작업이 완료되면 게이트웨이를 통하거나 다른 방식으로 브라우저를 포함한 WebRTC 사용자 에이전트에 실시간 텍스트를 통합하는, 통일되고 상호운용 가능한 접근 방식을 제공할 것으로 예상된다.

이 문서 발행 시점에는 사용자 정의 WebRTC 데이터 채널 등을 통해 WebRTC 클라이언트에서 RTT를 효과적으로 지원하는 게이트웨이를 개발할 수 있다. SCTP 데이터 채널 프로토콜과 RFC 4103 실시간 텍스트 같은 IETF 프로토콜로 향후 표준화된 게이트웨이를 사용할 수 있게 될 때까지는 이것으로 충분하다고 간주한다. RTT 지원을 국제적으로 효과적이고 일관되게 표준화하려면 W3C 그룹의 관련 작업과 함께 IETF에서 이를 정의해야 한다.

A. 후보 수정안

W3C의 2021년 1월 권고안으로 발행된 이후 다음 후보 개정 사항이 이 문서에 통합되었다.

B. 감사의 말

The editors wish to thank the Working Group chairs and Team Contact, Harald Alvestrand, Stefan Håkansson, Erik Lagerway and Dominique Hazaël-Massieux, for their support. Substantial text in this specification was provided by many people including Martin Thomson, Harald Alvestrand, Justin Uberti, Eric Rescorla, Peter Thatcher, Jan-Ivar Bruaroey and Peter Saint-Andre. Dan Burnett would like to acknowledge the significant support received from Voxeo and Aspect during the development of this specification.

The RTCRtpSender and RTCRtpReceiver objects were initially described in the W3C ORTC CG, and have been adapted for use in this specification.

C. 참고 문헌

Candidate Correction 46:Replace RFC8829 reference with RFC9429 (PR #2966)

B.1 규범적 참고 문헌

C.1 Normative references

[DOM]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT-6.0]
ECMA-262 6th Edition, The ECMAScript 2015 Language Specification. Allen Wirfs-Brock. Ecma International. June 2015. Standard. URL: http://www.ecma-international.org/ecma-262/6.0/index.html
[Fetch]
Fetch Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://fetch.spec.whatwg.org/
[FILEAPI]
File API. Marijn Kruisselbrink; Arun Ranganathan. W3C. 11 September 20194 December 2024. W3C Working Draft. URL: https://www.w3.org/TR/FileAPI/
[FIPS-180-4]
FIPS PUB 180-4 180-4: Secure Hash StandardStandard (SHS). U.S. Department of Commerce/National Institute of Standards and Technology. August 2015. National Standard. URL: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
[GETUSERMEDIA]
Media Capture and Streams. Cullen Jennings; Bernard Aboba; Jan-Ivar Bruaroey; Henrik Boström; youenn fablet; Daniel Burnett; Adam Bergkvist; Anant Narayanan. W3C. 21 January 202119 December 2024. W3C Candidate RecommendationCRD. URL: https://www.w3.org/TR/mediacapture-streams/
[hr-time]
High Resolution Time Level 2Time. Ilya GrigorikYoav Weiss. W3C. 21 7 November 20192024. W3C RecommendationWorking Draft. URL: https://www.w3.org/TR/hr-time-2/org/TR/hr-time-3/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[IANA-HASH-FUNCTION]
Hash Function Textual Names. IANA. URL: https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml
[IANA-RTP-2]
RTP Payload Format media types. IANA. URL: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-2
[INFRA]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119https://www.rfc-editor.org/rfc/rfc2119
[RFC3550]
RTP: A Transport Protocol for Real-Time Applications. H. Schulzrinne; S. Casner; R. Frederick; V. Jacobson. IETF. July 2003. Internet Standard. URL: https://tools.ietf.org/html/rfc3550https://www.rfc-editor.org/rfc/rfc3550
[RFC3890]
A Transport Independent Bandwidth Modifier for the Session Description Protocol (SDP). M. Westerlund. IETF. September 2004. Proposed Standard. URL: https://tools.ietf.org/html/rfc3890https://www.rfc-editor.org/rfc/rfc3890
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax. T. Berners-Lee; R. Fielding; L. Masinter. IETF. January 2005. Internet Standard. URL: https://tools.ietf.org/html/rfc3986
[RFC4566]
SDP: Session Description Protocol. M. Handley; V. Jacobson; C. Perkins. IETF. July 2006. Proposed Standard. URL: https://tools.ietf.org/html/rfc4566https://www.rfc-editor.org/rfc/rfc4566
[RFC4572]
Connection-Oriented Media Transport over the Transport Layer Security (TLS) Protocol in the Session Description Protocol (SDP). J. Lennox. IETF. July 2006. Proposed Standard. URL: https://tools.ietf.org/html/rfc4572https://www.rfc-editor.org/rfc/rfc4572
[RFC5245]
Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols. J. Rosenberg. IETF. April 2010. Proposed Standard. URL: https://tools.ietf.org/html/rfc5245https://www.rfc-editor.org/rfc/rfc5245
[RFC5246]
The Transport Layer Security (TLS) Protocol Version 1.2. T. Dierks; E. Rescorla. IETF. August 2008. Proposed Standard. URL: https://tools.ietf.org/html/rfc5246https://www.rfc-editor.org/rfc/rfc5246
[RFC5285]
A General Mechanism for RTP Header Extensions. D. Singer; H. Desineni. IETF. July 2008. Proposed Standard. URL: https://tools.ietf.org/html/rfc5285https://www.rfc-editor.org/rfc/rfc5285
[RFC5389]
Session Traversal Utilities for NAT (STUN). J. Rosenberg; R. Mahy; P. Matthews; D. Wing. IETF. October 2008. Proposed Standard. URL: https://tools.ietf.org/html/rfc5389https://www.rfc-editor.org/rfc/rfc5389
[RFC5506]
Support for Reduced-Size Real-Time Transport Control Protocol (RTCP): Opportunities and Consequences. I. Johansson; M. Westerlund. IETF. April 2009. Proposed Standard. URL: https://tools.ietf.org/html/rfc5506https://www.rfc-editor.org/rfc/rfc5506
[RFC5888]
The Session Description Protocol (SDP) Grouping Framework. G. Camarillo; H. Schulzrinne. IETF. June 2010. Proposed Standard. URL: https://tools.ietf.org/html/rfc5888https://www.rfc-editor.org/rfc/rfc5888
[RFC6464]
A Real-time Transport Protocol (RTP) Header Extension for Client-to-Mixer Audio Level Indication. J. Lennox, Ed.; E. Ivov; E. Marocco. IETF. December 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6464https://www.rfc-editor.org/rfc/rfc6464
[RFC6465]
A Real-time Transport Protocol (RTP) Header Extension for Mixer-to-Client Audio Level Indication. E. Ivov, Ed.; E. Marocco, Ed.; J. Lennox. IETF. December 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6465https://www.rfc-editor.org/rfc/rfc6465
[RFC6544]
TCP Candidates with Interactive Connectivity Establishment (ICE). J. Rosenberg; A. Keranen; B. B. Lowekamp; A. B. Roach. IETF. March 2012. Proposed Standard. URL: https://tools.ietf.org/html/rfc6544https://www.rfc-editor.org/rfc/rfc6544
[RFC7064]
URI Scheme for the Session Traversal Utilities for NAT (STUN) Protocol. S. Nandakumar; G. Salgueiro; P. Jones; M. Petit-Huguenin. IETF. November 2013. Proposed Standard. URL: https://tools.ietf.org/html/rfc7064https://www.rfc-editor.org/rfc/rfc7064
[RFC7065]
Traversal Using Relays around NAT (TURN) Uniform Resource Identifiers. M. Petit-Huguenin; S. Nandakumar; G. Salgueiro; P. Jones. IETF. November 2013. Proposed Standard. URL: https://tools.ietf.org/html/rfc7065https://www.rfc-editor.org/rfc/rfc7065
[RFC7656]
A Taxonomy of Semantics and Mechanisms for Real-Time Transport Protocol (RTP) Sources. J. Lennox; K. Gross; S. Nandakumar; G. Salgueiro; B. Burman, Ed.. IETF. November 2015. Informational. URL: https://tools.ietf.org/html/rfc7656https://www.rfc-editor.org/rfc/rfc7656
[RFC7675]
Session Traversal Utilities for NAT (STUN) Usage for Consent Freshness. M. Perumal; D. Wing; R. Ravindranath; T. Reddy; M. Thomson. IETF. October 2015. Proposed Standard. URL: https://tools.ietf.org/html/rfc7675https://www.rfc-editor.org/rfc/rfc7675
[RFC7874]
WebRTC Audio Codec and Processing Requirements. JM. Valin; C. Bran. IETF. May 2016. Proposed Standard. URL: https://tools.ietf.org/html/rfc7874https://www.rfc-editor.org/rfc/rfc7874
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://tools.ietf.org/html/rfc8174https://www.rfc-editor.org/rfc/rfc8174
[RFC8261]
Datagram Transport Layer Security (DTLS) Encapsulation of SCTP Packets. M. Tuexen; R. Stewart; R. Jesup; S. Loreto. IETF. November 2017. Proposed Standard. URL: https://tools.ietf.org/html/rfc8261https://www.rfc-editor.org/rfc/rfc8261
[RFC8445]
Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal. A. Keranen; C. Holmberg; J. Rosenberg. IETF. July 2018. Proposed Standard. URL: https://tools.ietf.org/html/rfc8445https://www.rfc-editor.org/rfc/rfc8445
[RFC8656]
Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN). T. Reddy, Ed.; A. Johnston, Ed.; P. Matthews; J. Rosenberg. IETF. February 2020. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8656
[RFC8826]
Security Considerations for WebRTCfor WebRTC. E. Rescorla. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8826https://www.rfc-editor.org/rfc/rfc8826
[RFC8829]
JavaScript Session Establishment Protocol (JSEP). J. Uberti; C. Jennings; E. Rescorla, Ed.. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8829
[RFC8831]
WebRTC Data Channels. R. Jesup; S. Loreto; M. Tüxen. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8831https://www.rfc-editor.org/rfc/rfc8831
[RFC8832]
WebRTC Data Channel Establishment Protocol. R. Jesup; S. Loreto; M. Tüxen. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8832https://www.rfc-editor.org/rfc/rfc8832
[RFC8834]
Media Transport and Use of RTP in WebRTC. C. Perkins; M. Westerlund; J. Ott. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8834https://www.rfc-editor.org/rfc/rfc8834
[RFC8835]
Transports for WebRTC. H. Alvestrand. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8835https://www.rfc-editor.org/rfc/rfc8835
[RFC8838]
Trickle ICE: Incremental Provisioning of Candidates for the Interactive Connectivity Establishment (ICE) Protocol. E. Ivov; J. Uberti; P. Saint-Andre. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8838https://www.rfc-editor.org/rfc/rfc8838
[RFC8841]
Session Description Protocol (SDP) Offer/Answer Procedures for Stream Control Transmission Protocol (SCTP) over Datagram Transport Layer Security (DTLS) Transport. C. Holmberg; R. Shpount; S. Loreto; G. Camarillo. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8841https://www.rfc-editor.org/rfc/rfc8841
[RFC8843]
Negotiating Media Multiplexing Using the Session Description Protocol (SDP). C. Holmberg; H. Alvestrand; C. Jennings. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8843https://www.rfc-editor.org/rfc/rfc8843
[RFC8851]
RTP Payload Format Restrictions. A.B. Roach, Ed.. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8851https://www.rfc-editor.org/rfc/rfc8851
[RFC8853]
Using Simulcast in Session Description Protocol (SDP) and RTP Sessions. B. Burman; M. Westerlund; S. Nandakumar; M. Zanaty. IETF. January 2021. Proposed Standard. URL: https://tools.ietf.org/html/rfc8853https://www.rfc-editor.org/rfc/rfc8853
[RFC8863]
Interactive Connectivity Establishment Patiently Awaiting Connectivity (ICE PAC). C. Holmberg; J. Uberti. IETF. January 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8863
[RFC9429]
JavaScript Session Establishment Protocol (JSEP). J. Uberti; C. Jennings; E. Rescorla, Ed. IETF. April 2024. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9429
[SDP]
An Offer/Answer Model with Session Description Protocol (SDP). J. Rosenberg; H. Schulzrinne. IETF. June 2002. Proposed Standard. URL: https://tools.ietf.org/html/rfc3264https://www.rfc-editor.org/rfc/rfc3264
[STUN-PARAMETERS]
STUN Error Codes. IETF. IANA. April 2011. IANA Parameter Assignment. URL: https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml#stun-parameters-6
[WebCryptoAPI]
Web Cryptography API. Mark Watson. W3C. 26 January 2017. W3C Recommendation. URL: https://www.w3.org/TR/WebCryptoAPI/
[WEBIDL]
Web IDL. Boris Zbarsky. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBRTC-STATS]
Identifiers for WebRTC's Statistics API. Harald Alvestrand; Varun Singh; Henrik Boström. W3C. 20 January 20216 March 2025. W3C Candidate RecommendationCRD. URL: https://www.w3.org/TR/webrtc-stats/
[X509V3]
ITU-T Recommendation X.509 version 3 (1997). "Information Technology - Open Systems Interconnection - The Directory Authentication Framework"  ISO/IEC 9594-8:1997.. ITU.
[X690]
Recommendation X.690 — Information Technology — ASN.1 Encoding Rules — Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER), and Distinguished Encoding Rules (DER). ITU. URL: https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf

C.2 정보성 참고 문헌

[API-DESIGN-PRINCIPLES]
Web Platform Design Principles. Martin Thomson; Jeffrey Yasskin. W3C. 6 March 2025. W3C Working Group Note. URL: https://www.w3.org/TR/design-principles/
[INDEXEDDB]
Indexed Database API. Nikunj Mehta; Jonas Sicking; Eliot Graff; Andrei Popescu; Jeremy Orlow; Joshua Bell. W3C. 8 January 2015. W3C Recommendation. URL: https://www.w3.org/TR/IndexedDB/
[RFC4103]
RTP Payload for Text Conversation. G. Hellstrom; P. Jones. IETF. June 2005. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4103
[RFC6236]
Negotiation of Generic Image Attributes in the Session Description Protocol (SDP). I. Johansson; K. Jung. IETF. May 2011. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6236
[RFC7728]
RTP Stream Pause and Resume. B. Burman; A. Akram; R. Even; M. Westerlund. IETF. February 2016. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7728
[RFC8825]
Overview: Real-Time Protocols for Browser-Based Applications. H. Alvestrand. IETF. January 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8825
[RFC8827]
WebRTC Security Architecture. E. Rescorla. IETF. January 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8827
[RFC8828]
WebRTC IP Address Handling Requirements. J. Uberti; G. Shieh. IETF. January 2021. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8828