Initial Author of this Specification was Ian Hickson, Google Inc., with the following
copyright statement:
© Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera Software
ASA. You are granted a license to use, reproduce and create derivative works of this document.
All subsequent changes since 26 July 2011 done by the W3C WebRTC Working Group (and previously the Device APIs Working Group) are under the following Copyright © 2011-2023 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 문서는 오디오 및 비디오를 포함한 로컬 미디어를 플랫폼에서 요청할 수 있도록 하는 JavaScript API 집합을 정의합니다.
이 절에서는 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.
이 문서는 완전하지 않습니다. 이 API는 WHATWG에서 수행된 예비 작업을 기반으로 합니다.
이 문서가 제안 권고안으로 진행되기 전에 WebRTC 작업 그룹은 광범위한 검토에서 제기된 문제를 해결할 예정입니다.
이 문서는 Web 실시간 통신 작업 그룹이 권고안 트랙을 사용하여 후보 권고안 초안으로 발행했습니다.
후보 권고안으로 발행되었다고 해서 W3C 및 그 회원들이 이를 승인했음을 의미하지 않습니다. 후보 권고안 초안은 작업 그룹이 후속 후보 권고안 스냅샷에 포함하려는 이전 후보 권고안의 변경 사항을 통합합니다.
이 문서는 초안이며 언제든지 다른 문서로 업데이트되거나, 대체되거나, 폐기될 수 있습니다. 진행 중인 작업 이외의 것으로 이 문서를 인용하는 것은 적절하지 않습니다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹에 의해 작성되었습니다. W3C는 해당 그룹의 결과물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하며, 해당 페이지에는 특허를 공개하는 방법에 대한 지침도 포함되어 있습니다. 자신이 알고 있는 특허에 필수 청구항이 포함되어 있다고 믿는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 합니다.
이 문서에는 2025년 8월 18일 W3C 프로세스 문서가 적용됩니다.
이 절은 비규범적입니다.
이 문서는 마이크나 비디오 카메라와 같은 로컬 멀티미디어 장치에 대한 액세스를 요청하기 위한 API를 정의합니다.
이 문서는 멀티미디어 스트림 데이터가 소비되는 위치를 제어하는 수단을 제공하고, 미디어를 생성하는 장치를 어느 정도 제어할 수 있게 하는 MediaStream API도 정의합니다. 또한 미디어를 캡처하고 렌더링할 수 있는 장치에 관한 정보를 노출합니다.
비규범적으로 표시된 절뿐만 아니라, 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적입니다. 이 명세의 그 밖의 모든 내용은 규범적입니다.
이 문서에서 핵심어 MAY, MUST, MUST NOT, NOT REQUIRED 및 SHOULD는 여기에 표시된 것처럼 모두 대문자로 나타나는 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 합니다.
이 명세는 하나의 제품, 즉 여기에 포함된 인터페이스를 구현하는 사용자 에이전트에 적용되는 적합성 기준을 정의합니다.
알고리즘이나 구체적인 단계로 표현된 적합성 요구 사항은 최종 결과가 동등하기만 하면 어떤 방식으로든 구현할 수 있습니다. (특히 이 명세에 정의된 알고리즘은 이해하기 쉽도록 작성된 것이며, 성능을 고려하여 작성된 것은 아닙니다.)
이 명세에 정의된 API를 구현하기 위해 ECMAScript [ECMA-262]를 사용하는 구현은 Web IDL 명세 [WEBIDL]에 정의된 ECMAScript 바인딩과 일관된 방식으로 이를 구현해야 합니다. 이는 이 명세가 해당 명세와 용어를 사용하기 때문입니다.
소스는 미디어 스트림 트랙의 원천을 제공하는 "대상"입니다. 소스는 미디어 자체를 송출하는 주체입니다. 소스는 물리적 웹캠, 마이크, 사용자의 하드 드라이브에 있는 로컬 비디오 또는 오디오 파일, 네트워크 리소스 또는 정적 이미지일 수 있습니다. 이 문서에서는 마이크 및 카메라 유형의 소스 사용만 설명하며, 다른 소스 유형의 사용은 다른 문서에서 설명합니다.
소스에 관한 사전 승인이 없는 애플리케이션에는 사용 가능한 소스의 수, 유형 및 다른 장치와의 관계만 제공됩니다. 소스에 관한 추가 정보는 애플리케이션이 소스를 사용할 권한을 부여받으면 제공될 수 있습니다(9.2.1 액세스 제어 모델 참조).
소스에는 제약 조건이 없습니다 — 트랙에 제약 조건이 있습니다. 소스가 트랙에 연결되면, 해당 트랙에 대해 그 트랙에 존재하는 제약 조건을 준수하는 미디어를 생성해야 합니다. 여러 트랙을 동일한 소스에 연결할 수 있습니다. 다운샘플링과 같은 사용자 에이전트 처리는 모든 트랙에 적절한 미디어가 제공되도록 하기 위해 사용될 수 있습니다.
소스에는 트랙에 노출되는 기능과 설정을 갖는 제약 가능한 속성이 있습니다. 제약 가능한 속성은 소스가 "소유"하지만, 소스는 서로 다른 요구를 동시에 수용할 수 있습니다. 이러한 이유로 기능은 동일한 소스를 사용하고 있는 모든 (여러) 트랙에 공통되지만, 설정은 트랙마다 다를 수 있습니다 (예를 들어 동일한 소스에 바인딩된 서로 다른 두 트랙 객체가 기능 및 설정 정보를 조회하면 동일한 기능을 반환받지만, 각각의 제약 조건을 충족하도록 조정된 서로 다른 설정을 반환받을 수 있습니다).
설정은 소스의 제약 가능한 속성이 갖는 즉각적인 현재 값을 의미합니다. 설정은 항상 읽기 전용입니다.
저조도 조건 때문에 카메라가 더 낮은 프레임 속도로 전환되는 경우처럼 소스의 상태는 동적으로 변경될 수 있습니다. 이러한 경우 영향을 받는 소스와 관련된 트랙은 더 이상 설정된 제약 조건을 충족하지 못할 수 있습니다. 플랫폼은 이러한 이탈을 가능한 한 최소화하도록 노력해야 합니다. 그러나 제약 조건을 충족하지 못하게 하는 일시적 또는 영구적인 상태가 존재하더라도 미디어 제공은 계속됩니다.
설정은 소스의 속성이지만,
소스에 연결된 트랙을 통해서만 애플리케이션에
노출됩니다. 이는 ConstrainablePattern 인터페이스를 통해 노출됩니다.
각 제약 가능한 속성에는 해당 속성이
소스에서 지원되는지 여부와, 지원되는 경우
지원되는 값의 범위를 설명하는 기능이 있습니다. 설정과 마찬가지로 기능은
ConstrainablePattern 인터페이스를 통해 애플리케이션에
노출됩니다.
지원되는 기능의 값은 이 명세에 정의된 범위와 열거형에 맞게 정규화되어야 합니다.
트랙에서
getCapabilities()
를 호출하면
해당 소스에 연결된 모든 트랙에 대해 동일한 기본 소스별 기능이
반환됩니다.
이 API는 의도적으로 단순화되어 있습니다. 기능은 서로 다른 값 간의 상호작용을 설명할 수 없습니다. 예를 들어 낮은 프레임 속도에서는 고해상도 비디오 스트림을 생성하고 높은 프레임 속도에서는 더 낮은 해상도를 생성할 수 있는 카메라의 기능을 정확하게 설명하는 것은 불가능합니다. 기능은 각 값의 전체 범위를 설명합니다. 제약 조건 간의 상호작용은 제약 조건 적용을 시도함으로써 드러납니다.
제약 조건은 애플리케이션이 트랙에 적절한 소스를 선택하고, 선택한 후에는 소스의 동작 방식에 영향을 줄 수 있도록 하는 일반적인 제어 인터페이스를 제공합니다.
제약 조건은 소스가 트랙에 미디어를 제공할 때 사용할 수 있는 동작 모드의 범위를 제한합니다. 트랙 제약 조건이 제공되지 않으면, 구현은 지원되는 기능의 전체 범위에서 소스의 설정을 자유롭게 선택할 수 있습니다. 또한 구현은 적용된 모든 제약 조건이 부과하는 범위 내에서 언제든지 소스 설정을 조정할 수 있습니다.
getUserMedia()는
제약 조건을 사용하여
트랙에 적절한 소스를 선택하고 구성하는 데 도움을 줍니다.
또한 트랙의 ConstrainablePattern 인터페이스에는
이후 언제든지 트랙의 제약 조건을 동적으로 변경하기 위한
API가 포함되어 있습니다.
초기 제약 조건을
충족할 수 없는 경우 트랙은
getUserMedia()를 사용하여
소스에 연결되지
않습니다. 그러나 트랙의 제약 조건을 충족하는 능력은
시간에 따라 변경될 수 있으며, 제약 조건도 변경될 수 있습니다. 상황이
변경되어 제약 조건을 충족할 수 없게 되면,
ConstrainablePattern 인터페이스는
애플리케이션에 알리기 위한 적절한 오류를 정의합니다. 5. 모델: 소스, 싱크, 제약 조건 및 설정에서는
제약 조건이 상호작용하는 방식을 더 자세히 설명합니다.
각 제약 가능한 속성에는 관련 소스 설정 이름 및 기능 이름에 대응하는 이름을 가진 제약 조건이 존재합니다.
제약 조건은 제약 조건 구조에서의 위치에 따라 세 그룹 중 하나에 속합니다. 그룹은 다음과 같습니다.
advanced
키워드를 사용하여 지정된 모든 제약 조건입니다.
일반적으로 적용되는 제약 조건이 적을수록 사용자 에이전트가 미디어 스트리밍 경험을 최적화할 수 있는 유연성이 커지므로, 애플리케이션 작성자는 필수 제약 조건을 꼭 필요한 경우에만 사용할 것을 강력히 권장합니다.
MediaStream API의 두 가지 주요 구성 요소는
MediaStreamTrack 및 MediaStream 인터페이스입니다.
MediaStreamTrack 객체는 사용자 에이전트의 하나의 미디어 소스에서
발생하는 단일
유형의 미디어를 나타냅니다. 예를 들어 웹 카메라에서
생성되는 비디오가 이에 해당합니다. MediaStream은 여러
MediaStreamTrack 객체를
하나의 단위로 그룹화하여
미디어 요소에서 녹화하거나 렌더링할 수 있도록 하는 데 사용됩니다.
각 MediaStream은 0개 이상의
MediaStreamTrack 객체를 포함할 수 있습니다.
MediaStream의 모든 트랙은 렌더링될 때
동기화되도록 의도되어 있습니다. 서로 다른 시계를 사용하는 소스의 트랙은
동기화할 수 없을 수도 있으므로 이는 엄격한 요구 사항은
아닙니다. 서로 다른
MediaStream 객체는
동기화될 필요가 없습니다.
트랙을 동기화하는 것이 의도이기는 하지만, 일부 상황에서는 트랙이 동기화를 잃도록 허용하는 것이 더 나을 수 있습니다. 특히 트랙이 원격 소스에서 제공되며 실시간 [WEBRTC]인 경우, 지연을 누적시키거나 끊김 및 기타 아티팩트가 발생할 위험을 감수하는 것보다 동기화 손실을 허용하는 편이 더 나을 수 있습니다. 구현은 재생 동기화에 관한 선택의 영향과 그러한 선택이 사용자의 인지에 미치는 영향을 이해해야 합니다.
하나의 MediaStreamTrack은
스테레오나 5.1 오디오 또는 입체 비디오와 같은
다중 채널 콘텐츠를 나타낼 수 있으며,
이 경우 채널들은 서로 잘 정의된 관계를 가집니다.
채널에 관한 정보는
[WEBAUDIO]와 같은 다른 API를 통해 노출될 수 있지만,
이 명세는 채널에 대한 직접적인 액세스를 제공하지 않습니다.
MediaStream 객체에는 객체의 모든 트랙의 결합된
입력 및 출력을 나타내는 입력과 출력이 있습니다.
MediaStream의 출력은 객체가
렌더링되는 방식을 제어합니다. 예를 들어 객체가 파일에 녹화되는 경우 저장되는 내용이나,
객체가
video
요소에서 사용되는 경우 표시되는 내용을 제어합니다.
하나의 MediaStream 객체를
동시에 여러 개의 서로 다른 출력에 연결할 수 있습니다.
새로운 MediaStream 객체는
기존 미디어 스트림 또는 트랙에서
MediaStream() 생성자를 사용하여 생성할 수 있습니다.
생성자 인수는
기존 MediaStream 객체일 수 있으며, 이
경우 주어진 스트림의 모든 트랙이 새로운
MediaStream 객체에 추가됩니다. 또는
MediaStreamTrack 객체의 배열일 수 있습니다. 후자의 형식을 사용하면
서로 다른 소스 스트림으로 하나의 스트림을 구성할 수
있습니다.
MediaStream 및
MediaStreamTrack 객체는 모두 복제할 수 있습니다.
복제된
MediaStream에는
원래 스트림의 모든 멤버 트랙의 복제본이 포함됩니다. 복제된 MediaStreamTrack에는
복제 원본 인스턴스와 독립적인
제약 조건 집합이 있으며, 이를 통해
동일한 소스의 미디어에 서로 다른
소비자에 대해
서로 다른 제약 조건을 적용할 수 있습니다. MediaStream 객체는 [WEBRTC]와 같이
getUserMedia 이외의
컨텍스트에서도 사용됩니다.
MediaStreamMediaStream constructor는 기존 트랙으로 새로운
스트림을 구성합니다. MediaStream 유형 또는
MediaStreamTrack 객체 배열 유형의 선택적 인수를 받습니다. 생성자가
호출되면 사용자
에이전트는 다음 단계를 실행해야 합니다:
stream을 새로 생성된
MediaStream 객체라고 합니다.
stream.id 속성을 새로 생성된
값으로 초기화합니다.
생성자의 인수가 존재하면 다음 단계를 실행합니다:
인수의 유형에 따라 트랙 집합 tracks을 구성합니다:
MediaStream 객체:
tracks을
MediaStream의 트랙
집합에 있는 모든
MediaStreamTrack
객체를 포함하는 집합으로 합니다.
MediaStreamTrack
객체의 시퀀스:
tracks을 제공된
시퀀스의 모든
MediaStreamTrack
객체를 포함하는 집합으로 합니다.
tracks의 각 MediaStreamTrack
track에 대해 다음
단계를 실행합니다:
stream을 반환합니다.
MediaStream의 트랙은
트랙 집합에 저장됩니다. 트랙 집합은 스트림의
트랙에 대응하는
MediaStreamTrack 객체를 반드시 포함해야
합니다. 집합 내 트랙의 상대적 순서는 사용자
에이전트가 정의하며 API는 그 순서에 어떠한 요구 사항도 부과하지 않습니다.
집합에서 특정 MediaStreamTrack
객체를 찾는 올바른 방법은 해당 객체의 id로 조회하는 것입니다.
MediaStream의 출력에서 데이터를 읽는 객체를
MediaStream 소비자라고 합니다. 현재
MediaStream 소비자에는 미디어
요소(예:
video
및
audio)
[HTML], Web
실시간 통신
(WebRTC; RTCPeerConnection)
[WEBRTC], 미디어 녹화
(MediaRecorder) [mediastream-recording], 이미지
캡처
(ImageCapture) [image-capture] 및 Web
오디오
(MediaStreamAudioSourceNode)
[WEBAUDIO]가 포함됩니다.
MediaStream 소비자는 트랙이 추가되고
제거되는 상황을 처리할 수 있어야 합니다. 이 동작은 각
소비자별로 지정됩니다.
MediaStream 객체에 아직 종료되지 않은
MediaStreamTrack이 하나 이상 있으면 해당 객체를 활성 상태라고 합니다. 트랙이 없거나 종료된 트랙만 있는
MediaStream은
비활성 상태입니다.
MediaStream 객체에 [[Kind]]가 "audio"이고 아직 종료되지 않은
MediaStreamTrack이 하나 이상 있으면 해당 객체를 청취
가능 상태라고 합니다. 오디오 트랙이 없거나 종료된 오디오 트랙만 있는
MediaStream은
청취 불가능 상태입니다.
사용자 에이전트는 예를 들어 외부
이벤트에 응답하여 MediaStream의 트랙 집합을 업데이트할 수 있습니다.
이 명세는 이러한 경우를 지정하지 않지만 MediaStream API를 사용하는 다른
명세에서는 지정할 수 있습니다. 한 가지 예로 WebRTC 1.0 [WEBRTC] 명세에서는
다른 피어로부터 수신된 MediaStream의 트랙 집합이 미디어
세션의 변경 결과로 업데이트될 수 있습니다.
MediaStream stream에
트랙 track을 추가하려면 사용자 에이전트는 다음 단계를 반드시
실행해야 합니다:
track이 이미 stream's 트랙 집합에 있으면 이 단계를 중단합니다.
track을 stream의 트랙 집합에 추가합니다.
stream에서 track을 사용하여 addtrack이라는 이름의 트랙 이벤트를 발생시킵니다.
MediaStream stream에서
트랙 track을 제거하려면
사용자 에이전트는 다음 단계를 반드시
실행해야 합니다:
track이 stream's 트랙 집합에 없으면 이 단계를 중단합니다.
stream에서 track을 사용하여 removetrack이라는 이름의 트랙 이벤트를 발생시킵니다.
WebIDL[Exposed=Window]
interface MediaStream : EventTarget {
constructor();
constructor(MediaStream stream);
constructor(sequence<MediaStreamTrack> tracks);
readonly attribute DOMString id;
sequence<MediaStreamTrack> getAudioTracks();
sequence<MediaStreamTrack> getVideoTracks();
sequence<MediaStreamTrack> getTracks();
MediaStreamTrack? getTrackById(DOMString trackId);
undefined addTrack(MediaStreamTrack track);
undefined removeTrack(MediaStreamTrack track);
MediaStream clone();
readonly attribute boolean active;
attribute EventHandler onaddtrack;
attribute EventHandler onremovetrack;
};
MediaStreamMediaStream 생성자 알고리즘을 참조하십시오.
MediaStreamMediaStream 생성자 알고리즘을 참조하십시오.
MediaStreamMediaStream 생성자 알고리즘을 참조하십시오.
id, 유형: DOMString,
읽기 전용id 속성은 객체가 생성될 때
초기화된 값을 반드시
반환해야 합니다.
MediaStream이
생성되면 사용자
에이전트는 식별자 문자열을 반드시 생성하고, 스트림 id를
초기화하는 방법을 지정하는 특수 목적 알고리즘의 일부로 객체가
생성되는 경우를 제외하고 객체의 id
속성을 해당 문자열로 반드시 초기화해야 합니다. 좋은 방법은 UUID [rfc4122]를
사용하는 것이며, UUID는 정규 형식에서 36자입니다. 핑거프린팅을
방지하기 위해 구현은 UUID를 생성할 때 RFC 4122의
4.4절 또는 4.5절의 형식을 사용해야 합니다.
스트림 id를 초기화하는 방법을 지정하는 알고리즘의
예로 수신 네트워크 구성 요소를 MediaStream 객체와
연결하는
알고리즘이 있습니다. [WEBRTC]
active, 유형: boolean, 읽기 전용
active
속성은 이 MediaStream이
활성 상태이면 true를,
그렇지 않으면 false를 반드시 반환해야 합니다.
onaddtrack, 유형: EventHandler
이 이벤트 핸들러의 이벤트 유형은 addtrack입니다.
onremovetrack, 유형: EventHandler
이 이벤트 핸들러의 이벤트 유형은 removetrack입니다.
getAudioTracks()이 스트림의 오디오 트랙을 나타내는 MediaStreamTrack
객체의 시퀀스를 반환합니다.
getAudioTracks
메서드는 이 스트림의
트랙 집합에 있는
[[Kind]]가
"audio"와 같은 모든
MediaStreamTrack 객체의
스냅샷을 나타내는 시퀀스를 반드시 반환해야 합니다.
트랙 집합에서 시퀀스로의 변환은 사용자 에이전트가 정의하며
호출 간에 순서가 안정적일 필요는 없습니다.
getVideoTracks()이 스트림의 비디오 트랙을 나타내는 MediaStreamTrack
객체의 시퀀스를 반환합니다.
getVideoTracks
메서드는 이 스트림의
트랙 집합에 있는
[[Kind]]가
"video"와 같은 모든
MediaStreamTrack 객체의
스냅샷을 나타내는 시퀀스를 반드시 반환해야 합니다.
트랙 집합에서 시퀀스로의 변환은 사용자 에이전트가 정의하며
호출 간에 순서가 안정적일 필요는 없습니다.
getTracks()이 스트림의 모든 트랙을 나타내는 MediaStreamTrack
객체의 시퀀스를 반환합니다.
getTracks 메서드는
[[Kind]]와 관계없이 이 스트림의
트랙 집합에 있는 모든
MediaStreamTrack 객체의
스냅샷을 나타내는 시퀀스를 반드시 반환해야 합니다.
트랙 집합에서 시퀀스로의
변환은 사용자
에이전트가 정의하며 호출 간에 순서가 안정적일 필요는
없습니다.
getTrackById()getTrackById
메서드는 이 스트림의 트랙 집합에서
[[Id]]가
trackId와 같은 MediaStreamTrack
객체를 반드시 반환하거나, 그러한 트랙이
존재하지 않으면 null을 반환해야 합니다.
addTrack()주어진 MediaStreamTrack을 이
MediaStream에
추가합니다.
addTrack 메서드가
호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야
합니다:
track을 메서드의 인수로 하고
stream을 메서드가 호출된 MediaStream 객체로
합니다.
track이 이미 stream의 트랙 집합에 있으면 이 단계를 중단합니다.
removeTrack()주어진 MediaStreamTrack 객체를
이 MediaStream에서
제거합니다.
removeTrack
메서드가 호출되면 사용자 에이전트는 다음
단계를 반드시 실행해야 합니다:
track을 메서드의 인수로 하고
stream을 메서드가 호출된 MediaStream 객체로
합니다.
track이 stream's 트랙 집합에 없으면 이 단계를 중단합니다.
clone()주어진 MediaStream 및
그 모든
트랙을 복제합니다.
clone() 메서드가
호출되면 사용자
에이전트는 다음 단계를 반드시 실행해야 합니다:
streamClone을 새로 생성된
MediaStream 객체로 합니다.
streamClone.MediaStream.id를 새로
생성된 값으로 초기화합니다.
이 MediaStream 객체의
각 트랙을 복제하고 그 결과를
streamClone의 트랙
집합에 추가합니다.
addtrack 또는 removetrack 이벤트를 발생시킬 것으로 예상되는 사용자 에이전트 코드는
다른 객체의 참조를 통해 대상 MediaStream 객체가 유지되도록
해야 합니다.
MediaStream 객체를 가비지 컬렉션하려고 할 때
addtrack 또는 removetrack 이벤트 리스너의 존재를
고려할 필요는 없습니다.
MediaStreamTrackMediaStreamTrack 객체는 사용자 에이전트의 미디어
소스를 나타냅니다. 소스의 한 예는
사용자 에이전트에 연결된 장치입니다. 다른 명세에서는
여기에 지정된 동작을 재정의하는 MediaStreamTrack의 소스를
정의할 수 있습니다. 여러 MediaStreamTrack 객체가
동일한 미디어 소스를 나타낼 수 있습니다. 예를 들어 연속된 두 번의 getUserMedia() 호출에서 표시된
UI를 통해
사용자가 동일한 카메라를 선택하는 경우가 이에 해당합니다.
MediaStreamTrack 소스는 다음
속성을 정의합니다:
MediaStreamTrack 또는
MediaStreamTrack의 하위 유형으로 설정됩니다.
기본적으로 MediaStreamTrack으로
설정됩니다.
MediaStreamTrack을 생성할
때 실행되는 MediaStreamTrack 소스별
구성 단계가 있습니다.
이 단계는 새로 생성된 MediaStreamTrack을 입력으로
받습니다. 기본적으로
이 단계는 비어 있습니다.MediaStreamTrack을 복제할
때 실행되는 MediaStreamTrack 소스별 복제 단계가 있습니다.
이 단계는 소스 및 대상 MediaStreamTrack을 입력으로
받습니다. 기본적으로
이 단계는 비어 있습니다.MediaStreamTrack 객체의
데이터에는 반드시
표준적인 이진 형식이 있는 것은 아닙니다. 예를 들어 단순히
"현재 사용자의 비디오 카메라에서 들어오는 비디오"일 수도 있습니다. 이를 통해
사용자 에이전트는 사용자의 플랫폼에
가장 적합한 방식으로 미디어를 조작할 수 있습니다.
스크립트는 stop()
메서드를 사용하여 MediaStreamTrack
객체가 더 이상 해당 소스를 필요로 하지 않음을 나타낼 수 있습니다. 소스를
사용하는 모든 트랙이 중지되거나 다른 수단으로 종료되면 소스는
중지됩니다. 소스가
getUserMedia()에 의해 노출되는
장치인 경우,
소스가 중지되면 사용자 에이전트는 다음 단계를 반드시
실행해야 합니다:
mediaDevices를 해당 MediaDevices 객체로 합니다.
deviceId를 소스 장치의 deviceId로
합니다.
mediaDevices.[[devicesLiveMap]][deviceId]
를
false로 설정합니다.
mediaDevices의 관련
설정 객체에 대해 장치의 종류 및
deviceId와 연결된 권한의 권한 상태가
"granted"가
아니면
mediaDevices.[[devicesAccessibleMap]][deviceId]
를
false로 설정합니다.
기반 source와 mediaDevicesToTieSourceTo를 사용하여 MediaStreamTrack을 생성하려면 다음 단계를 실행합니다:
track을 source의 MediaStreamTrack 소스 유형에 해당하는 새 객체로 합니다.
다음 내부 슬롯으로 track을 초기화합니다:
[[Source]], source로 초기화합니다.
[[Id]],
새로 생성된 고유 식별자 문자열로 초기화합니다. 이러한 식별자를
생성하는 방법에 대한 지침은
MediaStream.id 속성을 참조하십시오.
[[Kind]],
source가 오디오 소스이면 "audio"로,
source가 비디오 소스이면 "video"로
초기화합니다.
[[Label]],
사용자 에이전트가 제공한 경우 source의 레이블로,
그렇지 않으면 ""로 초기화합니다. 사용자
에이전트는 오디오 및
비디오 소스에 레이블을 지정할 수 있습니다(예: "내장 마이크" 또는 "외장 USB 웹캠").
[[ReadyState]],
"live"로 초기화합니다.
[[Enabled]],
true로 초기화합니다.
[[Muted]],
source가
음소거 상태이면 true로, 그렇지 않으면
false로 초기화합니다.
ConstrainablePattern에 지정된 대로
초기화합니다.
[[Restrictable]], false로 초기화합니다.
mediaDevicesToTieSourceTo가 null이 아니면,
source 및
mediaDevicesToTieSourceTo를 사용하여 트랙 소스를
MediaDevices에 연결합니다.
track을 매개변수로 하여 source의 MediaStreamTrack 소스별 구성 단계를 실행합니다.
track을 반환합니다.
track의 기반 소스를 초기화하여 source로 설정하려면 다음 단계를 실행합니다:
track.[[Source]]를
source로 초기화합니다.
track의 [[Capabilities]],
[[Constraints]] 및
[[Settings]]을
ConstrainablePattern에
지정된 대로 초기화합니다.
source와
mediaDevices가 주어졌을 때 트랙 소스를
MediaDevices에 연결하려면 다음 단계를 실행합니다:
source를
mediaDevices.[[mediaStreamTrackSources]]에
추가합니다.
globalObject라는 전역 객체의 모든 소스를 중지하려면 사용자 에이전트는 다음 단계를 반드시 실행해야 합니다:
관련 전역
객체가 globalObject인 각 MediaStreamTrack
객체 track에 대해,
track의 [[ReadyState]]를
"ended"로 설정합니다.
globalObject가 Window이면,
globalObject의
연결된 MediaDevices.[[mediaStreamTrackSources]]에 있는
각 source에 대해
source를 중지합니다.
사용자 에이전트는 다음 조건에서 globalObject의 모든 소스를 중지해야 합니다:
globalObject가 Window
객체이고 그 연결된
문서에 대해 문서
언로드
정리 단계가
실행되는 경우입니다.
globalObject가 WorkerGlobalScope
객체이고 해당 객체의
closing
플래그가 true로 설정된 경우입니다.
구현은 소스 사용을 추적하기 위해 소스별 참조 횟수를 사용할 수 있지만, 구체적인 사항은 이 명세의 범위를 벗어납니다.
트랙을 복제하려면 사용자 에이전트는 다음 단계를 반드시 실행해야 합니다:
track을 복제할 MediaStreamTrack
객체로 합니다.
source를 track의
[[Source]]로 합니다.
trackClone을
source와 null을 사용하여 MediaStreamTrack을 생성한
결과로 합니다.
trackClone의 [[ReadyState]]를
track의 [[ReadyState]] 값으로 설정합니다.
trackClone의 [[Capabilities]]를 track의 [[Capabilities]] 복제본으로 설정합니다.
trackClone의 [[Constraints]]를 track의 [[Constraints]] 복제본으로 설정합니다.
trackClone의 [[Settings]]를 track의 [[Settings]] 복제본으로 설정합니다.
track과 trackClone을 매개변수로 하여 source의 MediaStreamTrack 소스별 복제 단계를 실행합니다.
trackClone을 반환합니다.
"live" MediaStreamTrack의
미디어 흐름과 관련된 두 가지 차원이 있습니다:
음소거됨 / 음소거되지 않음,
그리고 활성화됨 / 비활성화됨입니다.
음소거됨은
MediaStreamTrack의
입력을 의미합니다.
MediaStreamTrack은
그 소스가 음소거됨,
즉 일시적으로 트랙에 데이터를 제공할 수 없는 경우
음소거 상태입니다.
MediaStreamTrack이
음소거 상태인 동안에는 라이브 샘플을 제공해서는 안 됩니다.
음소거 상태는 웹 애플리케이션이 제어할 수 없지만,
애플리케이션은 muted
속성을 읽고 연결된 mute 및 unmute
이벤트를 수신하여 이를 관찰할 수 있습니다.
MediaStreamTrack이
음소거되는 이유는 해당 소스에 의해 정의됩니다.
카메라 및 마이크 소스의 경우 음소거하는 이유는 구현 정의입니다. 이를 통해 사용자 에이전트는 다음과 같은 상황에서 개인정보 보호 완화 조치를 구현할 수 있습니다: 사용자가 마이크의 물리적 음소거 버튼을 누르는 경우, 사용자가 내장 카메라가 있는 노트북 덮개를 닫는 경우, 사용자가 운영 체제의 제어 기능을 전환하는 경우, 사용자가 사용자 에이전트 크롬의 음소거 버튼을 클릭하는 경우, 사용자 에이전트가 (사용자를 대신하여) 음소거하는 경우 등입니다.
일부 운영 체제에서는 더 높은 오디오 우선순위를 가진 다른 애플리케이션이
마이크에 접근하면 사용자 에이전트의 마이크 접근 권한을
빼앗을 수 있습니다.
예를 들어 모바일 OS에서 전화가 수신되는 경우입니다. 사용자 에이전트는
muted 및
관련 이벤트를 통해 이 정보를 웹 애플리케이션에 제공해야 합니다.
사용자 에이전트가 카메라 또는 마이크 소스에 대해 이러한 구현 정의 변경을 시작할 때마다, 사용자 상호작용 태스크 소스를 사용하여 트랙의 음소거 상태를 설정하여 사용자가 원하는 상태로 만들기 위한 태스크를 반드시 대기열에 넣어야 합니다.
트랙의 음소거 상태를 설정하여 newState로 만들려면 사용자 에이전트는 다음 단계를 반드시 실행해야 합니다:
track을 해당 MediaStreamTrack으로
합니다.
track.[[Muted]]가 이미
newState이면 이 단계를 중단합니다.
track.[[Muted]]를
newState로 설정합니다.
track에서 eventName이라는 이름의 이벤트를 발생시킵니다.
반면 활성화됨/비활성화됨 상태는
애플리케이션이
enabled
속성을 통해 제어하고 관찰할 수 있습니다.
소비자 입장에서는
MediaStreamTrack이
음소거되거나 비활성화된 경우(또는 둘 다인 경우) 항상
소비자가 정보가 전혀 없는 콘텐츠를 받는다는 점에서 결과는 동일합니다. 이는 오디오의 경우
무음, 비디오의 경우 검은 프레임을 의미합니다. 다시 말해 소스의 미디어는
MediaStreamTrack
객체가 음소거되지 않고 활성화된 경우에만
흐릅니다. 예를 들어 오디오 및 비디오에 대해 음소거되거나
비활성화된 MediaStreamTrack만
포함하는
MediaStream을 소스로 사용하는 비디오 요소는 재생 중이지만
무음 상태에서 검은 비디오 프레임을 렌더링합니다.
새로 생성된 MediaStreamTrack
객체에는
다음이 적용됩니다. 별도로 명시되지 않는 한(예를 들어 복제된 경우)
트랙은 항상 활성화되어 있으며, 음소거 상태는 트랙이 생성될 당시
소스의 상태를 반영합니다.
MediaStreamTrack은
수명 주기에서 두 가지 상태를 가집니다:
live 및 ended입니다. 새로 생성된
MediaStreamTrack은
생성된 방식에 따라 어느 상태에나 있을 수 있습니다.
예를 들어 종료된 트랙을 복제하면 새로운 종료된 트랙이 생성됩니다.
현재 상태는 객체의
readyState
속성에 반영됩니다.
live 상태에서는 트랙이 활성 상태이며 미디어
(또는 MediaStreamTrack이
음소거되거나 비활성화된 경우 정보가 전혀
없는 콘텐츠)를
소비자가 사용할 수 있습니다.
소스가 navigator.mediaDevices.getUserMedia()에
의해
노출되는 장치인 경우, 트랙이 음소거되거나
비활성화되고 그 결과 장치에 연결된 모든 트랙이
음소거, 비활성화 또는 중지 상태가 되면 UA는 장치의
deviceId, deviceId를
사용하여
navigator.mediaDevices.[[devicesLiveMap]][deviceId]
를 false로 설정할 수 있습니다.
단, 이 장치에 연결된 중지되지 않은 트랙이 다시 음소거 해제되거나
활성화되는 즉시 UA가 이를 다시 true로 설정해야 합니다.
getUserMedia()에
의해 노출된 장치에서
소싱된 "live", 음소거 해제 및
활성화 상태의 트랙이
음소거되거나 비활성화되고,
그 결과 장치에 연결된 모든 트랙(사용자 에이전트가 운영하는 모든
탐색 가능 항목
전체에서)이 음소거, 비활성화 또는 중지 상태가 되면, UA는 합리적으로 주의를 기울이는 사용자가
전환을 인지할 시간을 허용하면서 3초 이내에 장치를 해제해야 합니다.
장치에서 소싱된 live 트랙이 다시 음소거 해제되고
활성화되는 즉시, 해당 트랙의
관련
전역 객체의 연결된
Document가
그 시점에 보이는 상태라면 UA는 장치를 다시 획득하려고 시도해야
합니다.
그 시점에 문서가 보이는 상태가 아니라면,
UA는 대신 트랙을 음소거하는 태스크를 대기열에 넣고, 문서가
보이는 상태가 될 때까지
트랙을 음소거 해제하는 태스크를
대기열에 넣지 않아야 합니다.
장치를 다시 획득하지 못하면 UA는 트랙을 종료해야 합니다(장치가 물리적으로
제거되는 것과 같은 장치 문제를 감지한 경우 UA는 더 일찍 종료할 수 있습니다).
그 의도는 적어도 현재 문서가 장치의 유일한 사용자인 동안 물리적 및 논리적 “개인정보 보호 표시기”를 일치시킴으로써, 물리적 카메라(및 마이크) 하드웨어 표시등이 꺼져 있을 때 얻을 수 있는 개인정보 보호에 대한 확신을 사용자에게 제공하는 것입니다.
장치를 동시에 사용하는 다른 애플리케이션 및 문서가 때때로 이러한 의도를 방해할 수 있지만, 여기서 정한 규칙 자체를 방해하지는 않습니다.
MediaStreamTrack
객체는 트랙의 소스가 연결 해제되거나
소진되면
종료된다고 합니다.
동일한 소스를 사용하는 모든 MediaStreamTrack이
종료되면 소스도
중지됩니다.
애플리케이션이 MediaStreamTrack
객체에서 stop()
메서드를 호출한 후, 또는 MediaStreamTrack의
소스가 해당 트랙에 대한 라이브 샘플 생성을
영구적으로 종료한 후 중 더 이른 시점부터 MediaStreamTrack은
종료됨 상태라고 합니다.
카메라 및 마이크 소스의 경우 stop() 이외의 이유로 소스가
종료되는 이유는
구현
정의입니다
(예: 사용자가 페이지의 로컬 카메라 사용 권한을 철회했거나
사용자
에이전트가 어떤 이유로든 트랙을 종료하도록 지시한 경우).
MediaStreamTrack
track이
stop() 메서드가
호출된 경우 이외의 이유로
종료되면 사용자 에이전트는 다음
단계를 실행하는 태스크를 반드시 대기열에 넣어야 합니다:
track의 [[ReadyState]]가
이미 "ended" 값을
가지면 이
단계를 중단합니다.
track의 [[ReadyState]]를
"ended"로 설정합니다.
track이
종료되었음을 track의 [[Source]]에 알려
다른 MediaStreamTrack 객체가
해당 소스에 의존하지 않는 한 소스가 중지될 수 있도록 합니다.
사용자 요청으로 인해 트랙이 종료된 경우 이 이벤트의 이벤트 소스는 사용자 상호작용 이벤트 소스입니다.
permissionName으로 장치 권한 철회 알고리즘을 호출하려면 다음 단계를 실행합니다:
tracks를 현재
"live" 상태인 모든
MediaStreamTrack 중
이 종류의 트랙("camera" 또는 "microphone")과 연결된 권한이
permissionName과 일치하는 트랙의 집합으로 합니다.
tracks의 각 track에 대해 트랙을 종료합니다.
MediaStreamTrack은 제약 가능한
객체이며, 제약 가능 패턴 절에 정의되어 있습니다.
제약 조건은 트랙에 설정되며 소스에 영향을 줄 수 있습니다.
트랙
초기화 시
가
제공되었는지 또는 나중에 런타임에 설정해야 하는지와 관계없이,
ConstraintsConstrainablePattern 인터페이스에 정의된 API를
사용하면
트랙에 현재 설정되어 있는
제약 조건을 가져오고 조작할 수 있습니다.
트랙이 종료된 후에도
고유한 제약 가능 트랙 속성 목록을 계속 노출합니다.
이 목록에는 deviceId,
facingMode 및
groupId가 포함됩니다.
WebIDL[Exposed=Window]
interface MediaStreamTrack : EventTarget {
readonly attribute DOMString kind;
readonly attribute DOMString id;
readonly attribute DOMString label;
attribute boolean enabled;
readonly attribute boolean muted;
attribute EventHandler onmute;
attribute EventHandler onunmute;
readonly attribute MediaStreamTrackState readyState;
attribute EventHandler onended;
MediaStreamTrack clone();
undefined stop();
MediaTrackCapabilities getCapabilities();
MediaTrackConstraints getConstraints();
MediaTrackSettings getSettings();
Promise<undefined> applyConstraints(optional MediaTrackConstraints constraints = {});
};
kind
유형: DOMString,
읽기 전용id 유형: DOMString,
읽기 전용label
유형: DOMString,
읽기 전용enabled 유형: booleanenabled
속성은 객체의 활성화 상태를
제어합니다.
가져올 때는,
this.[[Enabled]]를 반드시 반환해야 합니다.
설정할 때는,
this.[[Enabled]]를 반드시 새
값으로 설정해야 합니다.
따라서
MediaStreamTrack이
종료된 후에도 enabled
속성은
설정될 때 여전히 값이 변경되지만, 그 새 값으로
아무 작업도 하지 않습니다.
muted
유형: boolean,
읽기 전용muted 속성은
트랙이 음소거되었는지를 반영합니다.
이 속성은
this.[[Muted]]를 반드시 반환해야 합니다.
onmute 유형: EventHandler
이 이벤트 핸들러의 이벤트 유형은 mute입니다.
onunmute 유형: EventHandler
이 이벤트 핸들러의 이벤트 유형은 unmute입니다.
readyState 유형:
MediaStreamTrackState,
읽기 전용
가져올 때 readyState 속성은
this.[[ReadyState]]를 반드시 반환해야 합니다.
onended 유형: EventHandler
이 이벤트 핸들러의 이벤트 유형은 ended입니다.
clonestopMediaStreamTrack 객체의
stop()
메서드가 호출되면 사용자
에이전트는 다음 단계를 반드시 실행해야 합니다:
track을 현재
MediaStreamTrack
객체로 합니다.
track의 [[ReadyState]]가
"ended"이면
이 단계를 중단합니다.
track이 종료되었음을 track의 소스에 알립니다.
트랙이 종료되었다는 알림을 받은 소스는 다른
MediaStreamTrack
객체가
해당 소스에 의존하지 않는 한 중지됩니다.
track의 [[ReadyState]]를
"ended"로
설정합니다.
getCapabilities이 MediaStreamTrack, 즉 제약 가능한
객체가 나타내는 소스의 기능을 반환합니다.
이 메서드의 정의는 ConstrainablePattern 인터페이스를 참조하십시오.
이 메서드는 기반
장치에 관한 지속될 가능성이 있는 교차 출처 정보를 제공하므로
장치의 핑거프린팅 표면을 증가시킵니다.![]()
getConstraints이 메서드의 정의는 ConstrainablePattern 인터페이스를 참조하십시오.
getSettingsMediaStreamTrack 객체의
MediaStreamTrack.getSettings()
메서드가 호출되면,
사용자 에이전트는 다음 단계를 반드시
실행해야 합니다:
track을 현재 MediaStreamTrack
객체로 합니다.
track의 [[ReadyState]]가
"ended"이면
다음 하위 단계를 실행합니다:
settings를 새로운 MediaTrackSettings
딕셔너리로 합니다.
고유한 제약 가능 트랙 속성 목록의 각 property에 대해, track이 종료될 때 해당 속성을 가지고 있었다면 settings에 대응하는 속성을 추가하고, 값은 track이 종료될 당시의 값으로 합니다.
settings를 반환합니다.
ConstrainablePattern 인터페이스에 정의된 트랙의 현재 설정을 반환합니다.
applyConstraintsMediaStreamTrack 객체의
applyConstraints()
메서드가 호출되면 사용자
에이전트는 다음 단계를 반드시 실행해야 합니다:
track을 현재
MediaStreamTrack
객체로 합니다.
track의 [[ReadyState]]가
"ended"이면
다음 하위 단계를 실행합니다:
p를 새로운 프로미스로 합니다.
p를 undefined로
이행합니다.
p를 반환합니다.
다음과 같이 applyConstraints 템플릿 메서드를 호출하고 그 결과를 반환합니다:
MediaStreamTrack이고,
MediaTrackSettings
딕셔너리의 가능한
인스턴스를 의미합니다. 사용자 에이전트는
변경 불가능한 고유 장치 속성이 고유한
제약 가능
트랙 속성 목록에 포함되어 있지 않은 한 이를 멤버로 포함해서는
안 되며, 그 밖에도
노출해서는
안 되는 장치 속성을 포함해서는 안 됩니다.
다른 명세에서는 때때로 노출해서는 안 되는 제약 가능한 속성을 정의할 수 있습니다.
설정 딕셔너리 중 resizeMode가 "none"으로 설정된 각각에 대해, 사용자 에이전트는 resizeMode가 "crop-and-scale"로 설정된 그 밖의 부분은 동일한 또 하나의 설정 딕셔너리를 반드시 포함해야 합니다. 비네이티브 모드에 대한 제약은 지원되지 않습니다.
결과적으로 crop-and-scale이 none의 상위 집합임을 반영합니다.
WebIDLenum MediaStreamTrackState {
"live",
"ended"
};
| 열거형 값 | 설명 |
|---|---|
live |
트랙이 활성 상태입니다(트랙의 기반 미디어 소스가 실시간으로 데이터를 제공하기 위해 최선을 다하고 있습니다). |
ended |
트랙이 종료되었습니다(트랙의 기반 미디어 소스가 더 이상 데이터를 제공하지 않으며, 이 트랙에 다시는 데이터를 제공하지 않습니다). 트랙이 이 상태에 진입하면 다시 벗어나지 않습니다. 예를 들어
|
MediaTrackSupportedConstraints는
MediaStreamTrack 객체의
기능을 제어하기 위해 사용자 에이전트가 인식하는
제약 조건 목록을 나타냅니다.
이 딕셔너리는 함수의 반환 값으로 사용되며, 연산의
인수로는 사용되지 않습니다.
향후 명세에서는 MediaTrackSupportedConstraints
딕셔너리를 boolean 유형의 딕셔너리 멤버를 가진
partial 딕셔너리를 정의하여 확장할 수 있습니다.
이 명세에 지정된 제약 조건은 다른 명세에서
달리 명시하지 않는 한,
MediaDevices.getUserMedia()에
의해 생성된
MediaStreamTrack
인스턴스에만
적용됩니다.
WebIDLdictionary MediaTrackSupportedConstraints {
boolean width = true;
boolean height = true;
boolean aspectRatio = true;
boolean frameRate = true;
boolean facingMode = true;
boolean resizeMode = true;
boolean sampleRate = true;
boolean sampleSize = true;
boolean echoCancellation = true;
boolean autoGainControl = true;
boolean noiseSuppression = true;
boolean latency = true;
boolean channelCount = true;
boolean deviceId = true;
boolean groupId = true;
boolean backgroundBlur = true;
};
MediaTrackSupportedConstraints
멤버width 유형: boolean,
기본값:
true
height 유형: boolean,
기본값:
true
aspectRatio 유형: boolean,
기본값:
true
frameRate
유형: boolean,
기본값:
true
facingMode 유형: boolean,
기본값:
true
resizeMode 유형: boolean,
기본값:
true
sampleRate 유형: boolean,
기본값:
true
sampleSize 유형: boolean,
기본값:
true
echoCancellation 유형: boolean,
기본값:
true
autoGainControl 유형: boolean,
기본값:
true
noiseSuppression 유형: boolean,
기본값:
true
latency
유형: boolean,
기본값:
true
channelCount 유형: boolean,
기본값:
true
deviceId
유형: boolean,
기본값:
true
groupId
유형: boolean,
기본값:
true
backgroundBlur 유형: boolean,
기본값:
true
MediaTrackCapabilities는
MediaStreamTrack의 기능을 나타냅니다. MediaStreamTrack
객체입니다.
향후 명세에서는 적절한 유형의 딕셔너리 멤버를 가진 partial 딕셔너리를 정의하여 MediaTrackCapabilities 딕셔너리를 확장할 수 있습니다.
WebIDLdictionary MediaTrackCapabilities {
ULongRange width;
ULongRange height;
DoubleRange aspectRatio;
DoubleRange frameRate;
sequence<DOMString> facingMode;
sequence<DOMString> resizeMode;
ULongRange sampleRate;
ULongRange sampleSize;
sequence<(boolean or DOMString)> echoCancellation;
sequence<boolean> autoGainControl;
sequence<boolean> noiseSuppression;
DoubleRange latency;
ULongRange channelCount;
DOMString deviceId;
DOMString groupId;
sequence<boolean> backgroundBlur;
};
역사적인 이유로 deviceId와
groupId는
의
ConstrainablePatternCapabilities에서
예상되는
sequence<DOMString> 대신 DOMString입니다.
MediaTrackCapabilities
멤버width
유형: ULongRangeheight
유형: ULongRangeaspectRatio 유형: DoubleRangeframeRate 유형: DoubleRangefacingMode 유형:
sequence<DOMString>
카메라는 여러 방향 모드를 보고할 수 있습니다. 예를 들어
여러 카메라가 사용자를 향하는 고급 텔레프레즌스 솔루션에서
사용자 왼쪽에 있는 카메라는 "left"와
"user"를 모두 보고할 수
있습니다. 추가
세부 정보는 facingMode를 참조하십시오.
resizeMode 유형:
sequence<DOMString>
사용자 에이전트는
이 카메라가 기본적으로 생성하는 것보다 더 많은 해상도 선택지를 제공하기 위해
자르기 및 다운스케일링을 사용할 수 있습니다.
보고되는 시퀀스에는 UA가 이 카메라의 해상도 선택지를
도출하기 위해 사용할 수 있는 모든 수단을 반드시 나열해야 합니다.
"none" 값은
UA가 자르기 및 다운스케일링을 하지 않도록 제한할 수 있음을 나타내므로
반드시 존재해야 합니다. 추가
세부 정보는 resizeMode를 참조하십시오.
sampleRate 유형: ULongRangesampleSize 유형: ULongRangeechoCancellation 유형:
sequence<boolean>
소스가 에코 제거를 수행할 수 없는 경우 단일
false가 목록의 유일한 요소여야 합니다. 소스가
에코 제거를 수행할 수 있는 경우 true가 목록에
반드시 포함되어야 합니다. 스크립트가 이 기능을 제어할 수 있는 경우 목록에는
최소한 true와 false를 모두 반드시 포함해야 합니다.
또한 소스가 어떤 오디오 소스를 제거할지 제어할 수 있도록 허용하는 경우,
EchoCancellationModeEnum
열거형에서 지원되는 모든 값을 포함해야 합니다. true
또는 false가 목록에 포함되어 있으면
EchoCancellationModeEnum의
어떤 값보다도 먼저 나타나야 합니다.
추가 세부 정보는 echoCancellation을
참조하십시오.
autoGainControl 유형:
sequence<boolean>
소스가 자동 게인 제어를 수행할 수 없으면 단일
false가 보고됩니다. 자동 게인 제어를
끌 수 없으면 단일 true가 보고됩니다. 스크립트가
이 기능을 제어할 수 있으면 소스는
true와 false를 모두 가능한
값으로 포함하는 목록을 보고합니다. 추가 세부 정보는 autoGainControl을
참조하십시오.
noiseSuppression 유형:
sequence<boolean>
소스가 노이즈 억제를 수행할 수 없으면 단일
false가 보고됩니다. 노이즈 억제를
끌 수 없으면 단일 true가 보고됩니다. 스크립트가
이 기능을 제어할 수 있으면 소스는
true와 false를 모두 가능한
값으로 포함하는 목록을 보고합니다. 추가 세부 정보는 noiseSuppression을
참조하십시오.
latency 유형: DoubleRangechannelCount 유형: ULongRangedeviceId 유형: DOMStringgroupId
유형: DOMStringbackgroundBlur 유형:
sequence<boolean>
false가
보고됩니다. 배경 흐림 기능을 끌 수 없으면 단일 true가
보고됩니다. 스크립트가 이 기능을 제어할 수 있으면 소스는
true와 false를 모두 가능한 값으로 포함하는 목록을 보고합니다. 자세한 내용은 backgroundBlur를 참조하십시오.WebIDLdictionary MediaTrackConstraints : MediaTrackConstraintSet {
sequence<MediaTrackConstraintSet> advanced;
};
MediaTrackConstraints
멤버advanced
유형:
sequence<MediaTrackConstraintSet>
이 요소의 정의는 제약 조건 및 ConstraintSet을 참조하십시오.
향후 명세에서는 적절한 유형의 딕셔너리 멤버를 가진
partial
딕셔너리를 정의하여 MediaTrackConstraintSet 딕셔너리를 확장할 수 있습니다.
WebIDLdictionary MediaTrackConstraintSet {
ConstrainULong width;
ConstrainULong height;
ConstrainDouble aspectRatio;
ConstrainDouble frameRate;
ConstrainDOMString facingMode;
ConstrainDOMString resizeMode;
ConstrainULong sampleRate;
ConstrainULong sampleSize;
ConstrainBooleanOrDOMString echoCancellation;
ConstrainBoolean autoGainControl;
ConstrainBoolean noiseSuppression;
ConstrainDouble latency;
ConstrainULong channelCount;
ConstrainDOMString deviceId;
ConstrainDOMString groupId;
ConstrainBoolean backgroundBlur;
};
MediaTrackConstraintSet
멤버width 유형: ConstrainULongheight 유형: ConstrainULongaspectRatio 유형: ConstrainDoubleframeRate 유형: ConstrainDoublefacingMode 유형: ConstrainDOMStringresizeMode 유형: ConstrainDOMStringsampleRate 유형: ConstrainULongsampleSize 유형: ConstrainULongechoCancellation 유형: ConstrainBooleanOrDOMString
autoGainControl 유형: ConstrainBooleannoiseSuppression 유형: ConstrainBooleanlatency 유형: ConstrainDoublechannelCount 유형: ConstrainULongdeviceId 유형: ConstrainDOMStringgroupId 유형: ConstrainDOMStringbackgroundBlur 유형: ConstrainBooleanMediaTrackSettings는
MediaStreamTrack의 설정을 나타냅니다. MediaStreamTrack 객체입니다.
향후 명세에서는 적절한 유형의 딕셔너리 멤버를 가진 partial 딕셔너리를 정의하여 MediaTrackSettings 딕셔너리를 확장할 수 있습니다.
WebIDLdictionary MediaTrackSettings {
unsigned long width;
unsigned long height;
double aspectRatio;
double frameRate;
DOMString facingMode;
DOMString resizeMode;
unsigned long sampleRate;
unsigned long sampleSize;
(boolean or DOMString) echoCancellation;
boolean autoGainControl;
boolean noiseSuppression;
double latency;
unsigned long channelCount;
DOMString deviceId;
DOMString groupId;
boolean backgroundBlur;
};
MediaTrackSettings
멤버width 유형: unsigned long
height 유형: unsigned long
aspectRatio 유형: doubleframeRate
유형: doublefacingMode 유형: DOMStringresizeMode 유형: DOMStringsampleRate 유형: unsigned long
sampleSize 유형: unsigned long
echoCancellation 유형: boolean 또는 DOMStringautoGainControl 유형: booleannoiseSuppression 유형: booleanlatency
유형: doublechannelCount 유형: unsigned long
deviceId 유형: DOMStringgroupId
유형: DOMStringbackgroundBlur 유형: boolean,
기본값:
true
MediaStreamTrack의 초기 제약 가능 속성 집합의 이름은 아래에 정의되어 있습니다.
다음 제약 가능 속성은 비디오와 오디오
MediaStreamTrack
객체 모두에 적용되도록 정의되어 있습니다:
| 속성 이름 | 유형 | 참고 |
|---|---|---|
| deviceId | DOMString |
MediaStreamTrack의 콘텐츠를
생성하는 장치의 식별자입니다. 이는
MediaDeviceInfo.deviceId의 정의를 따릅니다.
이 속성의 설정은
MediaStreamTrack에 연결된
소스에 의해 고유하게 결정된다는 점에 유의하십시오. 특히
getCapabilities()는
deviceId에 대해 하나의 값만
반환합니다. 따라서 이 속성은
getUserMedia()를
사용한 초기 미디어 선택에
사용할 수 있습니다. 그러나
applyConstraints()를
사용한 이후의 미디어 제어에는
유용하지 않습니다. 다른 값을
설정하려는 모든 시도는 충족할 수 없는
ConstraintSet을 초래하기 때문입니다.
길이가 0인 문자열을 deviceId 값 제약 조건으로
getUserMedia()와
함께 사용하는 경우,
해당 제약 조건이 지정되지 않은 것처럼
해석될 수 있습니다.
|
| groupId | DOMString |
MediaStreamTrack의 콘텐츠를
생성하는 장치에 대한 문서별 고유 그룹
식별자입니다.
이는
MediaDeviceInfo.groupId의 정의를 따릅니다.
이 속성의 설정은
MediaStreamTrack에 연결된
소스에 의해 고유하게 결정된다는 점에 유의하십시오. 특히
getCapabilities()는
groupId에 대해 하나의 값만
반환합니다. 이 속성은 브라우징 세션 간에 안정적이지
않으므로 getUserMedia()를
사용한 초기 미디어
선택에서의 유용성이 제한됩니다. 또한
applyConstraints()를
사용한 이후의 미디어 제어에는
유용하지 않습니다. 다른 값을
설정하려는 모든 시도는 충족할 수 없는
ConstraintSet을 초래하기 때문입니다.
|
다음 제약 가능 속성은 비디오
MediaStreamTrack
객체에만 적용되도록 정의되어 있습니다:
| 속성 이름 | 유형 | 참고 |
|---|---|---|
| width | unsigned long
|
픽셀 단위의 너비입니다. 기능으로서 유효 범위는 비디오 소스의 사전 설정 너비 값을 포함해야 하며, min은 1이고 max는 가장 큰 너비여야 합니다. 사용자 에이전트는 min 너비 범위 값과 네이티브 해상도 너비 사이의 모든 값으로 다운샘플링을 반드시 지원해야 합니다. |
| height | unsigned long
|
픽셀 단위의 높이입니다. 기능으로서 유효 범위는 비디오 소스의 사전 설정 높이 값을 포함해야 하며, min은 1이고 max는 가장 큰 높이여야 합니다. 사용자 에이전트는 min 높이 범위 값과 네이티브 해상도 높이 사이의 모든 값으로 다운샘플링을 반드시 지원해야 합니다. |
| frameRate | double |
프레임 속도(초당 프레임 수)입니다. 비디오 소스의 사전 설정에서 프레임 속도를 결정할 수 있다면, 기능으로서 유효 범위는 비디오 소스의 사전 설정 프레임 속도 값을 포함해야 하며 min은 0이고 max는 가장 큰 프레임 속도여야 합니다. 사용자 에이전트는 네이티브 해상도 프레임 속도를 정수 비율로 감소시켜 얻은 프레임 속도를 반드시 지원해야 합니다. 프레임 속도를 결정할 수 없는 경우(예: 소스가 기본적으로 프레임 속도를 제공하지 않거나 소스 스트림에서 프레임 속도를 결정할 수 없는 경우), 기능 값은 사용자 에이전트의 vsync 디스플레이 속도를 반드시 나타내야 합니다. 설정으로서 이 값은 구성된 프레임 속도를 나타냅니다.
감소가 사용된 경우 네이티브
프레임 속도가 아니라 해당 값을 나타냅니다. 예를 들어 감소를 통해
설정이 초당 25프레임이고 카메라의 네이티브 프레임 속도는 초당 30프레임이지만
조명 조건으로 인해 실제로는 초당 20프레임만
달성되는 경우, |
| aspectRatio | double |
정확한 종횡비(픽셀 단위 너비를 픽셀 단위 높이로 나눈 값을 소수점 열째 자리까지 반올림한 double로 표현) 또는 종횡비 범위입니다. |
| facingMode | DOMString |
이 문자열은
VideoFacingModeEnum의 멤버 중
하나입니다.
멤버는 사용자 관점에서 볼 때 카메라가 향할 수 있는 방향을
설명합니다. 이 열거형에 없는 문자열에 대해서는
가
정확히 동일한 문자열을 반환하지 않을 수도 있다는 점에 유의하십시오. 이는
이 속성에 향후 버전의 WebIDL
열거형을 사용할 가능성을 보존합니다.
|
| resizeMode | DOMString |
이 문자열은
VideoResizeModeEnum의 멤버 중
하나입니다.
멤버는
UA가 해상도를 도출할 수 있는 방법을
설명합니다. 즉, UA가 카메라 출력에
자르기 및 다운스케일링을 사용할 수 있는지 여부를 나타냅니다.
UA는 "none"이 사용될 때 네이티브
해상도를 모방하기 위해 다운스케일링, 업스케일링 및/또는 자르기를 사용하여 카메라의 동시 사용을
숨길 수 있지만, 카메라가
사용자
에이전트 외부의 다른 애플리케이션에서 사용 중인 경우에만 가능합니다. 가
정확히 동일한 문자열을 반환하지 않을 수도 있다는 점에 유의하십시오. 이는
이 속성에 향후 버전의 WebIDL
열거형을 사용할 가능성을 보존합니다.
|
| backgroundBlur | boolean |
일부 플랫폼이나 사용자 에이전트는 비디오 프레임, 특히 카메라 비디오 스트림의 배경 흐림 기능을 기본 제공할 수 있습니다. 웹 애플리케이션은 소스 수준에서 배경 흐림이 적용된다는 사실을 제어하거나 적어도 인식하고자 할 수 있습니다. 예를 들어 이를 통해 웹 애플리케이션이 UI를 업데이트하거나 자체적으로 배경 흐림을 적용하지 않도록 할 수 있습니다. |
지속적으로 변하는 환경 요인에 대응하여 캡처된 결과 비디오의 X축과
Y축을 자동으로 전환하는 것이 바람직한 시스템에서는
width, height 및 aspectRatio
제약 조건과 기능은 모든 알고리즘에서 영향을 받지 않은 상태를 반드시 유지해야 하며
기본 방향에서만 고려되어야 합니다. 단,
getSettings()
알고리즘에서는 이러한
제약 가능 속성의 설정을 필요한 경우 전환하여 어느 시점에서든
반환되는 캡처 비디오의 크기와 일치하도록 반드시 해야 합니다.
결과 캡처 비디오의 X축과 Y축 전환을 지원하는 시스템의 기본 방향은 해당 시스템에 대해 사용자 에이전트가 정의합니다.
WebIDLenum VideoFacingModeEnum {
"user",
"environment",
"left",
"right"
};
| 열거형 값 | 설명 |
|---|---|
user |
소스가 사용자를 향합니다(셀프뷰 카메라). |
environment |
소스가 사용자 반대 방향을 향합니다(주변 환경을 봅니다). |
left |
소스가 사용자의 왼쪽을 향합니다. |
right |
소스가 사용자의 오른쪽을 향합니다. |
아래는 사용자와 관련된 비디오 방향 모드를 보여 주는 그림입니다.
WebIDLenum VideoResizeModeEnum {
"none",
"crop-and-scale"
};
| 열거형 값 | 설명 |
|---|---|
none |
이 해상도와 프레임 속도는 카메라, 해당 드라이버 또는 OS에서 제공합니다. 참고: UA는 동시 사용을
숨기기 위해 이 값을 보고할 수 있지만,
카메라가 다른 탐색
가능 항목에서 사용 중인
경우에만 가능합니다. |
crop-and-scale |
이 해상도는 사용자 에이전트가 더 높은 카메라 해상도에서 다운스케일 및/또는 잘라낸 것이거나, 프레임 속도가 사용자 에이전트에 의해 감소된 것입니다. 아래에 명시된 경우를 제외하고 미디어를 업스케일하거나 늘리거나 입력 소스에서 발생하지 않은 가짜 데이터를 생성해서는 안 됩니다. 참고: UA는 동시 사용을
숨기기 위해 업스케일할 수 있지만, 카메라가
사용자 에이전트 외부의 다른 애플리케이션에서 사용 중인
경우에만 가능합니다. |
다음 제약 가능 속성은 오디오
MediaStreamTrack
객체에만 적용되도록 정의되어 있습니다:
| 속성 이름 | 값 | 참고 |
|---|---|---|
| sampleRate | unsigned long
|
오디오 데이터의 초당 샘플 수로 나타낸 샘플 속도입니다. |
| sampleSize | unsigned long
|
비트 단위의 선형 샘플 크기입니다. 제약 조건으로서는 선형 샘플을 생성하는 오디오 장치에 대해서만 충족될 수 있습니다. |
| echoCancellation | boolean 또는 DOMString |
이는 false, true 또는
EchoCancellationModeEnum의
멤버 중 하나입니다.
여러 마이크의 처리 과정에서 하나 이상의 오디오 스트림이
재생되고 있을 때, 마이크가 기록한 입력 신호에서
재생 중인 소리를 제거하려고 시도하는 것이 흔히 바람직합니다.
이를 에코 제거라고 합니다. 필요하지 않은 경우도 있으며,
오디오 아티팩트가 발생하지 않도록 이를 끄는 것이
바람직할 수 있습니다. 이를 통해 애플리케이션이 이
동작을 제어할 수 있습니다.
|
| autoGainControl | boolean |
마이크가 기록한 입력 신호에는 자동 게인 제어가 흔히 바람직합니다. 필요하지 않은 경우도 있으며 오디오가 변경되지 않도록 이를 끄는 것이 바람직할 수 있습니다. 이를 통해 애플리케이션이 이 동작을 제어할 수 있습니다. |
| noiseSuppression | boolean |
마이크가 기록한 입력 신호에는 노이즈 억제가 흔히 바람직합니다. 필요하지 않은 경우도 있으며 오디오가 변경되지 않도록 이를 끄는 것이 바람직할 수 있습니다. 이를 통해 애플리케이션이 이 동작을 제어할 수 있습니다. |
| latency | double |
초 단위의 지연 시간 또는 지연 시간 범위입니다. 지연 시간은 처리 시작 시점(예: 실제 세계에서 소리가 발생한 때)부터 프로세스의 다음 단계에서 데이터를 사용할 수 있게 될 때까지의 시간입니다. 일부 애플리케이션에서는 낮은 지연 시간이 매우 중요하며, 다른 애플리케이션에서는 전력 제약을 완화하는 데 도움이 되므로 높은 지연 시간이 허용될 수 있습니다. 이 값은 구성의 목표 지연 시간을 나타낼 것으로 예상되며, 실제 지연 시간은 이 값에서 다소 달라질 수 있습니다. |
| channelCount | unsigned long
|
오디오 데이터가 포함하는 독립적인 사운드 채널의 수, 즉 샘플 프레임당 오디오 샘플 수입니다. |
WebIDLenum EchoCancellationModeEnum {
"all",
"remote-only"
};
| 열거형 값 | 설명 |
|---|---|
"all" |
시스템은 시스템에서 재생 중인 모든 소리를 마이크의 입력 신호에서 제거하려고 반드시 시도해야 합니다. 이 옵션은 알림이나 스크린 리더와 같은 로컬 오디오의 전송을 방지하므로 최대한의 개인정보 보호를 제공하기 위한 것입니다. |
"remote-only"
|
시스템은 WebRTC 어떤 |
EchoCancellationModeEnum의 값
외에도,
echoCancellation
제약 가능 속성은 true 및 false 값도 허용합니다.
false는 에코 제거가 수행되지 않음을 의미합니다.
true는 마이크가 기록한 신호에서 어떤 오디오를 제거할지
UA가 결정한다는 의미입니다. true는 적어도 "remote-only"만큼
제거하려고 반드시 시도해야 하며
"all"만큼 제거하려고
시도해야 합니다.
MediaStreamTrack
객체가 종료되지 않았으며
mute, unmute
또는 ended 이벤트에 등록된 이벤트 리스너가 하나라도 있다면
해당 객체를 가비지 컬렉션해서는 안 됩니다.
각 소스 유형은 특정 이벤트를 전혀 발생시키지 않을 수도 있으므로
가비지 컬렉션 규칙을 더 구체적으로 정의할 수 있습니다.
MediaStreamTrack에서
stop()을 호출할 것을 권장합니다.
특히 캡처 트랙은 기반 리소스의 비용이 크고
사용자에게 표시되는 개인정보 보호 표시기에 영향을 줄 수 있기 때문입니다.
addtrack
및 removetrack 이벤트는
MediaStreamTrackEvent
인터페이스를 사용합니다.
addtrack 및 removetrack 이벤트는
사용자 에이전트에 의해
MediaStream의
트랙 집합이 업데이트되었음을 스크립트에 알립니다.
e라는 이름의 트랙 이벤트를
발생시키고 MediaStreamTrack
track을 사용한다는 것은, e라는 이름을 가지며
버블링되지 않고(달리 명시된 경우 제외) 취소할 수 없으며
(달리 명시된 경우 제외),
MediaStreamTrackEvent
인터페이스를 사용하고
track
속성이 track으로 설정된 이벤트를 생성하여 지정된 대상에서
디스패치해야 함을 의미합니다.
WebIDL[Exposed=Window]
interface MediaStreamTrackEvent : Event {
constructor(DOMString type, MediaStreamTrackEventInit eventInitDict);
[SameObject] readonly attribute MediaStreamTrack track;
};
constructor()새로운
MediaStreamTrackEvent를
생성합니다.
track 유형: MediaStreamTrack, 읽기 전용track
속성은 이벤트와 연결된 MediaStreamTrack
객체를 나타냅니다.
WebIDLdictionary MediaStreamTrackEventInit : EventInit {
required MediaStreamTrack track;
};
track 유형: MediaStreamTrack, 필수이 절은 비규범적입니다.
사용자 에이전트는 소스에서 싱크로 이어지는 미디어 파이프라인을 제공합니다. 사용자 에이전트에서
싱크는
<img>,
<video>
및
<audio>
태그입니다.
전통적인 소스에는 스트리밍 콘텐츠, 파일 및 웹 리소스가 포함됩니다. 이러한
소스에서 생성되는 미디어는 일반적으로 시간이 지나도 변경되지 않으므로 이러한
소스는 정적이라고 볼 수 있습니다.
이러한 소스를 사용자에게 표시하는 싱크(실제 태그
자체)에는 소스 콘텐츠를 조작하기 위한 다양한 제어 기능이 있습니다.
예를 들어
<img>
태그는 1600x1200 픽셀의 거대한 소스 이미지를
width="400" 및 height="300"으로 정의된 사각형에 맞도록
축소합니다.
소스에는 수명이 있습니다. 기본적으로 소스의 수명은
이를 생성한 컨텍스트에 연결됩니다. 예를 들어
MediaDevices.getUserMedia()에 의해 생성된 소스는
해당 navigator.mediaDevices 컨텍스트에 의해 생성된 것으로 간주됩니다.
마찬가지로 RTCRtpReceiver 객체의 소스는
RTCPeerConnection 자체에
바인딩되며, 이는 다시 해당 생성 컨텍스트에 바인딩됩니다.
특정 소스의 정의에 명시적으로 달리 언급되지 않는 한,
소스는 해당 생성 컨텍스트가 사라질 때 항상 중지됩니다.
서로 다른 컨텍스트의 두 소스가
동시에 동일한 캡처 장치를 사용할 수 있다는 점에 유의해야 합니다.
한 소스는 다른 소스와 독립적으로 중지될 수 있습니다.
getUserMedia API는 마이크 및 카메라와 같은 동적 소스를
추가합니다. 이러한 소스의 특성은 애플리케이션 요구에 따라
변경될 수 있습니다. 이러한 소스는 본질적으로 동적이라고 볼 수 있습니다.
동적 소스의 미디어를 표시하는
<video>
요소는 크기 조정을 수행하거나 미디어
파이프라인을 따라 정보를 피드백하여 소스가 표시에 더 적합한 콘텐츠를
생성하도록 할 수 있습니다.
참고: 이러한 종류의 피드백 루프는 분명히 단순히 "최적화"를 가능하게 하는 것이지만, 그 이득은 결코 작지 않습니다. 이러한 최적화를 통해 배터리를 절약하고, 네트워크 혼잡을 줄이는 등의 효과를 얻을 수 있습니다...
MediaStream 싱크(예:
<video>,
<audio>,
심지어
RTCPeerConnection)는
이 명세에 설명된 설정,
기능
및 Constraints가
제공하는 것보다 더 나아가 소스 스트림을 변환하기 위한 메커니즘을 계속
가집니다. (RTCPeerConnection의 것을 포함한
싱크 변환 옵션은 이
명세의 범위를 벗어납니다.)
트랙 제약 조건을 변경하거나 적용하면 해당 소스를 공유하는 모든 트랙의
설정과
결과적으로 해당 소스를 사용하는 모든 하위 단계 싱크에 영향을 줄 수 있습니다. 많은 싱크는
<
요소나 video>RTCPeerConnection처럼
이러한 변경을 문제없이 처리할 수 있습니다.
Recorder API와 같은 다른 싱크는 소스 설정
변경으로 인해 실패할 수 있습니다.
RTCPeerConnection은
네트워크를 통한 스트림에 대해 싱크 및 소스 역할을
동시에 수행하므로 흥미로운 객체입니다. 싱크로서는 소스 변환
기능(예: 비트 전송률 낮추기, 해상도 확대/축소,
프레임 속도 조정)을 가지며, 소스로서는 트랙 소스에 의해 자체 설정이
변경될 수 있습니다.
주어진 소스의 변경이 여러 싱크에 어떤 영향을 미치는지 설명하기 위해
다음 예를 살펴보겠습니다. 이 예에서는 너비와 높이만 사용하지만,
동일한 원칙은 이 명세에서 노출하는 모든 설정에 적용됩니다.
첫 번째 그림에서는 홈 클라이언트가 로컬 비디오
카메라에서 비디오 소스를 얻었습니다. 소스의 너비와 높이 설정은
각각 800픽셀과 600픽셀입니다. 홈 클라이언트의 세
MediaStream 객체에는 동일한 <deviceId를 사용하는 트랙이
포함되어 있습니다. 세 미디어 스트림은
서로 다른 세 싱크, 즉
<
요소(A), 또 다른
video><
요소(B), 그리고 피어
연결(C)에 연결되어 있습니다. 피어 연결은 소스 비디오를
원격 클라이언트로 스트리밍하고 있습니다. 원격 클라이언트에는 피어 연결을
소스로 사용하는 트랙이 포함된 두 미디어 스트림이 있습니다. 이 두 미디어 스트림은 두
video><
요소 싱크(Y 및
Z)에 연결되어 있습니다.
video>
이 시점에서 홈 클라이언트의 모든 싱크는 원래 소스가 제공한 크기 설정에 변환을 적용해야 한다는 점에 유의하십시오. B는 비디오를 축소하고, A는 비디오를 확대하여(품질 저하 발생), C 역시 네트워크를 통해 전송하기 위해 비디오를 약간 확대합니다. 원격 클라이언트에서는 싱크 Y가 비디오를 매우 크게 축소하는 반면 싱크 Z는 어떤 크기 조정도 적용하지 않습니다.
applyConstraints()가
호출된 것에 대한 응답으로, 트랙 중 하나가 홈
클라이언트의 비디오 소스에서 더 높은 해상도(1920 x 1200픽셀)를 원합니다.
소스 변경은 홈 클라이언트의 모든 트랙과 싱크에 즉시 영향을 주지만, 원격 클라이언트의 어떤 싱크(또는 소스)에도 영향을 주지 않는다는 점에 유의하십시오. 홈 클라이언트 소스 비디오의 크기가 증가함에 따라 싱크 A는 더 이상 크기 조정을 수행할 필요가 없지만, 싱크 B는 이전보다 더 많이 축소해야 합니다. 싱크 C(피어 연결)는 이제 원격 클라이언트로의 전송을 일정하게 유지하기 위해 비디오를 축소해야 합니다.
그림에는 표시되지 않았지만, 원격 클라이언트 측에서도 동일하게 유효한 설정 변경 요청을 수행할 수 있습니다. 이는 앞서 A, B 및 C가 영향을 받은 것과 같은 방식으로 싱크 Y와 Z에 영향을 미칠 뿐 아니라, 홈 클라이언트의 비디오 소스에 적용하는 변환을 변경하기 위해 홈 클라이언트의 피어 연결과 재협상이 발생할 수도 있습니다. 이러한 변경은 싱크 A 또는 B나 홈 클라이언트의 비디오 소스와 관련된 어떤 것도 변경할 필요가 없습니다.
이 명세는 원격 클라이언트의 비디오 소스 변경이 자동으로 홈 클라이언트의 비디오 소스 변경을 유발할 수 있는 메커니즘을 정의하지 않는다는 점에 유의하십시오. 구현은 다음 예에서 보여 주듯 애플리케이션이 설정한 제약 조건 내에서만 수행하는 한 이러한 소스-싱크 최적화를 선택하여 수행할 수 있습니다.
주어진 소스의 변경이 싱크 소비자에게 영향을 미친다는 것은 상당히
명백합니다. 그러나 일부 상황에서는 주어진 싱크의 변경이
구현으로 하여금 소스의 설정을 조정하게 할 수도 있습니다. 이는
다음 그림에 설명되어 있습니다. 아래 첫 번째 그림에서 홈 클라이언트의 비디오
소스는 1920 x 1200픽셀 크기의 비디오 스트림을 전송하고 있습니다. 비디오
소스에는 또한 제약 조건이 없으므로 애플리케이션의 관점에서는
정확한 소스 크기를 유연하게 정할 수 있습니다. 두
MediaStream 객체에는 동일한
deviceId를 가진 트랙이 포함되어 있으며, 해당 MediaStream들은
서로 다른 두
<
요소 싱크 A와
B에 연결되어 있습니다. 싱크 A의 크기는 video>width="1920" 및
height="1200"으로 설정되어 있으며 변환 없이 소스의 비디오 콘텐츠를
표시하고 있습니다. 싱크 B는 더 작은 크기로 설정되어 있으며, 그
결과 비디오를 너비 320픽셀,
높이 200픽셀의 사각형에 맞도록 축소하고 있습니다.
애플리케이션이 싱크 A를 더 작은 크기(너비 1920에서 1024픽셀로, 높이 1200에서 768픽셀로)로 변경하면 사용자 에이전트의 미디어 파이프라인은 어느 싱크도 더 높은 소스 해상도를 필요로 하지 않으며 소스와 싱크 A 양쪽에서 불필요한 작업이 수행되고 있음을 인식할 수 있습니다. 이러한 경우 더 높은 해상도의 비디오를 계속 생성하도록 소스를 강제하는 다른 제약 조건이 없다면, 미디어 파이프라인은 소스 해상도를 변경할 수 있습니다:
위 그림에서 홈 클라이언트의 비디오 소스 해상도는 재생을 최적화하기 위해 싱크 A와 B 중 더 큰 해상도로 변경되었습니다. 위에는 표시되지 않았지만 동일한 동작이 피어 연결 및 다른 싱크에도 적용될 수 있습니다.
소스 자체가 제약 조건을
충족할 수 없거나 소스가 이미 충돌하는 제약 조건을 충족하고 있기 때문에
소스가 충족할 수 없는 제약 조건이 트랙에 적용될 수 있습니다.
이런 일이 발생하면
applyConstraints()가
반환한 프로미스는 새 제약 조건을 적용하지 않은 채
거부됩니다. 이
경우 제약 조건에 변경이 발생하지 않으므로, 이 조건의 결과로
소스 자체에도 변경이 요구되지 않습니다. 다음은 이러한
동작의 예입니다.
이 예에서 두 미디어 스트림은 각각 동일한 소스를 공유하는 비디오 트랙을 하나씩 가지고 있습니다. 첫 번째 트랙에는 처음에 제약 조건이 적용되지 않았습니다. 이 트랙은 싱크 N에 연결되어 있습니다. 싱크 N의 해상도는 800 x 600픽셀이며 소스의 1024 x 768 해상도를 이에 맞게 축소하고 있습니다. 다른 트랙에는 소스의 보조 조명을 강제로 끄는 필수 제약 조건이 있으며 싱크 P에 연결되어 있습니다. 싱크 P의 너비와 높이는 소스와 동일합니다.
이제 첫 번째 트랙에 보조 조명을 강제로 켜야 한다는 필수 제약 조건이 추가됩니다. 이 시점에서 두 필수 제약 조건을 소스가 동시에 충족할 수 없습니다(보조 조명을 동시에 켜고 끌 수는 없습니다). 이 상태는 첫 번째 트랙이 충돌하는 제약 조건을 적용하려고 시도하면서 발생했으므로 제약 조건 적용이 실패하며, 소스의 설정이나 어느 트랙의 제약 조건에도 변경이 없습니다.
MediaStream은 미디어 요소에 할당될 수 있습니다.
MediaStream은 미리 로드하거나 탐색할 수 없으며
단순하고 잠재적으로 무한한 선형
미디어 타임라인을 나타냅니다. 타임라인은
0에서 시작하며 미디어 요소가
잠재적으로 재생 중인 동안 실시간으로 선형 증가합니다. 타임라인은
MediaStream의 재생이 일시 중지되면 증가하지 않습니다.
이 명세를 지원하는 사용자 에이전트는
[HTML]에
정의된 HTMLMediaElement
인터페이스의
srcObject
속성을 반드시 지원해야 하며,
여기에는 MediaStream
객체 재생 지원이 포함됩니다.
[HTML]
문서에서는 HTMLMediaElement가
미디어 제공자 객체와 함께 작동하는 방식을 설명합니다. 미디어 제공자 객체가
MediaStream인 경우
다음이 적용됩니다:
AudioTrack
또는 VideoTrack이
생성될 때마다 id 및 label 속성은
MediaStreamTrack의 해당 속성으로
초기화해야 하며, kind 속성은
"main"으로, language 속성은 빈
문자열로 초기화해야 합니다.
MediaStream의 현재 데이터를 반드시
재생해야 하며
버퍼링해서는 안 됩니다.
MediaStream의 트랙 집합 내 순서는 정의되어 있지 않으므로,
AudioTrackList
및 VideoTrackList의
정렬 방식에는 어떠한 요구 사항도 부과되지 않습니다.
요소가 HTMLVideoElement인
경우 비디오 재생이 종료되면 재생이 종료된 것으로
간주하며, 이는 다음과 같은 경우입니다:
요소의
readyState가
HAVE_METADATA
이상이고,
MediaStream
상태가
활성 상태였던 후
비활성 상태가 되었거나,
play()가
마지막으로 호출된 후
MediaStream
상태가
활성 상태였다가
비활성 상태가 된 후 다시
활성 상태가 되었으며,
autoplay가
false인 경우입니다.
재생이 종료된 후에는 새로운
MediaStreamTrack이
MediaStream에
추가되더라도 autoplay가
true이거나, 예를 들어 웹
애플리케이션이 play()를
호출하여 요소를 다시 시작하지 않는 한 재생이 재개되지 않습니다.
요소가 HTMLAudioElement인
경우 오디오 재생이 종료되면 재생이 종료된 것으로
간주하며, 이는 다음과 같은 경우입니다:
요소의
readyState가
HAVE_METADATA
이상이고,
MediaStream
상태가
청취 가능 상태였던 후
청취 불가능 상태가 되었거나,
play()가
마지막으로 호출된 후 MediaStream
상태가
청취 가능 상태였다가
청취 불가능 상태가 된 후 다시
청취 가능 상태가 되었으며,
autoplay가
false인 경우입니다.
재생이 종료된 후에는 새로운 오디오
MediaStreamTrack이
MediaStream에
추가되더라도 autoplay가
true이거나, 예를 들어 웹
애플리케이션이 play()를
호출하여 요소를 다시 시작하지 않는 한 재생이 재개되지 않습니다.
HTMLMediaElement에서
fastSeek()
메서드에 대한 모든 호출은
무시해야 합니다.
MediaStream의 특성으로 인해
연결된
HTMLMediaElement의
속성 동작 및 여기서 수행할 수 있는 연산에는 아래와 같은
특정 제한이 적용됩니다:
| 속성 이름 | 속성 유형 | 제공자가 MediaStream일 때의 Setter/Getter 동작 | 추가 고려 사항 |
|---|---|---|---|
preload
|
DOMString |
가져올 때: none. 설정할 때: 무시됩니다. |
MediaStream은 미리 로드할 수 없습니다. |
buffered
|
TimeRanges
|
buffered.length는 0을 반드시 반환해야 합니다. |
MediaStream은 미리 로드할 수 없습니다. 따라서
버퍼링된 양은
항상 빈 시간 범위입니다. |
currentTime
|
double |
음수가 아닌 모든 정수입니다. 초기값은 0이며,
요소가 잠재적으로
재생 중일 때마다 값이 실시간으로 선형 증가합니다.
|
값은 초 단위의 공식 재생 위치입니다. 이를 변경하려는 모든 시도는 반드시 무시해야 합니다. |
seeking
|
boolean |
false |
MediaStream은 탐색할 수 없습니다. 따라서
이 속성은 항상 false 값을 반드시
반환해야 합니다. |
defaultPlaybackRate
|
double |
가져올 때: 1.0. 설정할 때: 무시됩니다. |
MediaStream은 탐색할 수 없습니다. 따라서
이 속성은 항상 1.0 값을 반드시
반환해야 하며 이를 변경하려는 모든 시도는
반드시 무시해야 합니다. 이는 또한
ratechange
이벤트가 발생하지 않음을 의미합니다.
|
playbackRate
|
double |
가져올 때: 1.0. 설정할 때: 무시됩니다. |
MediaStream은 탐색할 수 없습니다. 따라서
이 속성은 항상 1.0 값을 반드시
반환해야 하며 이를 변경하려는 모든 시도는
반드시 무시해야 합니다. 이는 또한
ratechange
이벤트가 발생하지 않음을 의미합니다.
|
played
|
TimeRanges
|
played.length는 1을 반드시 반환해야 합니다.played.start(0)은 0을 반드시 반환해야 합니다.played.end(0)은 마지막으로 알려진 currentTime을
반드시 반환해야 합니다.
|
MediaStream의 타임라인은 항상
0에서 시작하여 currentTime까지 이어지는 하나의 범위로 구성됩니다. |
seekable
|
TimeRanges
|
seekable.length는 0을 반드시 반환해야 합니다. |
MediaStream은 탐색할 수 없습니다. |
loop
|
boolean |
true, false |
MediaStream에는 정의된 끝이 없어
반복할 수 없으므로 loop
속성을 설정해도 아무 효과가 없습니다.
|
위에 나열된 setter 중 어느 것도
HTMLMediaElement의
내부 상태를
변경하지 않으므로, MediaStream이 더 이상
요소의 할당된
미디어 제공자 객체가 아니게 되면 나열된 속성은 스트림이 요소에 할당되기
전의 값으로 돌아간 것처럼 보입니다.
srcObject에
null 또는 스트림이 아닌 객체가 할당되면,
미디어 요소 로드
알고리즘 직전에 MediaStream은 더 이상 요소의 할당된 미디어
제공자 객체가 아니게 됩니다. 그 결과
playbackRate
및 defaultPlaybackRate가
MediaStream이 할당되기 전과
달랐다면
ratechange
이벤트가 발생할 수 있습니다(7단계에서).
일부 연산은 OverconstrainedError를 던지거나 발생시킵니다. 이는
제약 조건 실패와 관련된 추가
정보를 전달하는 DOMException의 확장입니다.
WebIDL[Exposed=Window]
interface OverconstrainedError : DOMException {
constructor(DOMString constraint, optional DOMString message = "");
readonly attribute DOMString constraint;
};
OverconstrainedError다음 단계를 실행합니다:
constraint를 생성자의 첫 번째 인수로 합니다.
message를 생성자의 두 번째 인수로 합니다.
e를 새로운
OverconstrainedError
객체로 합니다.
e의
DOMException
생성자를 호출하되,
message 인수는 message로 설정하고
name 인수는
"OverconstrainedError"로 설정합니다.
이 이름에는 레거시
코드에 대한 매핑이 없으므로 e의 code 속성은
0을 반환합니다.
e.constraint를 constraint로 설정합니다.
e를 반환합니다.
constraint 유형: DOMString,
읽기 전용이 오류와 관련된 제약 조건의 이름이며,
특정 제약 조건 이름이 공개되지 않는 경우 ""입니다.
이 절은 비규범적입니다.
다음 이벤트는 MediaStream
객체에서 발생합니다:
| 이벤트 이름 | 인터페이스 | 발생하는 경우... |
|---|---|---|
| addtrack | MediaStreamTrackEvent |
새로운 MediaStreamTrack이
이 스트림에 추가되었습니다. 스크립트가 MediaStream의 트랙을 직접
수정할 때는 이 이벤트가 발생하지 않는다는 점에 유의하십시오. |
| removetrack | MediaStreamTrackEvent |
MediaStreamTrack이
이 스트림에서 제거되었습니다. 스크립트가 MediaStream의 트랙을 직접
수정할 때는 이 이벤트가 발생하지 않는다는 점에 유의하십시오. |
다음 이벤트는 MediaStreamTrack
객체에서 발생합니다:
| 이벤트 이름 | 인터페이스 | 발생하는 경우... |
|---|---|---|
| mute | Event |
MediaStreamTrack
객체의 소스가
일시적으로 데이터를 제공할 수 없습니다. |
| unmute | Event |
MediaStreamTrack
객체의 소스가 일시적으로 데이터를 제공할 수 없었던 후
다시 라이브 상태가 되었습니다. |
| ended | Event |
|
다음 이벤트는 MediaDevices
객체에서 발생합니다:
| 이벤트 이름 | 인터페이스 | 발생하는 경우... |
|---|---|---|
| devicechange | DeviceChangeEvent
|
사용자 에이전트에서
사용할 수 있는 미디어 장치 집합이
변경되었습니다. 현재 장치 목록은
devices 속성에서 사용할 수 있습니다.
|
이 절에서는 연결된 미디어 입력 및 출력 장치(예: 웹 카메라 또는 헤드셋)에 대해 사용자 에이전트에 질의하기 위해 스크립트가 사용할 수 있는 API를 설명합니다.
MediaDevicesMediaDevices 객체는
사용자 에이전트에서 사용할 수 있는 미디어 장치를 검사하고 액세스하는 데 사용되는
API의 진입점입니다.
realm이 주어졌을 때 MediaDevices를 생성하려면 다음 단계를 실행합니다:
mediaDevices를 realm의 새로운 MediaDevices 객체로 하고,
다음 내부 슬롯으로 초기화합니다:
[[devicesLiveMap]], 빈 맵으로 초기화합니다.
[[devicesAccessibleMap]], 빈 맵으로 초기화합니다.
[[kindsAccessibleMap]], 빈 맵으로 초기화합니다.
[[storedDeviceList]], 사용자 에이전트에서 사용할 수 있는 모든 미디어 입력 및 출력 장치의 목록으로 초기화합니다.
[[canExposeCameraInfo]], false로
초기화합니다.
[[canExposeMicrophoneInfo]], false로
초기화합니다.
[[mediaStreamTrackSources]], 빈 집합으로 초기화합니다.
settings를 mediaDevices의 관련 설정 객체로 합니다.
MediaDevices.getUserMedia()가
노출하는 각 장치 종류 kind에 대해 다음 단계를 실행합니다:
settings에 대해 kind와 연결된 권한(예: "camera",
"microphone")의
권한 상태가
"granted"이면
mediaDevices.[[kindsAccessibleMap]][kind]를
true로 설정하고,
그렇지 않으면
false로 설정합니다.
MediaDevices.getUserMedia()가
노출하는 각 개별 장치에 대해, 해당 장치의
deviceId인 deviceId를 사용하여 다음 단계를 실행합니다:
mediaDevices.[[devicesLiveMap]][deviceId]를
false로 설정하고,
settings에 대해 장치의 종류 및
deviceId와 연결된 권한의 권한 상태가
"granted"이면
mediaDevices.[[devicesAccessibleMap]][deviceId]를
true로 설정하고,
그렇지 않으면
false로 설정합니다.
mediaDevices를 반환합니다.
getUserMedia()가 노출하는
각 장치 종류 kind에 대해,
mediaDevices의 관련
설정 객체에 대한 kind와 연결된 권한의
권한 상태가 전환될 때마다,
다음 단계를 실행합니다:
다른 값에서 "granted"로
전환된 경우
mediaDevices.[[kindsAccessibleMap]][kind]를
true로 설정합니다.
"granted"에서
다른 값으로 전환된 경우
mediaDevices.[[kindsAccessibleMap]][kind]를
false로 설정합니다.
getUserMedia()가 노출하는
각 장치에 대해,
mediaDevices의 관련
설정 객체에 대한 장치의 종류 및 장치의 deviceId인 deviceId와 연결된 권한의
권한
상태가 전환될 때마다 다음
단계를 실행합니다:
다른 값에서 "granted"로
전환된 경우,
mediaDevices.[[devicesAccessibleMap]][deviceId]가
아직 true가 아니라면
true로 설정합니다.
"granted"에서
다른 값으로 전환되고 장치가 현재 중지된 경우,
mediaDevices.[[devicesAccessibleMap]][deviceId]를
false로 설정합니다.
새로운 미디어 입력 및/또는 출력 장치를
사용자 에이전트에서 사용할 수 있게 되거나, 사용할 수 있던 입력 및/또는 출력 장치를
사용할 수 없게 되거나, MediaDeviceKind의 입력 및/또는 출력
장치에 대한
시스템 기본값이 변경되면, 사용자 에이전트는
장치 열거를 진행할 수 있음이
true인 각 MediaDevices
객체 mediaDevices에 대해 다음
장치 변경 알림 단계를 반드시
실행해야 하며,
다른 어떤 MediaDevices 객체에 대해서도
실행해서는 안 됩니다:
lastExposedDevices를
mediaDevices 및
mediaDevices.[[storedDeviceList]]를 사용하여
장치 정보 객체 목록을
생성한 결과로 합니다.
deviceList를 사용자 에이전트에서 사용할 수 있는 모든 미디어 입력 및/또는 출력 장치의 목록으로 합니다.
newExposedDevices를 mediaDevices 및 deviceList를 사용하여 장치 정보 객체 목록을 생성한 결과로 합니다.
newExposedDevices의 MediaDeviceInfo
객체가 lastExposedDevices의 객체와 일치하고 순서도 같으면
이 단계를 중단합니다.
enumerateDevices
알고리즘으로 인해,
위 단계는 devicechange
이벤트가
특정 MediaDeviceKind의 장치를 열거하기 위해
enumerateDevices를
사용할
수 있도록
허용된 문서에서만 발생하도록 제한합니다.
mediaDevices.[[storedDeviceList]]를
deviceList로 설정합니다.
mediaDevices에서 devicechange라는 이름의
이벤트를 발생시키는 태스크를 대기열에 넣되,
DeviceChangeEvent
생성자를 사용하고 devices를
newExposedDevices로 초기화합니다.
여러 이벤트가 발생할 예정이거나 여러 장치가 동시에 추가 또는 제거되는 경우(예: 마이크가 있는 카메라), 사용자 에이전트는 여러 이벤트 발생을 하나의 이벤트 발생으로 결합할 수 있습니다.
또한 이전에 순회된 MediaDevices 객체가
나중에 장치 열거를 진행할 수 있음
기준을 충족하게 되면(예:
보이는 상태가 되면), 사용자 에이전트는
그 시점에 해당 MediaDevices
객체에서 장치 변경 알림
단계를 반드시 실행해야 합니다.
이러한 이벤트는 서로 다른 출처의 문서에서
동시에 발생할 가능성이 있습니다. 사용자 에이전트는
교차 출처 활동의
상관관계를 방지하기 위해 이벤트 타이밍에 퍼징을 추가할 수 있습니다.
WebIDL[Exposed=Window, SecureContext]
interface MediaDevices : EventTarget {
attribute EventHandler ondevicechange;
Promise<sequence<MediaDeviceInfo>> enumerateDevices();
};
ondevicechange 유형: EventHandler
이 이벤트 핸들러의 이벤트 유형은 devicechange입니다.
enumerateDevices사용자 에이전트에서 사용할 수 있는 미디어 입력 및 출력 장치에 관한 정보를 수집합니다.
이 메서드는 프로미스를 반환합니다. 열거가 성공하면
프로미스는 이행되며,
사용자 에이전트에서 사용할 수 있는 미디어 입력 및 출력
장치를 나타내는
MediaDeviceInfo 객체의
시퀀스를 제공합니다.
이 시퀀스에서 입력 장치를 나타내는 요소는
MediaDeviceInfo를 확장하는
InputDeviceInfo 유형입니다.
카메라 및 마이크 소스는 열거할 수 있어야 합니다. 추가 소스 유형을 추가하는 명세는 해당 소스 유형을 열거할 수 있어야 하는지에 대한 권고 사항을 제공합니다.
enumerateDevices()
메서드가
호출되면 사용자 에이전트는 다음 단계를 실행해야 합니다:
p를 새로운 프로미스로 합니다.
proceed를 this로 장치 열거를 진행할 수 있음을 확인한 결과로 합니다.
mediaDevices를 this로 합니다.
다음 단계를 병렬로 실행합니다:
proceed가 false인 동안, 사용자 에이전트는
mediaDevices로
장치 열거를
진행할 수 있음의 결과로 proceed를 설정하기 위해
대기열에 넣은 태스크가 proceed를 true로 설정할 때까지
다음 단계로 진행하기 위해 반드시 기다려야 합니다.
resultList를 mediaDevices 및
mediaDevices.[[storedDeviceList]]를
사용하여
장치 정보 객체
목록을 생성한 결과로 합니다.
p를 resultList로 이행합니다.
p를 반환합니다.
mediaDevices와 deviceList가 주어졌을 때 장치 정보 객체 목록을 생성하려면 다음 단계를 실행합니다:
resultList를 빈 목록으로 합니다.
microphoneList, cameraList 및 otherDeviceList를 빈 목록으로 합니다.
document를 mediaDevices의
관련
전역 객체의 연결된
Document로 합니다.
deviceList에서 발견된 각 장치 device에 대해 다음 하위 단계를 실행합니다:
device가 마이크가 아니거나 document가
"microphone"으로 식별되는
기능을
사용할
수 있도록
허용되지 않았다면,
이 하위 단계를 중단하고 다음 장치가 있으면 계속 진행합니다.
deviceInfo를 mediaDevices를 사용하여 device를 나타내는 장치 정보 객체를 생성한 결과로 합니다.
device가 시스템 기본 마이크이면 deviceInfo를 microphoneList의 앞에 추가합니다. 그렇지 않으면 deviceInfo를 microphoneList의 뒤에 추가합니다.
deviceList에서 발견된 각 장치 device에 대해 다음 하위 단계를 실행합니다:
device가 카메라가 아니거나 document가
"camera"로 식별되는 기능을
사용할
수 있도록
허용되지 않았다면,
이 하위 단계를 중단하고 다음 장치가 있으면 계속 진행합니다.
deviceInfo를 mediaDevices를 사용하여 device를 나타내는 장치 정보 객체를 생성한 결과로 합니다.
device가 시스템 기본 카메라이면 deviceInfo를 cameraList의 앞에 추가합니다. 그렇지 않으면 deviceInfo를 cameraList의 뒤에 추가합니다.
mediaDevices에서 마이크 정보를
노출할 수 있음이 false이면,
microphoneList를 첫 번째 항목까지만 남깁니다.
mediaDevices에서 카메라
정보를 노출할 수 있음이
false이면,
cameraList를 첫 번째 항목까지만 남깁니다.
deviceList에서 발견된 각 장치 device에 대해 다음 하위 단계를 실행합니다:
device가 마이크이거나 device가 카메라이면 이 하위 단계를 중단하고 다음 장치가 있으면 계속 진행합니다.
device, microphoneList, cameraList 및
mediaDevices를 입력으로 하여
카메라와
마이크 이외 장치의
노출 결정 알고리즘을 실행합니다.
이 알고리즘의 결과가 false이면
이 하위 단계를 중단하고 다음 장치가 있으면 계속 진행합니다.
deviceInfo를 mediaDevices를 사용하여 device를 나타내는 장치 정보 객체를 생성한 결과로 합니다.
device가 시스템 기본 오디오 출력이면 다음 하위 단계를 실행합니다:
defaultAudioOutputInfo를 mediaDevices를 사용하여 device를 나타내는 장치 정보 객체를 생성한 결과로 합니다.
defaultAudioOutputInfo의 deviceId를
"default"로 설정합니다.
사용자 에이전트는 이것이 시스템 기본 오디오 출력임을
명시하도록 defaultAudioOutputInfo의 label을
업데이트해야 합니다.
defaultAudioOutputInfo를 otherDeviceList의 앞에 추가합니다.
microphoneList의 모든 장치를 순서대로 resultList의 뒤에 추가합니다.
cameraList의 모든 장치를 순서대로 resultList의 뒤에 추가합니다.
otherDeviceList의 모든 장치를 순서대로 resultList의 뒤에 추가합니다.
resultList를 반환합니다.
이 메서드는 미디어 캡처 장치의 가용성을 통해
브라우징 세션과 출처 전반에 걸쳐 지속되는
정보를 반환하므로, 사용자
에이전트가 노출하는 핑거프린팅 표면을 증가시킵니다.![]()
관련
전역 객체의
연결된
Document가 캡처하지 않은 동안에는 이 메서드가
노출하는 정보를 두 비트로 제한합니다. 즉, 카메라가 있는지와
마이크가 있는지 여부입니다. 사용자
에이전트는 예를 들어
관련
전역 객체의 연결된
Document가 합리적이라고 간주되는 제약 조건으로
getUserMedia()를
호출할 때까지 시스템에 카메라와 마이크가 있는 것처럼 가장하여 이를 완화할 수 있습니다.
관련
전역 객체의 연결된
Document가
캡처를 시작한 후에는 모든 미디어 캡처 장치의 목록을 통해
추가적인 지속성 교차 출처 정보를 제공하며,
여기에는 캡처 장치의 그룹화 및 사람이 읽을 수 있는 레이블도 포함되어
핑거프린팅 표면이 더 증가합니다.![]()
사용자 에이전트는 장치 레이블을 정제하여 노출을 제한할 수 있습니다.
예를 들어 레이블에서 발견된 사용자 이름은 제거하되,
장치 제조업체나 모델 정보는 유지할 수 있습니다.
정제된 레이블을 통해 사용자가 해당 장치를 식별할 수 있도록 하는 것이
중요합니다.
위에 설명된 알고리즘은 미디어 장치
정보에 대한 액세스가 관련
전역 객체의 연결된
Document가 캡처했는지 여부에 따라 달라짐을 의미합니다.
카메라 및 마이크 장치의 경우 관련
전역 객체의
연결된
Document가 캡처하지 않았다면
(즉, getUserMedia()가
호출되지 않았거나 성공적으로 이행된 적이 없다면),
MediaDeviceInfo 객체는
kind에는 유효한 값을 포함하지만
deviceId, label 및 groupId에는 빈 문자열을 포함합니다.
또한 enumerateDevices()
결과에는 각 kind당
최대 하나의 장치만 나열됩니다.
그렇지 않으면
MediaDeviceInfo 객체는
deviceId, kind,
label 및 groupId에 의미 있는 값을 포함합니다.
사용 가능한 모든 장치는 enumerateDevices()
결과에 나열됩니다.
mediaDevices가 주어졌을 때 발견된 장치 device를 나타내는 장치 정보 객체를 생성하려면 다음 단계를 실행합니다:
deviceInfo를
device를 나타내는 새로운 MediaDeviceInfo 객체로 합니다.
deviceInfo.kind를
device에 맞게 초기화합니다.
deviceInfo.kind가
"videoinput"과 같고
mediaDevices에서 카메라 정보를
노출할 수 있음이 false이면
deviceInfo를 반환합니다.
deviceInfo.kind가
"audioinput"과 같고
mediaDevices에서 마이크
정보를 노출할 수 있음이 false이면
deviceInfo를 반환합니다.
deviceInfo.label을
device에 맞게 초기화합니다.
device에 대해 저장된 deviceId가 존재하면,
deviceInfo.deviceId를 해당 값으로 초기화합니다.
그렇지 않으면 deviceInfo.deviceId를
deviceId에서 설명한 대로
새로 생성된 고유 식별자로 합니다.
device가 document에 대해 이미 표현된 장치와 동일한 물리적
장치에 속하면, deviceInfo.groupId를
기존 MediaDeviceInfo
객체의
groupId 값으로 초기화합니다.
그렇지 않으면 deviceInfo.groupId를
groupId에서 설명한 대로
새로 생성된 고유 식별자로 합니다.
deviceInfo를 반환합니다.
mediaDevices가 주어졌을 때 장치 열거를 진행할 수 있음 검사를 수행하려면 다음 단계를 실행합니다:
mediaDevices에서
장치 정보를
노출할 수 있음이면 사용자 에이전트는
true를 반환할 수 있습니다.
mediaDevices로 보이는 상태임을 확인한 결과를 반환합니다.
mediaDevices가 주어졌을 때 장치 정보를 노출할 수 있음 검사를 수행하려면 다음 단계를 실행합니다:
mediaDevices에서 카메라 정보를
노출할 수 있음이면
true를 반환합니다.
mediaDevices에서 마이크
정보를 노출할 수 있음이면
true를 반환합니다.
false를 반환합니다.
mediaDevices가 주어졌을 때 카메라 정보를 노출할 수 있음 검사를 수행하려면 다음 단계를 실행합니다:
"videoinput" 종류의 로컬 장치 중 하나라도
mediaDevices의 관련
전역 객체의
연결된
Document에 있는 라이브
MediaStreamTrack에 연결되어 있으면
true를 반환합니다.
mediaDevices.[[canExposeCameraInfo]]를 반환합니다.
mediaDevices가 주어졌을 때 마이크 정보를 노출할 수 있음 검사를 수행하려면 다음 단계를 실행합니다:
"audioinput" 종류의 로컬 장치 중 하나라도
관련
전역 객체의
연결된
Document에 있는 라이브
MediaStreamTrack에 연결되어 있으면
true를 반환합니다.
mediaDevices.[[canExposeMicrophoneInfo]]를
반환합니다.
mediaDevices가 주어졌을 때 보이는 상태임 검사를 수행하려면 다음 단계를 실행합니다:
mediaDevices의 관련
전역 객체의 연결된
Document가
완전히
활성 상태이고 해당 문서의 가시성
상태가
"visible"이면 true를 반환합니다. 그렇지 않으면 false를 반환합니다.
mediaDevices가 주어졌을 때 시스템 포커스를 가짐 검사를 수행하려면 다음 단계를 실행합니다:
mediaDevices의 관련
전역 객체의 탐색 가능
항목의
최상위
순회 가능 항목이
시스템 포커스를 가지면
true를 반환합니다. 그렇지 않으면 false를 반환합니다.
deviceType이 주어졌을 때 장치 노출을 확장할 수 있음 검사를 수행하려면 다음 단계를 실행합니다:
requestedTypes 집합과 불리언 value가 주어졌을 때 mediaDevices에서 장치 정보 노출을 설정하려면 다음 단계를 실행합니다:
"video"가 requestedTypes에 있으면
다음 하위 단계를 실행합니다:
mediaDevices.[[canExposeCameraInfo]]를
value로 설정합니다.
value가 true이고 "microphone"으로
장치 노출을
확장할 수 있음이면,
mediaDevices.[[canExposeMicrophoneInfo]]를
true로 설정합니다.
"audio"가 requestedTypes에 있으면
다음 하위 단계를 실행합니다:
mediaDevices.[[canExposeMicrophoneInfo]]를
value로 설정합니다.
value가 true이고 "camera"로
장치 노출을
확장할 수 있음이면,
mediaDevices.[[canExposeCameraInfo]]를
true로 설정합니다.
카메라와 마이크 이외 장치의 노출 결정 알고리즘은 device, microphoneList, cameraList 및 mediaDevices를 입력으로 받고, device에 관한 정보를 웹 페이지에 노출할지 여부를 결정하는 불리언을 반환합니다.
기본적으로 false를 반환합니다.
다른 명세에서는 특정 장치 유형에 대한 알고리즘을 정의할 수 있습니다.
globalObject에 대해 컨텍스트가 캡처 중임 검사를 수행하려면 다음 단계를 실행합니다:
globalObject가 Window가
아니면
false를 반환합니다.
mediaDevices를 globalObject의 연결된 MediaDevices로 합니다.
mediaDevices.[[mediaStreamTrackSources]]의
각 source에 대해 다음 하위 단계를 실행합니다:
deviceId를 source의 장치의 deviceId로 합니다.
mediaDevices.[[devicesLiveMap]][deviceId]가
true이면 true를 반환합니다.
false를 반환합니다.
이 알고리즘은 마이크, 카메라 및 디스플레이를 포함한 모든 캡처 트랙을 다룹니다.
WebIDL[Exposed=Window, SecureContext]
interface MediaDeviceInfo {
readonly attribute DOMString deviceId;
readonly attribute MediaDeviceKind kind;
readonly attribute DOMString label;
readonly attribute DOMString groupId;
[Default] object toJSON();
};
deviceId
유형: DOMString,
읽기 전용표현된 장치의 식별자입니다. 장치는 해당 식별자와
kind에 의해
반드시 고유하게 식별되어야 합니다.
저장된 식별자를 인식할 수 있도록 하기 위해, 식별자는
최상위
순회 가능 항목의 동일
출처 Document들에서 반드시 동일해야 합니다.
자식
탐색 가능 항목에서는,
문서 간 식별자가 동일한지 여부에 대한 결정이 사이트 간 상관관계 완화 조치를
방해하지 않도록, 존재하는 경우 저장소(예:
localStorage)에
대한
사용자
에이전트의 파티셔닝 규칙을 반드시 따라야 합니다.
식별자가 사용자를 고유하게 식별할 수 있다면, 해당 식별자를
서로 다른 출처에서 동일한 사용자의 상관관계를 파악하는 데 사용하지 못하도록
다른 출처의 문서에서 추측할 수 없도록 반드시 해야 합니다.
식별자가 사용자에 연결되어 있지 않고 User-Agent 문자열과 같은 다른 수단으로
추측할 수 있다면 출처 간에 재사용할 수 있습니다.
이 출처의 페이지에서 어떤 로컬 장치라도 라이브
MediaStreamTrack에 연결되었거나,
이 출처에 로컬 장치에 접근하기 위한 저장된 권한이
부여되었다면, 아래에 자세히 설명된 경우를 제외하고 이 식별자는
반드시 지속되어야 합니다. 고유하고 안정적인 식별자를 통해 애플리케이션은
여러 번의 방문에 걸쳐 특정 소스를 저장하고, 가용성을 확인하고,
직접 요청할 수 있습니다.
그러나 이 출처의 페이지에서 어떤 로컬 장치도 라이브 MediaStreamTrack에 연결되지 않았고, 이 출처에 로컬 장치에 접근하기 위한 저장된 권한도 부여되지 않은 동안에는 사용자 에이전트가 이 출처의 마지막 브라우징 세션이 닫힌 후 이 식별자를 지울 수 있습니다. 사용자 에이전트가 이 조건에서 식별자를 지우지 않기로 선택한다면, 쿠키와 마찬가지로 사용자가 식별자를 시각적으로 확인하고 삭제할 수 있도록 반드시 해야 합니다.
deviceId는 브라우징 세션 간에
지속될 수 있고
핑거프린팅 메커니즘으로 사용될 가능성을 줄이기 위해,
deviceId는
쿠키 [COOKIES]와 같은 다른 지속성 저장소 메커니즘처럼 취급해야 합니다.
즉, 사용자 에이전트는 쿠키 사용이 차단된 사이트에 대해 장치
식별자를 지속해서는 안 되며,
다른 지속성 저장소가 지워질 때 출처별 장치 식별자를
사용자 에이전트가 반드시 교체해야
합니다.
kind
유형: MediaDeviceKind,
읽기 전용표현된 장치의 종류입니다.
label 유형: DOMString,
읽기 전용이 장치를 설명하는 레이블입니다(예: "외장 USB 웹캠"). 이 레이블은 최종 사용자가 장치를 서로 구분할 수 있도록 하기 위한 것입니다. 애플리케이션은 레이블에 장치 유형이나 모델과 같은 특정 정보가 포함되어 있다고 가정할 수 없습니다. 장치에 연결된 레이블이 없다면 이 속성은 빈 문자열을 반드시 반환해야 합니다.
groupId
유형: DOMString,
읽기 전용표현된 장치의 그룹 식별자입니다. 두 장치가 동일한 물리적 장치에 속하면 동일한 그룹 식별자를 가집니다. 예를 들어 동일한 헤드셋의 스피커와 마이크를 나타내는 오디오 입력 및 출력 장치는 동일한 groupId를 가집니다.
그룹 식별자는 각 문서에 대해 반드시 고유하게 생성되어야 합니다.
toJSONWebIDLenum MediaDeviceKind {
"audioinput",
"audiooutput",
"videoinput"
};
MediaDeviceKind 열거형
설명 |
|
|---|---|
audioinput |
오디오 입력 장치를 나타냅니다. 예를 들어 마이크입니다. |
audiooutput |
오디오 출력 장치를 나타냅니다. 예를 들어 헤드폰입니다. |
videoinput |
비디오 입력 장치를 나타냅니다. 예를 들어 웹캠입니다. |
InputDeviceInfo 인터페이스는
해당 인터페이스가 나타내는 입력 장치의 기능에 액세스할 수 있게 합니다.
WebIDL[Exposed=Window, SecureContext]
interface InputDeviceInfo : MediaDeviceInfo {
MediaTrackCapabilities getCapabilities();
};
getCapabilities사용자가 제공한 제약 조건이 없는 경우,
장치의 MediaStream의
기본 오디오 또는 비디오 트랙을
(해당 kind 값에 따라)
설명하는 MediaTrackCapabilities
객체를 반환합니다.
이러한 기능은 id가 이
MediaDeviceInfo의
deviceId 속성 값인
getUserMedia({deviceId: id})가 반환한
MediaStream에서
이 유형의 첫 번째
MediaStreamTrack에
getCapabilities()를
호출하여 얻을 수 있는 기능과 반드시 동일해야 합니다.
어떤 로컬 장치에도 액세스가 허용되지 않았고 이
InputDeviceInfo가
고유 식별 정보와 관련하여 필터링된 경우(위의
enumerateDevices()
결과 설명 참조), 이 메서드는
빈 딕셔너리를 반환합니다.
devicechange
이벤트는 DeviceChangeEvent
인터페이스를 사용합니다.
WebIDL[Exposed=Window]
interface DeviceChangeEvent : Event {
constructor(DOMString type, optional DeviceChangeEventInit eventInitDict = {});
[SameObject] readonly attribute FrozenArray<MediaDeviceInfo> devices;
[SameObject] readonly attribute FrozenArray<MediaDeviceInfo> userInsertedDevices;
};
devices 유형: FrozenArray<MediaDeviceInfo>,
읽기 전용
devices 속성은
현재 사용 가능한 장치 목록을 나타내는 MediaDeviceInfo
객체의 배열을 반환합니다.
userInsertedDevices 유형: FrozenArray<MediaDeviceInfo>,
읽기 전용
userInsertedDevices
속성은
devices의
MediaDeviceInfo 객체 중
사용자가 최근 물리적으로 삽입하거나 활성화했고
그 결과 이 이벤트를 통해 새로 노출된 객체만 포함하는 배열을 반환합니다.
그렇지 않으면 빈 목록을 반환합니다.
사용자 에이전트는
getUserMedia()가
호출되기 전에 사용자가 삽입하거나 활성화한 장치도,
이 이벤트가 해당 장치의 첫 번째 노출을 표시하고 사용자가
getUserMedia()에서
장치를 선택하지 않았다면 포함할 수 있습니다.
MediaDeviceInfo 객체가
존재한다면 devices에도 반드시
존재해야 합니다.
사용자가 호출 중(또는 호출 직전)에 장치를 삽입하는 것은 해당 장치를 즉시 사용하고자 한다는 강한 신호일 수 있습니다.
애플리케이션은 이 속성을 활용하여 이러한 신호를
장치 정보 노출의 변경으로 인해 발생할 수 있는
devices의
차이와 구분할 것을 권장합니다.
WebIDLdictionary DeviceChangeEventInit : EventInit {
sequence<MediaDeviceInfo> devices = [];
};
devices 유형: sequence<MediaDeviceInfo>,
기본값: []
devices 멤버는
사용 가능한 장치를 나타내는 MediaDeviceInfo 객체의
배열입니다.
이 절에서는 Navigator 및
MediaDevices를 확장하여 사용자 에이전트에서 사용할 수 있는
미디어 입력 장치에 액세스할 권한을 요청하는 API를 제공합니다.
또는 로컬 MediaStream을 비디오 요소와 같은
특정 유형의 DOM 요소에서 캡처할 수 있습니다
[mediacapture-fromelement]. 이는
자동화된 테스트에 유용할 수 있습니다.
MediaDevices 인터페이스 확장getUserMedia() 정의는
수개월 동안 Navigator에서
존재해 온 메서드 정의와 비교하여 두 가지 주요
변경 사항을 반영합니다.
첫째, getUserMedia()
메서드의 공식 정의이자
개발자에게 사용이 권장되는 정의는 이제
MediaDevices 아래에
정의된 이 메서드입니다. 이 결정은
이전 버전과의 호환성을 위해 원래 API가 Navigator.getUserMedia로
Navigator
객체 아래에 계속 제공되는 한 합의된 사항을 반영합니다. 작업 그룹은 이 API의 초기 사용자들이
널리 사용되는 사용자 에이전트에서 getUserMedia()의 공식 구현 전후 모두에서
코드가 동작하도록 getUserMedia를 "var getUserMedia =
navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;"로 정의하도록 권장받아 왔음을 인정합니다. 기능적으로 동등하도록 하기 위해
Navigator
아래의 getUserMedia()
메서드는 여기의 메서드를 기준으로 정의됩니다.
둘째, 여기에서 정의된 메서드는 프로미스 기반인 반면,
Navigator
아래에 정의된 메서드는 현재 여전히 콜백 기반입니다.
Navigator 아래에서 getUserMedia() 정의를 찾으려는 개발자는
그곳에 제공된 자세한 참고 사항을 읽을 것을 강력히 권장합니다.
getSupportedConstraints
메서드는 애플리케이션이
사용자 에이전트가
인식하는 제약 조건을 확인할 수 있도록 제공됩니다. 애플리케이션은
필수 제약 조건을 안정적으로 사용하거나
고급 제약 조건의 조합 논리에서 예측 가능한 결과를 얻기 위해
이 정보가 필요할 수 있습니다.
WebIDLpartial interface MediaDevices {
MediaTrackSupportedConstraints getSupportedConstraints();
Promise<MediaStream> getUserMedia(optional MediaStreamConstraints constraints = {});
};
getSupportedConstraints사용자 에이전트가 알고 있는 제약 가능한 속성을 멤버로 갖는 딕셔너리를 반환합니다. 지원되는 제약 가능한 속성은 반드시 표현되어야 하며, 사용자 에이전트가 지원하지 않는 제약 가능한 속성은 반환되는 딕셔너리에 포함되어서는 안 됩니다. 반환되는 값은 사용자 에이전트가 구현하는 항목을 나타내며 브라우징 세션 중에는 변경되지 않습니다.
사용자에게 웹캠 또는 기타 비디오나 오디오 입력을 사용할 권한을 요청합니다.
constraints 인수는
MediaStreamConstraints
유형의 딕셔너리입니다.
이 메서드는 프로미스를 반환합니다. 사용자가 아래에 설명된 유효한 트랙을 승인하면
프로미스는 적절한 MediaStream
객체로
이행됩니다.
아래에 설명된 대로 유효한 트랙을 찾지 못하거나 사용자가 권한을 거부하면 프로미스는 거부됩니다.
getUserMedia() 메서드가
호출되면 사용자 에이전트는 다음 단계를 반드시
실행해야 합니다:
constraints를 메서드의 첫 번째 인수로 합니다.
requestedMediaTypes를 constraints에서
딕셔너리 값 또는 true 값을 가진 미디어
유형의 집합으로 합니다.
requestedMediaTypes가 빈 집합이면
TypeError로
거부된
프로미스를 반환합니다.
WebIDL 규칙 때문에 WebIDL에는
"optional"이라는 단어가 나타나지만, 호출이 성공하려면
인수를 반드시 제공해야 합니다.
document를 관련
전역 객체의
연결된
Document로 합니다.
document가
완전히
활성 상태가 아니면, name
속성 값이 "InvalidStateError"인
DOMException
객체로 거부된 프로미스를 반환합니다.
requestedMediaTypes에 "audio"가 포함되어 있고 document가 "microphone" 권한 이름으로 식별되는 기능을 사용하도록 허용되지 않은 경우, 아래의 권한 실패라고 표시된 단계로 이동합니다.
requestedMediaTypes에 "video"가 포함되어 있고 document가 "camera" 권한 이름으로 식별되는 기능을 사용하도록 허용되지 않은 경우, 아래의 권한 실패라고 표시된 단계로 이동합니다.
mediaDevices를 this로 합니다.
isInView를 보이는 상태임 알고리즘의 결과로 합니다.
p를 새 프로미스로 합니다.
다음 단계를 병렬로 실행합니다:
isInView가 false인 동안, 사용자 에이전트는
보이는 상태임
알고리즘의 결과로 isInView를 설정하도록 대기열에 넣은
태스크가 isInView를 true로 설정할 때까지
다음 단계로 진행하기 위해 반드시 기다려야 합니다.
finalSet을 (초기에는) 빈 집합으로 합니다.
requestedMediaTypes의 각 미디어 유형 kind에 대해 다음 단계를 실행합니다:
kind 유형 미디어의 가능한 각 소스 장치의
가능한 각 구성에 대해, 소스 장치를 보유하고 특정 설정으로 구성된
설정
딕셔너리를 가진 최종
MediaStreamTrack을
대신하는 자리표시자로 후보를 구상합니다.
이 후보 집합을 candidateSet이라고 합니다.
candidateSet이 빈 집합이면 아래의 NotFound 실패라고 표시된 단계로 이동합니다.
true이면 CS를 빈 제약 조건 집합(제약 조건 없음)으로
설정합니다. 그렇지 않으면
CS를 constraints의
kind 항목 값으로 설정한 상태로 계속합니다.
MediaStreamTrack
객체에 대해 정의되지 않은 모든 제약 가능한 속성을 제거합니다.
즉 "video" 내부의 오디오 전용 제약
조건과
"audio" 내부의 비디오 전용
제약 조건은 OverconstrainedError를 발생시키는 대신
단순히 무시됩니다.
CS에
필수
제약 조건인 멤버가 포함되어 있고, 그 이름이
장치
선택에 허용되는
필수 제약 조건 목록에 없다면,
p를 TypeError로
거부하고
이 단계를 중단합니다.
candidateSet의 각 후보에 대해 CS를
제약 조건 집합으로 하여
SelectSettings
알고리즘을 실행합니다. 알고리즘이
undefined를 반환하면 해당 후보를
candidateSet에서 제거합니다. 이는
제약 조건을 충족하는 설정 딕셔너리가 적어도 하나 존재하는지
확인하여 제약 조건을 충족할 수 없는 장치를 제거합니다.
candidateSet이 빈 집합이면
failedConstraint를
SelectSettings
알고리즘을 실행하는 동안 검사한 모든 설정 딕셔너리에서
적합도 거리가 무한대였던 임의의
필수
제약 조건으로 하거나,
그러한 것이 없다면 ""로 하고,
아래의 제약 조건 실패라고 표시된 단계로 이동합니다.
이 오류는 사용자가 어떤 장치에도
권한을 부여하기 전에 기반 장치가 무엇을 생성할 수 없는지에 관한
정보를 제공하므로 핑거프린팅 표면으로
사용될 수 있습니다.![]()
현재 Document에서
라이브 MediaStreamTrack에
연결되어 있지 않은 candidateSet의 모든 후보 장치에 대해
현재 권한
상태를 읽습니다.
장치의 권한 상태가 "denied"인
모든 후보를 candidateSet에서 제거합니다.
candidateSet이 이제 비어 있다면,
이는 이 유형의 모든 장치가
"denied"
상태임을 나타내므로 아래의
PermissionFailure라고 표시된 단계로 이동합니다.
선택적으로, 예를 들어 이전에 설정된 사용자 기본 설정, 보안상의 이유 또는 플랫폼 제한에 따라 아래의 권한 실패라고 표시된 단계로 이동합니다.
candidateSet의 모든 후보를 finalSet에 추가합니다.
stream을 새롭고 비어 있는
MediaStream 객체로
합니다.
requestedMediaTypes의 각 미디어 유형 kind에 대해, 가급적 동시에 다음 하위 단계를 실행합니다:
사용자 에이전트는 서로 다른 종류의 미디어에 대한 동시 요청을 하나의 사용자 대상 권한 프롬프트로 묶을 것을 권장합니다.
PermissionDescriptor의
name
멤버를 kind와 연결된 권한 이름으로 설정하여
사용
권한을
요청합니다
(예: "video"의 경우 "camera",
"audio"의 경우 "microphone").
이때 현재 Document의
라이브 및 동일
권한
MediaStreamTrack에
연결된 모든 장치는 권한 상태가 "granted"인
것으로
간주하여, 제공된 미디어 집합을 얻습니다.
이 문맥에서 동일 권한은
현재 요청되는 것과 동일한 수준의
권한을 획득하는 데 필요했던 MediaStreamTrack을
의미합니다(예: 격리된 것이 아님).
사용자의 권한을 요청할 때 사용자 에이전트는 권한이 선택된 장치에만 부여되는지 아니면 해당 kind의 모든 장치에 부여되는지를 반드시 공개해야 합니다.
사용자가 응답하지 않으면 이 알고리즘은 이 단계에서 멈춥니다.
요청 결과가 "denied"이면,
아래의 권한 실패라고 표시된 단계로 이동합니다.
hasSystemFocus를 false로 합니다.
hasSystemFocus가 false인 동안,
사용자 에이전트는
시스템 포커스를
가짐
알고리즘의 결과로 hasSystemFocus를 설정하도록
대기열에 넣은 태스크가 hasSystemFocus를
true로 설정할 때까지 다음 단계로 진행하기 위해
반드시 기다려야 합니다.
requestedMediaTypes 및 true를 사용하여
mediaDevices에서 장치 정보
노출을 설정합니다.
requestedMediaTypes의 각 미디어 유형 kind에 대해 다음 하위 단계를 실행합니다:
finalCandidate를 제공된 미디어로 합니다. 이는 finalSet에서 kind 유형의 정확히 하나의 후보여야 합니다. finalSet에서 어떤 후보를 선택할지는 전적으로 사용자 에이전트에 달려 있으며 사용자에게 물어 결정할 수도 있습니다.
사용자 에이전트는 SelectSettings 알고리즘에서 계산한 적합도 거리 값을 선택 알고리즘의 입력으로 사용해야 합니다. 하지만 사용자 기본 설정과 같이 장치에 관한 내부적으로 이용 가능한 다른 정보를 사용할 수도 있습니다.
이는 필수 제약 조건이 아닌 값은 보장되지 않음을 의미합니다.
사용자 에이전트는 가능한 경우 kind에 대해 사용자의 기본 장치 또는 시스템 기본 장치를 기본값으로 사용할 것을 권장합니다. 사용자 에이전트는 미리 녹화된 미디어 파일을 포함한 모든 미디어 소스를 사용자가 사용하도록 허용할 수 있습니다.
요청 결과는 "granted"입니다.
OS/프로그램/웹페이지 잠금과 같은 하드웨어 오류로 액세스할 수 없으면
해당 후보를 finalSet에서 제거합니다.
finalSet에 kind 유형의 후보가 없으면
name
속성 값이
"NotReadableError"인
새 DOMException
객체로 p를
거부하고
이 단계를 중단합니다.
그렇지 않으면 업데이트된 finalSet으로 이 하위 단계를 다시 시작합니다.
위에 나열된 이유 이외의 이유로 장치 액세스에 실패하면
해당 후보를 finalSet에서 제거합니다.
finalSet에 kind 유형의 후보가 없으면
name
속성 값이 "AbortError"인
새 DOMException
객체로 p를
거부하고
이 단계를 중단합니다.
그렇지 않으면 업데이트된 finalSet으로 이 하위 단계를 다시 시작합니다.
grantedDevice를 finalCandidate의 소스 장치로 합니다.
grantedDevice의 deviceId인 deviceId를 사용하여,
mediaDevices.[[devicesLiveMap]][deviceId]가
아직 true가 아니라면
true로 설정하고,
mediaDevices.[[devicesAccessibleMap]][deviceId]가
아직 true가 아니라면
true로 설정합니다.
track을
grantedDevice와 mediaDevices로
MediaStreamTrack을
생성한 결과로 합니다.
MediaStreamTrack의
소스는 변경되어서는 안 됩니다.
track을 stream의 트랙 집합에 추가합니다.
stream의 모든 트랙에 적절한
제약 조건을 사용하여 ApplyConstraints
알고리즘을 실행합니다.
그중 하나라도 undefined 이외의 값을 반환하면
failedConstraint를 그 결과로 하고 아래의
제약 조건 실패라고 표시된 단계로 이동합니다.
stream의 각 track에 대해,
track.[[Source]] 및
mediaDevices를 사용하여 트랙 소스를
MediaDevices에 연결합니다.
p를 stream으로 이행하고 이 단계를 중단합니다.
NotFound 실패:
requestedMediaTypes가 주어졌을 때
getUserMedia
특정 실패가 허용됨이
false를 반환하면, 아래의
권한 실패라고 표시된 단계로 이동합니다.
name
속성 값이 "NotFoundError"인
새 DOMException
객체로 p를
거부합니다.
제약 조건 실패:
requestedMediaTypes가 주어졌을 때
getUserMedia
특정 실패가 허용됨이
false를 반환하면, 아래의
권한 실패라고 표시된 단계로 이동합니다.
message를
undefined 또는 유용한
사람이 읽을 수 있는 메시지로 하고,
장치
정보를 노출할 수 있음이
true이면 constraint를
failedConstraint로 하고, 그렇지 않으면 ""로 합니다.
OverconstrainedError(constraint,
message)를 호출하여 생성한
새 OverconstrainedError로
p를 거부합니다.
권한 실패: name
속성 값이
"NotAllowedError"인
새 DOMException
객체로 p를 거부합니다.
p를 반환합니다.
requestedMediaTypes가 주어졌을 때 getUserMedia 특정 실패가 허용되는지 확인하려면 다음 단계를 실행합니다:
위 알고리즘에서는 제약 조건을 두 번 확인합니다. 한 번은 장치 선택 시이고, 한 번은 액세스 승인 후입니다. 두 검사 사이에 시간이 지났을 수 있으므로 선택한 장치가 더 이상 적합하지 않을 가능성이 있습니다. 이 경우 NotReadableError가 발생합니다.
장치 선택에 허용되는 필수 제약 조건에는 다음 제약 조건 이름이 포함됩니다: width, height, aspectRatio, frameRate, facingMode, resizeMode, sampleRate, sampleSize, echoCancellation, autoGainControl, noiseSuppression, latency, channelCount, deviceId, groupId.
MediaStreamConstraints 딕셔너리는
사용자 에이전트에게 getUserMedia()가
반환하는 MediaStream에 어떤 종류의
MediaStreamTrack을 포함할지 지시하는 데 사용됩니다.
WebIDLdictionary MediaStreamConstraints {
(boolean or MediaTrackConstraints) video = false;
(boolean or MediaTrackConstraints) audio = false;
};
MediaStreamConstraints
멤버video 유형:
(boolean
or MediaTrackConstraints),
기본값: false
true이면 반환되는
MediaStream에 비디오 트랙이 포함되도록 요청합니다.
Constraints
구조가 제공되면 비디오 트랙의 특성과
설정을 추가로 지정합니다. false이면
MediaStream은
비디오 트랙을 포함해서는 안 됩니다.
audio 유형:
(boolean
or MediaTrackConstraints),
기본값: false
true이면 반환되는
MediaStream에 오디오 트랙이 포함되도록 요청합니다.
Constraints 구조가 제공되면
오디오 트랙의 특성과 설정을 추가로 지정합니다.
false이면 MediaStream은
오디오 트랙을 포함해서는 안 됩니다.
이 절은 비규범적입니다.
이 절의 getUserMedia() 정의는 원래 제안된 호출 형식을 반영하며, 이전 버전과의 호환성을 유지하고자 하는 브라우저를 위해서만 여기에 문서화되어 있습니다. 권장 인터페이스와 두 가지 중요한 점에서 다릅니다.
첫째, getUserMedia() 메서드의 공식 정의이자
개발자에게 사용이 권장되는 정의는 이제 MediaDevices에 있습니다. 이
결정은
이전 버전과의 호환성을 위해 원래 API가 여기의 Navigator 객체 아래에서
계속 제공되는 한 합의된 사항을 반영합니다. 작업 그룹은 이러한 API의
초기 사용자들이 널리 사용되는 브라우저에서 getUserMedia()의 공식 구현 전후 모두
코드가 동작하도록 getUserMedia를 "var getUserMedia =
navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;"로 정의하도록 권장받아 왔음을 인정합니다.
기능적으로 동등하도록 하기 위해 여기의 getUserMedia()
메서드는 MediaDevices 아래의 메서드를 기준으로 정의됩니다.
둘째, 명세의 다른 모든 콜백 기반 메서드를 프로미스 기반으로 변경하기로 한 결정에 따라 navigator.getUserMedia() 정의 역시 navigator.mediaDevices.getUserMedia() 사용에서 이를 반영해야 했습니다. navigator.getUserMedia()는 이제 명세에 남은 유일한 콜백 기반 메서드이므로, a) 이것이 여전히 명세에 속해야 하는지, b) 속한다면 구문이 콜백 기반으로 유지되어야 하는지 아니면 프로미스를 사용하도록 어떤 방식으로 변경되어야 하는지에 관한 논의가 계속되고 있습니다. 이러한 질문에 대한 의견, 특히 현재 이 기능의 구현을 적극적으로 사용하는 개발자의 의견을 권장합니다.
콜백 기반 구문에서 프로미스 기반 구문으로 변경된 다른 메서드는 어떤 형태로든 레거시 사용을 고려해야 할 만큼 널리 구현되지 않았다고 판단되었다는 점에 유의하십시오.
구현이 적합한 것으로 간주되기 위해 이 인터페이스를 구현할 필요는 없습니다.
WebIDL
getUserMedia사용자에게 웹캠 또는 기타 비디오나 오디오 입력을 사용할 권한을 요청합니다.
constraints 인수는
MediaStreamConstraints
유형의 딕셔너리입니다.
사용자가
MediaDevices의
getUserMedia()에
설명된 유효한 트랙을 승인하면,
successCallback은 적절한
MediaStream
객체를 인수로 하여 호출됩니다.
MediaDevices의
getUserMedia()에
설명된 대로 유효한 트랙을 찾는 데 실패하거나 사용자가 권한을 거부하면
errorCallback이 호출됩니다.
getUserMedia()
메서드가 호출되면,
사용자 에이전트는 다음 단계를 반드시 실행해야 합니다:
constraints를 메서드의 첫 번째 인수로 합니다.
successCallback을 메서드의 두 번째 인수가 나타내는 콜백으로 합니다.
errorCallback을 메서드의 세 번째 인수가 나타내는 콜백으로 합니다.
constraints를 인수로 하여 getUserMedia() 알고리즘에 지정된 단계를 실행하고, p를 그 결과 프로미스로 합니다.
p가 값 stream으로 이행되면 다음 단계를 실행합니다:
stream을 인수로 하여 successCallback을 호출합니다.
p가 이유 r로 거부되면 다음 단계를 실행합니다:
r을 인수로 하여 errorCallback을 호출합니다.
이 절은 비규범적입니다.
사용자 에이전트는 특정
getUserMedia() 호출이
성공할 것이라고 판단한 경우 리소스를 예약할 것을 권장합니다.
반환된 프로미스를 이행하기 전에 리소스를 예약하는 것이 바람직합니다.
이후의 getUserMedia() 호출은
(이 페이지든 다른 페이지든) 이전에 할당된 리소스와
다른 애플리케이션이 보유한 리소스를 사용 중인 것으로 간주해야 합니다.
사용 중으로 표시된 리소스는 사용자가 지정하지 않는 한
현재 웹 페이지의 소스로 제공되어서는 안 됩니다. 선택적으로
사용자 에이전트는 사용 중인 소스에서 제공되는 스트림을
제공하도록 선택할 수 있지만, 해당 소스를 사용 중 상태로 유지하는 원래
스트림의 소유자와 출처가 일치하는 페이지에만 제공할 수 있습니다.
이 문서에서는 권한 부여 대화 상자 또는 장치 선택 인터페이스(있는 경우)에서 사용자가 페이지가 요청한 스트림의 소스로 사용 가능한 모든 하드웨어를 선택할 수 있도록 할 것을 권장합니다(리소스가 지정된 필수 제약 조건을 충족할 수 있는 경우). 모범 사례로 특별히 권장하는 것은 아니지만, 일부 사용자 에이전트는 비디오 또는 오디오 소스를 로컬 파일 및 기타 미디어로 대체하는 기능을 지원할 수 있습니다. 이 기능을 사용자에게 제공하기 위해 파일 선택기를 사용할 수 있습니다.
또한 이 문서에서는 사용자가 이전 getUserMedia() 호출 (이 페이지 또는 여전히 살아 있는 다른 페이지)에 의해 현재 사용 중인 모든 리소스를 볼 수 있도록 하고, 해당 스트림을 종료하여 그 대신 현재 페이지가 리소스를 사용할 수 있게 할 것을 권장합니다. 현재 운영 환경에서 가능하다면 다른 애플리케이션이 현재 보유한 리소스도 동일한 방식으로 표시하고 처리할 것을 제안합니다. 사용자가 이 옵션을 선택하면 영향을 받은 스트림의 페이지에 제공되었던 리소스에 해당하는 트랙을 제거해야 합니다.
장치에 대한 권한이 요청되면 사용자 에이전트는 동일한 출처에서 나중에 사용할 수 있도록 이 권한을 저장하여 사용자가 나중에 다시 권한을 부여할 필요가 없도록 할 수 있습니다. 각 장치별로, 특정 클래스의 모든 장치에 대해, 또는 모든 장치에 대해 권한을 저장하는 기능을 제공할지는 사용자 에이전트가 선택합니다. 선택 사항은 사용자에게 명확해야 하며, 저장하려는 권한의 전체 집합에 대해 권한이 부여되어 있어야 합니다. 예를 들어 모든 카메라를 사용할 권한을 저장하려면 사용자는 하나의 카메라만이 아니라 모든 카메라를 사용할 권한을 부여했어야 합니다.
설명된 바와 같이 이 명세는 권한 부여로 저장된 권한이 생성되는지 여부를 규정하지 않습니다. 권한이 저장되지 않는 경우 해당 장치에서 제공되는 모든 MediaStreamTrack이 중지될 때까지만 권한이 유지됩니다.
MediaStream에는 둘 이상의
비디오 및 오디오 트랙이 포함될 수 있습니다. 예를 들어 하나의 스트림 객체에 두 개
이상의 웹캠 비디오를 포함할 수 있습니다. 하지만
현재 API에서는 페이지가 독립된 소스에서 여러 비디오
스트림이 필요함을 표현할 수 없습니다.
페이지가 여러 개의 독립된 비디오 및/또는 오디오 스트림을 요청할 수 있는 방법으로 동일한 페이지에서 getUserMedia()를 여러 번 호출하는 것을 허용할 것을 권장합니다.
또한 페이지에서 여러 번의 getUserMedia() 호출을 수행하는 경우, 리소스를 요청하는 순서와 완료되는 순서는 이 명세에서 제한하지 않는다는 점에 유의하십시오.
한 번의 getUserMedia() 호출은 항상 0개 또는 1개의 오디오 트랙과 0개 또는 1개의 비디오 트랙을 가진 스트림을 반환합니다. 스크립트가 안정된 상태에 도달하기 전에 getUserMedia()를 여러 번 호출하는 경우, 이 문서는 UI 설계자에게 권한 대화 상자를 병합하여 사용자가 한 번의 대화 상자 상호작용으로 여러 카메라 및/또는 미디어 소스의 사용 권한을 부여할 수 있도록 할 것을 권고합니다. 각 getUserMedia 호출의 제약 조건을 사용하여 어떤 스트림이 어떤 미디어 소스를 받는지 결정할 수 있습니다.
deviceId를 생성하는 효율적인 방법은
개인 키 + (사용자
에이전트의 파티셔닝 규칙에 따라 출처 또는 출처 + 최상위 출처) + salt + 드라이버에 있는 장치의 기반
(하드웨어) id에서 암호학적 해시를 생성하고, 그 결과 해시를 영숫자 문자열로
표시하는 것입니다. 충돌 위험을 피하기 위해 해시에 32비트 이하를 사용하는 것이
권장되지만, 너무 낮은 비트 수는 권장되지 않습니다.
저장 공간을 대가로 하는 더 낮은 엔트로피의 대안은 사용자 에이전트의 파티셔닝 규칙에 따라 각 출처 또는 출처 + 최상위 출처에서 새로 발견되는 각 장치에 0에서 255까지의 숫자를 무작위로 할당하고, 숫자가 부족하면 가장 오랫동안 나타나지 않은 숫자를 폐기하는 것입니다.
카메라 또는 마이크에서 제공되는 트랙은 사용자의 개인정보 보호를 관리하기 위해 언제든지 사용자 에이전트에 의해 강제로 음소거될 수 있습니다. 하지만 이렇게 하면 웹 호환성 문제가 발생할 수 있을 뿐 아니라 사용자 활동에 관한 정보가 유출될 수 있으므로 주의가 필요합니다.
다음의 경우에는 카메라 또는 마이크 트랙을 음소거하는 것이 모범 사례입니다:
사용자 에이전트가 이미 전역적으로 미디어 재생을 일시 중단하지만 JavaScript는 일시 중단되지 않는 OS 수준 이벤트입니다. 그 근거는 사용자가 의도적으로 그렇게 구성하지 않은 한 이러한 상황에서도 캡처가 계속된다면 사용자가 놀랄 수 있기 때문입니다. OS 수준 이벤트로 인해 이미 트랙에서 프레임 유입이 중단된다면 이로 인해 사용자 활동에 관한 새로운 정보가 노출되지 않습니다. 그렇지 않은 경우에도 캡처가 종료된다는 사실을 노출하는 것은 사용자를 놀라게 할 수 있는 상황에서 캡처를 계속하는 것과 비교하면 합리적인 개인정보 보호 절충으로 보입니다.
보이는 상태가 아닌 웹 페이지가 해당 소스의 모든 트랙이 비활성화된 상태에서 트랙을 다시 활성화하는 경우입니다. 이는 페이지가 보이는 상태가 될 때까지 캡처 재개를 지연하기 위한 것입니다.
이전에 음소거한 카메라 또는 마이크 트랙을 다음의 경우 음소거 해제하는 것이 모범 사례입니다:
사용자 에이전트가 이미 전역적으로 미디어 재생을 재개하는 OS 수준 이벤트이고, 그리고 페이지가 사용자에게 보이는 경우입니다(예: 잠금 화면 상태가 아닌 경우). 사용자 에이전트는 이전 캡처 세션에 대한 사용자의 인식을 저해할 정도로 상당한 시간이 지났다고 판단하면 이러한 동작을 연기할 수 있습니다.
웹 페이지가 보이는 상태가 되고 동시에 음소거되어 있는 하나 이상의 활성화된 트랙을 가지고 있는 경우입니다.
제약 가능 패턴을 통해 애플리케이션은 이를 구현하는 객체(제약 가능한
객체)의 속성을 검사하고 조정할 수 있습니다. 다른 명세에서
참조할 수 있도록 별도의 정의 집합으로 분리되어 있습니다. 핵심 개념은
기능이며, 이는 객체의 제약 가능한 속성과 해당 속성의
가능한 값 집합으로 구성되고, 범위 또는
열거형으로 지정할 수 있습니다. 예를 들어 카메라는 초당 20~50프레임(범위)의
프레임 속도(속성)를 지원할 수 있으며, 사용자를 향하거나, 사용자 반대쪽을 향하거나,
사용자의 왼쪽 또는 오른쪽을 향하도록 위치를 지정할 수
있습니다(열거형 집합). 애플리케이션은
getCapabilities() 접근자를 통해 제약 가능한 속성이 지원하는 기능을
검사할 수 있습니다.
애플리케이션은 기본 및/또는 고급 ConstraintSet과
applyConstraints() 메서드를 통해 객체의 기능에 원하는
값(범위)을 선택할 수 있습니다. ConstraintSet은 객체의 하나 이상의
속성 이름과 각 속성에 대해 원하는 값(또는
원하는 값의 범위)으로 구성됩니다. 이러한 각 속성/값
쌍은 개별 제약 조건으로 간주할 수 있습니다. 예를 들어
애플리케이션은 두 개의 제약 조건을 포함하는 ConstraintSet을 설정할 수 있는데,
첫 번째는 카메라의 프레임 속도가 초당 30~40프레임
사이여야 한다고 지정하고(범위), 두 번째는 카메라가 사용자를 향해야
한다고 지정할 수 있습니다(특정 값). 개별 제약 조건이 상호작용하는 방식은
추가 'advanced' 속성이 있는 ConstraintSet인 기본 Constraint 구조에서
제약 조건이 제공되는지와 그 방식, 또는 고급 목록의 ConstraintSet에
들어 있는지에 따라 달라집니다. 동작은 다음과 같습니다. 기본 Constraint 구조의
모든 'min', 'max' 및 'exact' 제약 조건은 함께
필수 제약 조건으로 취급되며, 표시된 속성 이름에 대해
이러한 모든 개별 제약 조건을 동시에 충족할 수 없다면
사용자 에이전트는 반환된 프로미스를 거부해야 합니다.
그렇지 않으면 필수 제약 조건을 적용해야 합니다. 그다음
advanced 목록에
제공된 ConstraintSet을 지정된 순서대로 고려하고, 각각의 완전한
ConstraintSet(즉, ConstraintSet의 모든 제약 조건을 함께)을 충족/적용하려고
시도하지만, 전체를 충족/적용할 수 없는 경우에만 해당 ConstraintSet을
건너뜁니다. 다음으로 사용자 에이전트는 'ideal' 제약 조건이나 속성에
단일 값으로 제공된 제약 조건(선택적 기본 제약 조건이라고 함)을 각각
개별적으로 적용하려고 반드시 시도해야 합니다.
이러한 속성 중 가능한 한 많은 수를 임의의
순서로 반드시 충족해야 합니다. 마지막으로
사용자 에이전트는 반환된 프로미스를 이행해야 합니다.
getSupportedConstraints()를 통해 사용되는 모든 명명된 속성을
사용자 에이전트가 지원하는지 확인해야 합니다. 그 이유는
WebIDL이 제약 조건을 보유한 딕셔너리에서 지원되지 않는 모든 이름을 제거하므로
사용자 에이전트가 이를 볼 수 없고 지원되지 않는 이름이
아무런 알림 없이 무시되기 때문입니다. 이로 인해 JavaScript 코드에서는 제약 조건을
설정하지만 사용자 에이전트가
이를 무시하는 혼란스러운 프로그래밍 오류가 발생할 수 있습니다.
필수 제약 조건의 이름을 지원(인식)하지만 이를 충족할 수 없는
사용자 에이전트는 오류를 생성하지만,
해당 제약 가능 속성을 지원하지 않는 사용자 에이전트는
오류를 생성하지 않습니다.
다음 예는 제약 조건의 작동 방식을 이해하는 데 도움이 될 수 있습니다. 첫 번째 예는 기본 Constraint 구조를 보여 줍니다. 세 개의 제약 조건이 주어지며, 사용자 에이전트는 각각을 개별적으로 충족하려고 시도합니다. 이 카메라에서 사용할 수 있는 해상도에 따라 세 제약 조건을 모두 동시에 충족하지 못할 수도 있습니다. 이 경우 사용자 에이전트는 가능하다면 두 개를 충족하고, 두 개도 함께 충족할 수 없다면 하나만 충족합니다. 세 개를 모두 동시에 충족할 수 없는 경우 충족 가능한 두 제약 조건의 조합이 둘 이상일 수도 있다는 점에 유의하십시오. 그런 경우 사용자 에이전트가 선택합니다.
const stream = await navigator.mediaDevices.getUserMedia({
video: {
width: 1280,
height: 720,
aspectRatio: 3/2
}
});
다음 예에서는 약간의 복잡성이 추가됩니다. width와 height에는 여전히 이상적인 값이 제공되지만 이번에는 각각에 최소 요구 사항이 있으며 반드시 충족해야 하는 최소 frameRate도 있습니다. frameRate, width 또는 height의 최솟값을 충족하지 못하면 프로미스를 거부합니다. 그렇지 않으면 width, height 및 aspectRatio의 목표 값도 충족하려고 시도한 다음 프로미스를 이행합니다.
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
width: {min: 640, ideal: 1280},
height: {min: 480, ideal: 720},
aspectRatio: 3/2,
frameRate: {min: 20}
}
});
} catch (error) {
if (error.name != "OverconstrainedError") {
throw error;
}
// 제약 조건 초과. 다른 조합으로 다시 시도합니다 (권한 프롬프트는 표시되지 않았습니다)
}
이 예는 'advanced' 속성을 추가하여 Constraints 구조에서 가능한 완전한 제어를 보여 줍니다. 이 경우 사용자 에이전트는 필수 제약 조건에 대해서는 동일하게 동작하지만, 이상적인 값을 충족하려고 시도하기 전에 'advanced' 목록을 처리합니다. 이 예에서 'advanced' 목록은 두 개의 ConstraintSet을 포함합니다. 첫 번째는 width 및 height 제약 조건을 지정하고, 두 번째는 aspectRatio 제약 조건을 지정합니다. 고급 목록에서는 이러한 단일 값이 'exact' 값으로 취급된다는 점에 유의하십시오. 이 예는 다음을 의미합니다. "내 비디오는 너비가 최소 640픽셀이고 높이가 최소 480픽셀이어야 합니다. 정확히 1920x1280을 선호하지만, 그것이 불가능하다면 가능하면 aspectRatio를 4x3으로 해주십시오. 그것조차 불가능하다면 가능한 한 1280x720에 가까운 해상도를 제공해 주십시오."
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
width: {min: 640, ideal: 1280},
height: {min: 480, ideal: 720},
frameRate: {min: 30},
advanced: [
{width: 1920, height: 1280},
{aspectRatio: 4/3},
{frameRate: {min: 50}},
{frameRate: {min: 40}}
]
}
});
} catch (error) {
if (error.name != "OverconstrainedError") {
throw error;
}
// 제약 조건 초과. 다른 조합으로 다시 시도합니다 (권한 프롬프트는 표시되지 않았습니다)
}
고급 ConstraintSet의 순서는 중요합니다. 앞의 예에서는 1920x1280 ConstraintSet과 4x3 종횡비 ConstraintSet을 동시에 충족하는 것이 불가능합니다. 1920x1280이 목록에서 먼저 나타나므로 사용자 에이전트는 이를 먼저 충족하려고 시도합니다. 따라서 애플리케이션 작성자는 동일한 속성에 대해 여러 고급 ConstraintSet을 지정하여 백오프 전략을 구현할 수 있습니다. 애플리케이션은 또한 두 개의 고급 ConstraintSet을 더 지정하는데, 첫 번째는 50보다 큰 프레임 속도를 요청하고 두 번째는 40보다 큰 프레임 속도를 요청합니다. 사용자 에이전트가 프레임 속도를 50보다 크게 설정할 수 있다면 그렇게 설정합니다(그러면 후속 ConstraintSet은 자연스럽게 충족됩니다). 그러나 사용자 에이전트가 프레임 속도를 50보다 높게 설정할 수 없다면 해당 ConstraintSet을 건너뛰고 프레임 속도를 40보다 높게 설정하려고 시도합니다. 사용자 에이전트가 두 ConstraintSet 중 어느 것도 충족할 수 없는 경우, 기본 ConstraintSet의 'min' 값은 하한으로 30을 요구합니다. 즉 사용자 에이전트가 30을 넘는 값을 얻을 수 없다면 완전히 실패하지만, 가능하다면 50보다 큰 값을 선택하고, 그다음 40보다 큰 값을 시도합니다.
기본 제약 조건과 달리 고급 목록의
ConstraintSet 내부 제약 조건은 함께 충족되거나 함께 건너뛰어야 합니다.
따라서 {width: 1920, height: 1280}은 해당 특정
해상도를 요청하는 것이며, 해당 너비 또는 해당 높이 중 하나를 요청하는 것이 아닙니다.
기본 제약 조건은 개별 제약 조건의 'or'(비배타적)를 요청하는 것으로
생각할 수 있는 반면, 각 고급 ConstraintSet은 ConstraintSet 내
개별 제약 조건의 'and'를 요청합니다. 애플리케이션은
getConstraints() 접근자를 통해 현재 적용 중인 전체 Constraints 집합을
검사할 수 있습니다.
사용자 에이전트가 제약 가능한
속성에 대해 선택하는 구체적인 값을 설정이라고 합니다. 예를 들어 애플리케이션이
frameRate가 초당 최소 30프레임이고
40을 넘지 않아야 한다고 지정하는 ConstraintSet을 적용하면 설정은
그 사이의 어떤 값도 될 수 있습니다(예: 초당 32, 35 또는 37프레임).
애플리케이션은 getSettings()
접근자를 통해 객체의 제약 가능한 속성의 현재 설정을 조회할 수 있습니다.
이 명세는 형식적으로
ConstrainablePattern을 WebIDL 인터페이스로 정의하지만, 실제로는
다른 인터페이스를 위한
템플릿 또는 패턴이며 직접 상속할 수 없습니다.
메서드의 반환 값을 확장해야 하는데 WebIDL은 이를
지원하지 않기 때문입니다. 따라서 여기에서 정의한 기능을 사용하려는 각 인터페이스는
여기에서 제공된 함수 및 인터페이스에 대해 자체
WebIDL 사본을 제공해야 합니다. 그러나 변경되지 않는
여기의 의미론을 참조할 수 있습니다. 이에 대한 예는 MediaStreamTrack 인터페이스
정의를 참조하십시오.
이 패턴은 제약 가능한 객체가 세 개의 내부 슬롯을 정의하는 것에 의존합니다:
[[Capabilities]] 내부
슬롯은 노출된 각 제약 가능 속성에 대해 허용 가능한 값의
집합 전체를 설명하는 Capabilities 딕셔너리로
초기화하며, 이는
Capabilities에서 설명한 대로이고,
해당 속성이 없으면 빈 딕셔너리로 초기화합니다.
[[Constraints]] 내부
슬롯은 빈 Constraints 딕셔너리로
초기화합니다.
[[Settings]] 내부 슬롯은
노출된 각 제약 가능 속성의 현재 활성
설정 값을 설명하는 Settings 딕셔너리로
초기화하며, 이는 Settings에서 설명한 대로이고,
해당 속성이 없으면 빈 딕셔너리로 초기화합니다.
WebIDL[Exposed=Window]
interface ConstrainablePattern {
Capabilities getCapabilities();
Constraints getConstraints();
Settings getSettings();
Promise<undefined> applyConstraints(optional Constraints constraints = {});
};
getCapabilities()
메서드는 객체가 지원하는 제약 가능한
속성 이름의 딕셔너리를 반환합니다. 호출되면
사용자 에이전트는
[[Capabilities]] 내부
슬롯의 값을 반드시 반환해야 합니다.
기반 하드웨어가 제약 가능 속성에 정의된 범위와
정확히 일치하지 않을 수 있습니다. 이런 경우가 가능하다면 해당 항목은
하드웨어의 설정을 해당 속성에 정의된 값으로 변환하고
스케일링하는 방법을 정의해야 합니다.
예를 들어 가상의 fluxCapacitance 속성 범위가
-10(min)에서 10(max)이지만 일반적인 하드웨어 장치가
"off", "medium", "full" 값만 지원한다고 가정하겠습니다.
제약 가능 속성 정의는 이러한 하드웨어에 대해
사용자 에이전트가
범위 값 -10을 "off"에, 10을 "full"에, 0을
"medium"에 매핑해야 한다고 지정할 수 있습니다. 또한 엄격한 값
3을 부과하는 ConstraintSet이 주어지면
사용자 에이전트가 하드웨어에서
"medium" 값을 설정하려고 시도해야 하며,
getSettings()는
"medium"에 대응하도록 정의된 값이 0이므로
fluxCapacitance를 0으로 반환해야 한다고 나타낼 수도 있습니다.
getConstraints
getConstraints() 메서드는
객체에서 가장 최근에 성공적으로 호출된
ApplyConstraints
알고리즘의 인수였던 Constraints를 지정된
순서를 유지하여 반환합니다. 반환된 일부 고급
ConstraintSet은 현재 충족되지 않을 수도 있다는 점에 유의하십시오.
현재 어떤 ConstraintSet이 적용 중인지 확인하려면
애플리케이션은 getSettings를
사용해야 합니다.
위에서 설명한 정확한 제약 조건을
반환하는 대신 UA는 적용된 제약 조건과 모든
상황에서 동일한 효과를 갖는 제약 조건 집합을 반환할 수 있습니다.
호출되면 사용자 에이전트는
[[Constraints]] 내부 슬롯의 값을
반드시 반환해야 합니다.
getSettings() 메서드는
플랫폼 기본값인지
ApplyConstraints 알고리즘에 의해
설정되었는지와 관계없이 객체의 모든 제약 가능한 속성의 현재 설정을 반환합니다.
설정은 제약 조건을 준수하는
목표 값이므로 때때로 측정된 성능과 다를 수 있다는 점에
유의하십시오. 호출되면 사용자
에이전트는 [[Settings]]
내부 슬롯의 값을 반드시 반환해야 합니다.
applyConstraints 템플릿 메서드가 호출되면 사용자 에이전트는 다음 단계를 반드시 실행해야 합니다:
object를 이 메서드가 호출된 객체로 합니다.
newConstraints를 이 메서드의 인수로 합니다.
p를 새 프로미스로 합니다.
이 메서드가 여러 번 호출된 경우 호출 순서를 유지하면서 다음 단계를 병렬로 실행합니다:
failedConstraint를 newConstraints를 인수로 하여 ApplyConstraints 알고리즘을 실행한 결과로 합니다.
successfulSettings를 위 단계의 알고리즘이 완료된 후 object의 현재 설정으로 합니다.
다음 단계를 실행하는 태스크를 대기열에 넣습니다:
failedConstraint가
undefined가 아니면 message를
undefined 또는 유용한 사람이 읽을 수 있는
메시지로 하고,
OverconstrainedError(failedConstraint,
message)를 호출하여 생성한
새 OverconstrainedError로 p를
거부한 다음
이 단계를 중단합니다. 이 경우 기존
제약 조건은 계속 적용됩니다.
object의 [[Constraints]]
내부 슬롯을 newConstraints 또는
모든 상황에서 newConstraints와
동일한 효과를 갖는 Constraints
딕셔너리로 설정합니다.
object의 [[Settings]] 내부 슬롯을 successfulSettings로 설정합니다.
p를
undefined로
이행합니다.
p를 반환합니다.
제약 조건 적용을 위한 ApplyConstraints 알고리즘은 아래에 기술되어 있습니다. 다음은 알고리즘 기술에 사용되는 몇 가지 예비 정의입니다:
객체에 설정으로 적용될 수 있는 값의 집합을 설정 딕셔너리라고 합니다.
문자열 값 제약 조건의 경우, 아래에서 "=="는 시퀀스의 값 중 하나가 비교 대상 값과 정확히 동일하면 true로 정의합니다.
설정 딕셔너리와 제약 조건 집합 CS 사이의 적합도 거리를 CS에 존재하는 각 멤버(constraintName 및 constraintValue 쌍으로 표현)에 대해 다음 값의 합으로 정의합니다:
constraintName을 사용자 에이전트가 지원하지 않으면 적합도 거리는 0입니다.
제약 조건이 필수이고 (constraintValue가 'min', 'max' 또는 'exact'라는 이름의 멤버를 하나 이상 포함하거나, 고급 ConstraintSet 자체의 단일 값인 경우), 설정 딕셔너리의 constraintName 멤버 값이 제약 조건을 충족하지 않거나 존재하지 않으면 적합도 거리는 양의 무한대입니다.
이 유형의 객체에 제약 조건이 적용되지 않으면 적합도 거리는 0입니다(즉, 제약 조건이 적합도 거리에 영향을 주지 않습니다).
constraintValue는 불리언이지만 제약 가능 속성이 불리언이 아니라면, 적합도 거리는 설정 딕셔너리의 constraintName 멤버가 존재하는지 여부를 다음 공식에 따라 계산합니다.
(constraintValue == exists) ? 0 : 1
(actual == ideal) ? 0 : |actual - ideal| / max(|actual|, |ideal|)
(actual == ideal) ? 0 : 1
추가 정의:
SelectSettings 알고리즘을 다음과 같이 정의합니다:
알 수 없는 속성은 WebIDL에 의해 제거되므로
알 수 없거나 지원되지 않는 필수 제약 조건은
아무런 알림 없이 사라진다는 점에 유의하십시오. 이것이 예상치 못한 결과가 되지 않도록
애플리케이션 작성자는 아래 예제에 표시된 것처럼 먼저
getSupportedConstraints()
메서드를 사용해야 합니다.
ConstrainablePattern
객체로 합니다. copy를 object의 제약되지 않은
사본으로 합니다(즉, copy는 모든 ConstraintSet이
제거된 object처럼 동작해야 합니다).
copy의 가능한 모든 설정 딕셔너리에 대해 속성의 단일 값을 이상적인 값으로 취급하여 적합도 거리를 계산합니다. candidates를 적합도 거리가 유한한 설정 딕셔너리의 집합으로 합니다.
candidates가 비어 있으면
SelectSettings 알고리즘의 결과로
undefined를 반환합니다.
속성의 단일 값을 exact로 취급하여 해당 ConstraintSet과 candidates의 각 설정 딕셔너리 사이의 적합도 거리를 계산합니다.
candidates에 있는 하나 이상의 설정 딕셔너리에 대해 적합도 거리가 유한하면 해당 설정 딕셔너리만 candidates에 유지하고 나머지는 버립니다.
candidates의 모든 설정 딕셔너리에 대해 적합도 거리가 무한대이면 이 ConstraintSet을 무시합니다.
candidates에서 설정 딕셔너리 하나를 선택하여 SelectSettings 알고리즘의 결과로 반환합니다. 사용자 에이전트는 3단계에서 계산한 적합도 거리가 가장 작은 것을 반드시 사용해야 합니다. 가장 작은 적합도 거리를 가진 설정 딕셔너리가 둘 이상이면 사용자 에이전트가 시스템 기본 속성 값 및 사용자 에이전트 기본 속성 값을 기반으로 그중 하나를 선택합니다.
선택된 장치에 대해 시스템 기본값이 있는 모든 속성은 위 알고리즘과 호환되는 경우 시스템 기본값을 사용해야 합니다. 이는 일반적으로 sampleRate 또는 sampleSize 같은 속성에 해당합니다. echoCancellation이나 resizeMode 같은 다른 속성에는 일반적으로 시스템 기본값이 없습니다. 사용자 에이전트는 이러한 속성에 대한 자체 기본값을 정의합니다. 구현자는 기본값이 미디어 콘텐츠 생성 방식에 자주 영향을 미치므로 적절한 기본값을 선택하도록 주의해야 합니다.
의미 있는 기본값을 선택하기 위해 기존 구현을 살펴볼 것을 권장합니다. 기본값은 시스템에 따라, 예를 들어 데스크톱과 모바일에서 다를 수 있다는 점에 유의하십시오. 작성 시점에 사용자 에이전트 구현은 다음 기본값을 사용하는 경향이 있으며, 이는 RTCPeerConnection을 싱크로 사용하는 데 적합하도록 선택되었습니다:
width를 640으로 설정합니다.
height를 480으로 설정합니다.
frameRate를 30으로 설정합니다.
echoCancellation을
true로 설정합니다.
newConstraints가 인수로 주어졌을 때 object에 ApplyConstraints 알고리즘을 적용하려면 사용자 에이전트는 다음 단계를 반드시 실행해야 합니다:
successfulSettings를 newConstraints를 제약 조건 집합으로 하여 SelectSettings 알고리즘을 실행한 결과로 합니다.
successfulSettings가
undefined이면 failedConstraint를
SelectSettings 알고리즘 실행 중 검사한
모든 설정 딕셔너리에서 적합도 거리가 무한대였던 임의의
필수 제약 조건으로 하거나,
그러한 것이 없다면 ""로 한 다음
failedConstraint를 반환하고 이 단계를 중단합니다.
undefined를 반환합니다.위 알고리즘과 동일한 결과를 내는 모든 구현은 허용되는 구현입니다. 예를 들어 구현은 설정의 가능한 모든 값을 추적하는 대신 고려된 제약 조건에서 허용되는 설정의 최댓값과 최솟값을 추적하도록 선택할 수 있습니다.
설정 딕셔너리를 선택할 때 UA는 자신이 이용할 수 있는 모든 정보를 사용할 수 있습니다. 이러한 정보의 예로는 getUserMedia의 장치 선택 과정에서 선택이 이루어지는지, 카메라의 에너지 사용량이 설정 딕셔너리마다 달라지는지 또는 설정 딕셔너리를 사용하면 장치 드라이버가 리샘플링을 적용하게 되는지 등이 있습니다.
사용자 에이전트는 언제든지 객체의 제약 가능한 속성에 새로운 설정을 선택할 수 있습니다. 그렇게 하는 경우 위 알고리즘에 설명된 방식으로 현재 모든 Constraints를 충족하려고 반드시 시도해야 하며, successfulSettings를 그 결과의 새 설정으로 하고 다음 단계를 실행하는 태스크를 대기열에 넣어야 합니다:
object를 하나 이상의 제약 가능한 속성에 대한 새
설정이 변경된
객체로 합니다.
ConstrainablePattern
object의 [[Settings]] 내부 슬롯을 successfulSettings로 설정합니다.
applyConstraints()에
전달하거나
constraints
값으로 반환될 수 있는 Constraints의 예는 아래와 같습니다. 이 예에서는
카메라 소스 MediaStreamTrack에 정의된
제약 가능한 속성을 사용합니다. 이 예에서 모든
제약 조건은 이상적인 값이므로 결과는 사용자의 특정 카메라를 기반으로
"최선의 노력" 방식으로 결정됩니다:
await track.applyConstraints({
width: 1920,
height: 1080,
frameRate: 30,
});
const {width, height, frameRate} = track.getSettings();
console.log(`${width}x${height}x${frameRate}`); // 1920x1080x30 또는 예를 들면 다음과 같을 수 있습니다.
// 최선의 노력으로 1280x720x30
더 세밀하게 제어하려면 애플리케이션이 실패를 처리할 준비가 되어 있는 경우 정확한 일치를 요구할 수 있습니다:
try {
await track.applyConstraints({
width: {exact: 1920},
height: {exact: 1080},
frameRate: {min: 25, ideal: 30, max: 30},
});
const {width, height, frameRate} = track.getSettings();
console.log(`${width}x${height}x${frameRate}`); // 1920x1080x25-30!
} catch (error) {
if (error.name != "OverconstrainedError") {
throw error;
}
console.log(`이 카메라는 요청된 ${error.constraint}을 생성할 수 없습니다.`);
}
Constraints는 단순히 초기화 편의를 위한 것뿐만 아니라 장치 선택에 영향을 주기 위해
getUserMedia에도
전달할 수 있습니다.
이 경우
고유 제약 조건도
사용할 수 있습니다.
다음은 이전 방문에서 사용한 특정 카메라와 마이크를 선호하도록 제약 조건을 사용하는 예입니다. 크기에 대한 요구 사항과 스테레오에 대한 선호도를 포함하며, 권한이 부여된 후 적용되고 요청된 장치를 더 이상 사용할 수 없는 경우(또는 일부 사용자 에이전트에서 사용자가 이를 재정의한 경우) 적절한 대체 장치를 찾는 데에도 도움이 됩니다.
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId: localStorage.camId,
width: {min: 800, ideal: 1024, max: 1280},
height: {min: 600}
},
audio: {
deviceId: localStorage.micId,
channelCount: 2
}
});
// 허용됨. 다음 사용을 위해 deviceId를 저장합니다
localStorage.camId = stream.getVideoTracks()[0].getSettings().deviceId;
localStorage.micId = stream.getAudioTracks()[0].getSettings().deviceId;
} catch (error) {
if (error.name != "OverconstrainedError") {
throw error;
}
// 제약 조건 초과. 적절한 대체 장치를 찾지 못했습니다
}
위 예에서는 {exact: deviceId}를 사용하지 않으므로,
브라우저가 제공된 deviceId보다 사용자 선호도나 장치 부재와 같은
장치에 관해 내부적으로 이용 가능한 정보를 우선하여 사용할 수 있습니다.
또한 이 예에서는 새 선택을 나타낼 수 있으므로 권한이 부여될 때마다
deviceId를 저장합니다.
반대로 다음은 제약 조건을 사용하여 콘텐츠 내
카메라 선택기를 구현하는 예입니다. 이 경우 exact를 사용하고
사용자가 선택지 목록에서 선택하여 얻은 deviceId에만
의존합니다:
async function switchCameraTrack(freshlyChosenDeviceId, oldTrack) {
if (isMobile) {
oldTrack.stop(); // 일부 플랫폼에서는 한 번에 하나의 카메라만 열 수 있습니다.
}
const stream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId: {exact: freshlyChosenDeviceId}
}
});
const [track] = stream.getVideoTracks();
localStorage.camId = track.getSettings().deviceId;
return track;
}
다음은 휴대전화의 후면 카메라를 요청하는 예입니다. 이상적으로는 720p를 원하지만 이에 가까운 값도 허용합니다. 크기에 대한 제약 조건이 가로 모드로 지정되어 있다는 점에 유의하십시오:
async function getBackCamera() {
return await navigator.mediaDevices.getUserMedia({
video: {
facingMode: {exact: 'environment'},
width: 1280,
height: 720
}
});
}
다음은 "720p에 가까운 네이티브 16:9 해상도를 원하지만 네이티브에서 사용할 수 없더라도 정확히 10의 프레임 속도를 원합니다"라는 예입니다. 이는 두 단계로 수행해야 합니다. 첫 번째 단계에서는 네이티브 모드를 찾고, 두 번째 단계에서는 사용자 지정 프레임 속도를 적용합니다. 또한 이 예에서는 회전되었을 수 있는 현재 설정에서 제약 조건을 도출하는 방법을 보여 줍니다:
async function nativeResolutionButDecimatedFrameRate() {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
resizeMode: 'none', // 네이티브 해상도와 프레임 속도를 의미합니다
width: 1280,
height: 720,
aspectRatio: 16 / 9 // 종횡비는 정확하지 않을 수 있습니다
}
});
const [track] = stream.getVideoTracks();
const {width, height, aspectRatio} = track.getSettings();
// 제약 조건은 가로 방향이고 설정은 회전되어 있을 수 있습니다(세로)
if (width < height) {
[width, height] = [height, width];
aspectRatio = 1 / aspectRatio;
}
await track.applyConstraints({
resizeMode: 'crop-and-scale',
width: {exact: width},
height: {exact: height},
frameRate: {exact: 10},
aspectRatio,
});
return stream;
}
다음은 사용자 에이전트에서 지원되지 않아 제약 조건이
무시되는 것을 애플리케이션이 허용하지 않는 경우에
getSupportedConstraints를
사용하는 방법을 보여 주는 예입니다:
async function getFrontCameraRes() {
const supports = navigator.mediaDevices.getSupportedConstraints();
for (const constraint of ["facingMode", "aspectRatio", "resizeMode"]) {
if (!(constraint in supports) {
throw new OverconstrainedError(constraint, "지원되지 않음");
}
}
return await navigator.mediaDevices.getUserMedia({
video: {
facingMode: {exact: 'user'},
advanced: [
{aspectRatio: 16/9, height: 1080, resizeMode: "none"},
{aspectRatio: 4/3, width: 1280, resizeMode: "none"}
]
}
});
}
유효한 입력 집합을 지정하는 구문은 값의 유형에 따라 달라집니다. 표준 원자 유형 (boolean, long, double, DOMString) 외에도 유효한 값에는 아래에 정의된 대로 모든 원자 유형의 목록 및 min-max 범위가 포함됩니다.
목록 값은 논리합으로 반드시 해석해야 합니다. 예를 들어 카메라의
'facingMode' 속성이 유효한 값으로
["left", "right", "user", "environment"]를 가진다고 정의되어 있다면,
이는 'facingMode'가 "left", "right", "environment" 및 "user" 값을
가질 수 있음을 의미합니다. 마찬가지로
'facingMode'를 ["user", "left", "right"]로 제한하는
Constraints는
사용자 에이전트가 "facingMode"가 "user",
"left" 또는 "right" 중 하나가 되도록 카메라를 선택해야 함
(가능한 경우 카메라 방향을 조정)함을 의미합니다. 따라서 이 Constraint는
카메라가 사용자의 반대 방향을 향하지 않도록 요청하지만
사용자 에이전트가
사용자가 다른 방향을 선택하도록 허용하는 것은 가능하게 합니다.
WebIDLdictionary ConstrainDoubleRange : DoubleRange {
double exact;
double ideal;
};
WebIDLdictionary ULongRange {
[Clamp] unsigned long max;
[Clamp] unsigned long min;
};
max 유형: unsigned long
이 속성의 유효한 최댓값입니다.
min 유형: unsigned long
이 속성의 최솟값입니다.
WebIDLdictionary ConstrainULongRange : ULongRange {
[Clamp] unsigned long exact;
[Clamp] unsigned long ideal;
};
exact
유형: unsigned long
이 속성에 필요한 정확한 값입니다.
ideal
유형: unsigned long
이 속성의 이상적인(목표) 값입니다.
WebIDLdictionary ConstrainDOMStringParameters {
(DOMString or sequence<DOMString>) exact;
(DOMString or sequence<DOMString>) ideal;
};
WebIDLdictionary ConstrainBooleanOrDOMStringParameters {
(boolean or DOMString) exact;
(boolean or DOMString) ideal;
};
WebIDLtypedef ([Clamp] unsigned long or ConstrainULongRange) ConstrainULong;
ConstrainULong은 ([Clamp]
unsigned long or
ConstrainULongRange) 유형을 참조하는 데 사용됩니다.
WebIDLtypedef (double or ConstrainDoubleRange) ConstrainDouble;
ConstrainDouble은 (double
or ConstrainDoubleRange) 유형을 참조하는 데 사용됩니다.
WebIDLtypedef (boolean or ConstrainBooleanParameters) ConstrainBoolean;
ConstrainBoolean은 (boolean or ConstrainBooleanParameters) 유형을 참조하는 데 사용됩니다.
WebIDLtypedef (DOMString or
sequence<DOMString> or
ConstrainDOMStringParameters) ConstrainDOMString;
ConstrainDOMString은 (DOMString or sequence<DOMString> or
ConstrainDOMStringParameters) 유형을 참조하는 데 사용됩니다.
WebIDLtypedef (boolean or DOMString or ConstrainBooleanOrDOMStringParameters) ConstrainBooleanOrDOMString;
ConstrainBooleanOrDOMString은
(boolean or DOMString or ConstrainBooleanOrDOMStringParameters)
유형을 참조하는 데 사용됩니다.
Capabilities은 하나 이상의
키-값 쌍을 포함하는 딕셔너리이며, 각 키는 제약 가능한 속성이어야 하고,
각 값은 해당 속성에 허용되는 값 집합의 부분집합이어야 합니다.
값 표현식의 정확한 구문은 속성 유형에 따라 달라집니다.
Capabilities 딕셔너리는
제약 가능한
객체에 제약 조건으로 적용할 수 있는 제약 가능한
속성을 지정합니다. 제약 가능한 객체의 Capabilities는
Web 플랫폼에 정의된 속성의 부분집합일 수 있으며,
해당 속성에 대해 설정된 값의 부분집합을 가질 수 있습니다. Capabilities는
사용자 에이전트에서 애플리케이션으로 반환되며
애플리케이션이 지정할 수 없다는 점에 유의하십시오. 그러나 애플리케이션은
Constraints를 통해 사용자 에이전트가 제약 가능한 속성에 대해
선택하는 Settings를 제어할 수 있습니다.
Capabilities 딕셔너리의 예는 아래와 같습니다. 이 경우 제약 가능한 객체는 매우 제한된 Capabilities 집합을 가진 비디오 소스입니다.
{
frameRate: {min: 1.0, max: 60.0},
facingMode: ['user', 'left']
}
다음 예에서는 범위 값에 대한 기능이 조합이 아니라 개별 제약 가능 속성에 대한 범위를 제공한다는 점을 보여 줍니다. 이는 특히 비디오 width와 height에 관련이 있는데, width와 height의 범위가 별도로 보고되기 때문입니다. 예에서 제약 가능한 객체가 640x480 및 800x600 해상도만 제공할 수 있다면 반환되는 관련 기능은 다음과 같습니다:
{
width: {min: 640, max: 800},
height: {min: 480, max: 600},
aspectRatio: {min: 4/3, max: 4/3}
}
위 예에서 aspectRatio는 width와 height의 임의 조합이 불가능함을 명확히 나타내지만, 여전히 두 개보다 많은 해상도를 사용할 수 있는 것처럼 보일 수 있다는 점에 유의하십시오.
제약 가능 패턴을 사용하는 명세는 아래 딕셔너리를 상속해서는 안 되며, 대신 자체 정의를 제공해야 합니다. 예는MediaTrackCapabilities를
참조하십시오.
WebIDLdictionary Capabilities {};
Settings는 하나 이상의 키-값
쌍을 포함하는 딕셔너리입니다. 해당 속성이 반환되는 객체 유형에 정의되어 있는 경우
getCapabilities()가 반환한 각 키를 반드시 포함해야 합니다.
예를 들어 오디오
MediaStreamTrack에는 "width" 속성이 없습니다.
각 키에는 단일 값이 반드시
있어야 하며 그 값은 getCapabilities()가 해당 속성에
정의한 집합의 멤버여야 합니다.
Settings 딕셔너리는 사용자 에이전트가 객체의 제약 가능한
속성에 대해 선택한 실제 값을 포함합니다. 값의 정확한
구문은 속성 유형에 따라 달라집니다.
적합한 사용자 에이전트는 이 명세에 정의된 모든 제약 가능한 속성을 반드시 지원해야 합니다.
Settings 딕셔너리의 예는 아래와 같습니다. 이 예는 실제로는 사용자 에이전트가 이들보다 더 많은 제약 가능한 속성을 지원해야 한다는 점에서 그다지 현실적이지 않습니다.
{
frameRate: 30.0,
facingMode: 'user'
}
MediaTrackSettings를 참조하십시오.
WebIDL의 제한으로 인해 제약 가능 패턴을 구현하는 인터페이스는 여기에서 정의된 Constraints와 ConstraintSet을 단순히 상속할 수 없습니다. 대신 이 패턴을 따르는 자체 정의를 제공해야 합니다. 이에 대한 예는 MediaTrackConstraints를 참조하십시오.
WebIDLdictionary ConstraintSet {};
ConstraintSet의 각 멤버는
제약 가능한 속성에 대응하며 해당 속성의 유효한
Capability 값의 부분집합을 지정합니다. ConstraintSet을 적용하면
사용자 에이전트에
대응하는 제약 가능한 속성의 설정을 지정된 값 또는 값의 범위로
제한하도록 지시합니다. 주어진 속성은 기본 Constraints 집합과
고급 ConstraintSet 목록 모두에 나타날 수 있으며,
고급 목록의 각 ConstraintSet에는 최대 한 번만 나타날 수 있습니다.
WebIDLdictionary Constraints : ConstraintSet {
sequence<ConstraintSet> advanced;
};
advanced 유형: sequence<ConstraintSet>이는 사용자
에이전트가 순서대로 충족하려고 반드시
시도해야 하는 ConstraintSet 목록이며, 충족할 수 없는 것만
건너뜁니다. 이러한 ConstraintSet의 순서는 중요합니다. 특히
applyConstraints의 인수로 전달되는 경우
사용자
에이전트는 지정된 순서대로 이를 충족하려고 반드시
시도해야 합니다. 따라서 고급 ConstraintSet C1과 C2를
각각 개별적으로는 충족할 수 있지만 함께 충족할 수 없다면,
이 목록에서 먼저 나오는 C1 또는 C2가 충족되고
나머지는 충족되지 않습니다. 사용자
에이전트는 일부를 충족할 수 없더라도 목록의 모든
ConstraintSet을 충족하려고 반드시 시도해야 합니다.
따라서 앞의 예에서 제약 조건 C3가 C1 및 C2 뒤에
지정되었다면, C2를 충족할 수 없더라도
사용자 에이전트는
C3을 충족하려고 시도합니다. 주어진 속성 이름은 각 ConstraintSet에
한 번만 나타날 수 있지만 둘 이상의 ConstraintSet에는 나타날 수 있다는 점에
유의하십시오.
이 샘플 코드는 버튼 하나를 표시합니다. 클릭하면 버튼이 비활성화되고 사용자에게 스트림을 제공하라는 메시지가 표시됩니다. 사용자는 스트림을 제공한 다음(예: 페이지에 로컬 카메라 액세스 권한 부여) 스트림을 비활성화하여(예: 해당 액세스 권한 철회) 버튼을 다시 활성화할 수 있습니다.
<button id="startBtn">시작</button>
<script>
const startBtn = document.getElementById('startBtn');
startBtn.onclick = async () => {
try {
startBtn.disabled = true;
const constraints = {
audio: true,
video: true
};
const stream = await navigator.mediaDevices.getUserMedia(constraints);
for (const track of stream.getTracks()) {
track.onended = () => {
startBtn.disabled = stream.getTracks().some((t) => t.readyState == 'live');
};
}
} catch (err) {
console.error(err);
}
};
</script>
이 예에서는 로컬 비디오 카메라를 사용하여 자신의 사진을 찍을 수 있습니다. Image Capture 명세 [image-capture]가 이를 더 간단하게 수행할 수 있는 방법을 제공한다는 점에 유의하십시오.
<script>
window.onload = async () => {
const video = document.getElementById('monitor');
const canvas = document.getElementById('photo');
const shutter = document.getElementById('shutter');
try {
video.srcObject = await navigator.mediaDevices.getUserMedia({video: true});
await new Promise(resolve => video.onloadedmetadata = resolve);
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
document.getElementById('splash').hidden = true;
document.getElementById('app').hidden = false;
shutter.onclick = () => canvas.getContext('2d').drawImage(video, 0, 0);
} catch (err) {
console.error(err);
}
};
</script>
<h1>스냅샷 키오스크</h1>
<section id="splash">
<p id="errorMessage">불러오는 중...</p>
</section>
<section id="app" hidden>
<video id="monitor" autoplay></video>
<button id="shutter">📷</button>
<canvas id="photo"></canvas>
</section>
이 명세는
이름
"camera"
및
"microphone"으로
식별되는 두 개의 강력한 기능을
정의합니다.
다음 유형과 알고리즘을 정의합니다:
WebIDLdictionary CameraDevicePermissionDescriptor : PermissionDescriptor {
boolean panTiltZoom = false;
};
권한은 한 종류의 장치 중 적어도 하나에 대한 액세스를 포괄합니다.
디스크립터의 의미는 해당 종류의 임의 장치에 대한 액세스 가능 여부를 질의한다는 것입니다.
따라서 "camera" 권한에 대한 질의가 "granted"를
반환하면,
클라이언트는 권한 프롬프트 없이 하나의 카메라에 액세스할 수 있음을 알 수 있으며,
"denied"가
반환되면 카메라에 대한 어떤 getUserMedia 요청도 성공하지 못한다는 것을 알 수 있습니다.
사용자 에이전트가 한 종류의 일부 장치에는 권한이 부여되었지만 모든 장치에는 부여되지 않았다고 판단하면,
질의는
"granted"를
반환합니다.
사용자 에이전트가 한 종류의 모든 장치에 권한이 거부되었다고 판단하면,
질의는
"denied"를
반환합니다.
{name: "camera", panTiltZoom: true}는
{name: "camera", panTiltZoom: false}보다 더 강합니다.
"granted"
권한은 getUserMedia가 성공한다는 보장이 아닙니다. 이는
사용자에게 권한을 묻는 프롬프트가 표시되지 않는다는 것만 나타냅니다. 제약 조건이나 카메라가 사용 중인 경우 등
getUserMedia가 실패하게 할 수 있는 다른 요인이 많이 있습니다.
name을
인수로 전달하여 장치 권한 철회 알고리즘을 호출한
결과입니다.
이 명세는 문자열 "camera" 및 "microphone"으로 식별되는 두 개의
정책 제어
기능을 정의합니다.
둘 다
"self"의 기본
허용 목록을 가집니다.
문서의
권한
정책은
해당 문서의 콘텐츠가
getUserMedia를 사용하여 각각 카메라 또는
마이크를 요청할 수 있는지 결정합니다. 어떤 문서에서든
비활성화되어 있으면 문서의 어떤 콘텐츠도
getUserMedia를 사용하여 각각
카메라 또는 마이크를 요청하도록 허용되지
않습니다.
이는 사용 권한 요청
알고리즘에 의해 강제됩니다.
또한 enumerateDevices는 문서가
사용하도록
허용된 장치만 열거합니다.
이 명세는 하나의 MediaDevices 객체의
관점에서 알고리즘을 사용하여 개인정보 보호 표시기 요구 사항을 표현합니다.
구현자는 iframe으로 인해 한 페이지에서 공존할 수 있는 여러
MediaDevices 객체를 포괄하도록
이러한 원칙을 확장하여 표시기 표현을 통합할 것을 권장합니다.
getUserMedia()가 노출하는 각 장치
kind에 대해,
[[kindsAccessibleMap]][kind] 값과
해당 종류의 장치에 대한 모든
[[devicesAccessibleMap]][deviceId]
값의 논리합으로 정의합니다.
[[kindsAccessibleMap]][kind] 값과
해당 종류의 장치에 대한 모든
[[devicesLiveMap]][deviceId] 값의
논리합으로 정의합니다.
anyAccessible을 모든 any<kind>Accessible 값의 논리합으로 정의합니다.
anyLive를 모든 any<kind>Live 값의 논리합으로 정의합니다.
그다음 사용자 에이전트에는 다음 요구 사항이 적용됩니다:
[[devicesAccessibleMap]][deviceId]
값 및
[[devicesLiveMap]][deviceId] 값에 대해
최소한 값이 변경될 때 반드시 알려야 합니다.
또한 사용자 에이전트에는 다음 동작이 권장됩니다:
[[devicesAccessibleMap]][deviceId]
값 및
[[devicesLiveMap]][deviceId] 값에 대해
현재 상태를 지속적으로 표시할 것을 권장합니다. 또한 모든 장치별 하드웨어 표시등이
대응하는 [[devicesLiveMap]][deviceId] 값과 일치하도록
할 것을
권장합니다.
이 절은 비규범적이며 새로운 동작을 지정하지 않고 명세의 다른 부분에 이미 존재하는 정보를 요약합니다.
이 명세는 미디어 입력 장치, 특히 마이크와 카메라를 관리할 수 있는 기능으로 Web 플랫폼을 확장합니다. 또한 오디오 출력 장치(스피커 및 헤드폰)와 같은 다른 미디어 장치에 관한 정보를 노출할 가능성도 허용하지만, 그러한 노출의 세부 사항은 다른 명세에 위임됩니다. 사용자의 마이크와 카메라에서 오디오 및 비디오를 캡처하면 개인 식별 정보를 애플리케이션에 노출하게 되므로, 이 명세는 이를 공유하기 전에 명시적인 사용자 동의를 얻도록 요구합니다.
카메라나 마이크를 캡처하기 전에 애플리케이션("드라이브 바이 웹")에는
사용자에게 카메라 또는 마이크가 있는지(몇 개인지는 제외)만
확인할 수 있는 기능이 제공됩니다. 장치 식별자는 출처 간에
사용자를 추적할 수 있는 핑거프린트에 유용하지 않도록 설계되었지만,
카메라 또는 마이크 기능의 존재는 핑거프린팅 표면에 2비트를
추가합니다. 출처별 지속 식별자인 deviceId는
다른 지속성 저장소(예: 쿠키)와 동일하게 취급할 것을 권장합니다.
카메라 또는 마이크 캡처가 시작되면, 이 명세는 앞서 언급한 장치의 미디어 데이터에 액세스하고 이를 사용하는 방법을 설명합니다. 이 데이터는 민감할 수 있습니다. 장치가 사용 중임을 나타내는 표시기를 제공해야 한다는 조언이 있지만, 권한의 성격과 사용 중인 장치의 표시기 모두 플랫폼의 결정 사항입니다.
캡처 시작 권한은 사례별로 부여하거나 지속적으로 부여할 수 있습니다. 사례별 권한의 경우 사용자가 권한을 부여할 때까지 UI가 사용자 상호작용을 차단하지 않도록 "아니요"라고 말할 수 있는 것이 중요합니다. 이는 "지속적인 아니요"라고 말할 수 있는 방법을 제공하거나 모달 권한 대화 상자를 사용하지 않는 방식으로 구현할 수 있습니다.
카메라 또는 마이크 캡처가 시작되면 웹 문서는 사용 가능한 모든 미디어 캡처 장치와 해당 레이블을 나열할 수 있게 됩니다. 이 기능은 웹 문서가 닫힐 때까지 유지되며 지속시킬 수 없습니다. 대부분의 경우 레이블은 출처 간에 안정적이므로 시간과 출처를 넘어 특정 장치를 추적하는 방법을 제공할 가능성이 있습니다.
이 명세는 사용 중인 장치 이외의 장치 정보도 노출합니다. 이는 이전 버전과의 호환성 및 레거시 이유 때문입니다. 향후 명세는 이 모델을 사용하지 말고 장치 열거 설계 원칙에 설명된 모범 사례를 따를 것을 권장합니다.
캡처가 시작되었거나 수행된 열린 웹 문서 또는 보이는 상태인 웹 문서에서는 새 미디어 장치가 추가되거나 제거될 때마다 devicechange 이벤트가 여러 탐색 가능 항목과 출처에서 동시에 발생할 수 있습니다. 사용자 에이전트는 이러한 이벤트의 타이밍에 퍼징을 적용하거나 해당 웹 문서가 보이는 상태가 될 때까지 발생을 연기하여 출처 간 브라우징 활동이 상관관계로 연결될 위험을 완화할 수 있습니다.
웹 문서가 캡처 장치의 미디어 스트림에 액세스하게 되면 장치의 작동 기능 범위(예: 카메라에서 사용할 수 있는 해상도)를 포함한 상세 정보에도 액세스할 수 있게 됩니다. 이러한 작동 기능은 대부분 브라우징 세션과 출처 전반에 걸쳐 지속되므로 시간과 출처를 넘어 특정 장치를 추적하는 방법을 제공합니다.
캡처 장치의 비디오 스트림에 액세스할 수 있게 되면 해당 스트림은 해당 장치를 고유하게 핑거프린팅하는 데 사용될 가능성이 매우 높습니다 (예: 불량 픽셀 감지를 통해). 마찬가지로 오디오 스트림에 액세스할 수 있게 되면 해당 스트림은 사용자의 위치를 방 수준까지, 심지어 서로 다른 사용자가 같은 방에 동시에 있는지까지 핑거프린팅하는 데 사용될 가능성이 매우 높습니다 (예: 주변 오디오 분석 또는 장치 스피커에서 의도적으로 재생한 고유 오디오 분석). 오디오와 비디오 모두에 대한 사용자 수준의 완화 방법은 카메라 및/또는 마이크를 물리적으로 가리거나 사용자 에이전트 크롬 제어를 통해 권한을 철회하는 것입니다.
제약 조건을 이용하면 getUserMedia 호출 실패가 사용자에게 묻지 않고도 시스템의 장치에 관한 정보를 반환하도록 할 수 있으며, 이는 핑거프린팅에 사용할 수 있는 표면을 증가시킵니다. 사용자 에이전트는 이러한 추가 표면을 제한하기 위해 실패한 getUserMedia 호출의 허용 빈도를 제한하는 것을 고려해야 합니다.
캡처 시작을 위한 지속 권한이 저장된 경우에는 부여된 권한 목록을 쉽게 찾고 사용자가 철회하려는 권한을 쉽게 철회할 수 있도록 하는 것이 중요합니다.
권한이 부여되면 사용자 에이전트는 다음 두 가지를 사용자가 쉽게 알아볼 수 있도록 해야 합니다:
저장된 권한을 가진 사이트의 개발자는 이러한 권한이 악용되지 않도록 주의해야 합니다. 이러한 권한은 [permissions] API를 사용하여 철회할 수 있습니다.
특히 권한이 부여된 미디어 장치의 오디오 또는 비디오 스트림을 제3자가 선택할 수 있는 엔드포인트로 자동 전송할 수 있도록 해서는 안 됩니다.
실제로 사이트가
https://webrtc.example.org/?call=user와 같이
자동으로 통화를 설정하고 오디오/비디오를
user에게 전송하는 URL을 제공한다면,
예를 들어 다음과 같이 악용될 수 있습니다:
https://webrtc.example.org/에 저장된 권한을 부여한 사용자는
링크를 따르거나
https://webrtc.example.org/?user=EvilSpy로 리디렉션되어
공격자 EvilSpy에게 자신의
오디오/비디오 스트림을 전송하도록 속을 수 있습니다.
이 절은 비규범적입니다.
향후 이 명세의 새 버전이 작성될 수 있지만, 다른 표준에서도 이 명세의 기능을 기반으로 하는 새로운 기능을 정의해야 할 것으로 예상됩니다. 이 절의 목적은 이러한 확장 기능의 작성자에게 지침을 제공하는 것입니다.
명세에서 WebIDL로 정의된 모든 인터페이스, 메서드 또는 속성은 확장할 수 있습니다. 가능성이 높은 두 확장 지점은 새로운 미디어 유형을 정의하는 것과 새로운 제약 가능 속성을 정의하는 것입니다.
kind 정의(오디오 및 비디오 이외)
최소한 새로운 미디어 유형을 정의하려면 다음이 필요합니다.
MediaStream 인터페이스에 추가하고,
MediaStreamTrack
인터페이스의
kind 속성에
새로운 유형을 추가 유효 값으로 추가하고,
MediaStream과 함께
HTMLMediaElement가
작동하는 방식을 업데이트하고
(6.
미디어 요소의 MediaStream 참조),
여기에는 새 미디어 유형을 위한
청취 가능/청취 불가능 상태에 대응하는 상태를 추가하는 것도 포함하며,
MediaDeviceKind를 업데이트하고,
getCapabilities()
및
getUserMedia()
설명을 업데이트하고,
MediaStreamConstraints 딕셔너리에 추가하고,
kind와 연결된 새로운 PermissionDescriptor 이름을
포함하고, 이러한
권한과 액세스 시작 및 종료, 음소거/비활성화가
새로 추가되거나 기존에 존재하는 "방송 중" 및 "장치
액세스 가능" 표시기 상태에 어떤 영향을 미치는지 정의해야 합니다(MediaDevices 참조).
또한 다음을 업데이트해야 합니다.
MediaStreamTrack 인터페이스의
label 속성 설명,
또한 다음을 포함할 수도 있습니다.
MediaStreamTrackState에서
이러한 트랙이 어떻게 종료될 수 있는지에 대한 예를 제공합니다.이를 위해서는 해당 속성의 Constraints,
Capabilities 및 Settings(3. 용어 참조)가
어떻게 작동할지 검토하고 정의해야 합니다.
MediaTrackSupportedConstraints,
MediaTrackCapabilities,
MediaTrackConstraints,
MediaTrackSettings, 4.3.8 제약 가능한
속성 및
MediaStreamConstraints의 관련 텍스트를
모델로 사용해야 합니다.
확장 명세 작성자는
명세 저장소에서 명세 유지관리자에게 알릴 것을 강력히 권장합니다.
이 명세의 향후 버전과 WebRTC Working Group이 작성하는 다른 명세는
잠재적인 사용 충돌을 줄이기 위해 알고 있는 모든 확장 기능을 고려합니다.
MediaStreamTrack 및 MediaStream을 위한 새로운 싱크 정의다른 명세에서는 MediaStream 및/또는
MediaStreamTrack을 위한 새로운 싱크를 정의할 수 있습니다.
최소한 새로운
MediaStreamTrack 소비자는 다음을 정의해야 합니다:
MediaStreamTrack이
음소거 및 비활성화를 포함한 다양한 상태에서 어떻게
소비되는지(4.3.1 미디어 흐름 및 수명 주기 참조).
MediaStreamTrack용
다른 명세에서는 MediaStreamTrack의 새로운 소스를
정의할 수 있습니다.
최소한 새로운 MediaStreamTrack 소스는 다음을
수행해야 합니다.
kind의
MediaStreamTrack을 생성하는
새로운 API를 정의해야 합니다
(getUserMedia()는
카메라 및 마이크 소스 전용입니다).
kind에 적용되는 제약 가능 속성
(4.3.8 제약 가능한 속성
참조)이 있다면 이를 선언하고,
이 소스에서 어떻게 작동하는지 정의해야 합니다.
편집자는 Working Group 의장과 Team Contact, Harald Alvestrand, Stefan Håkansson, Erik Lagerway 및 Dominique Hazaël-Massieux의 지원에 감사드립니다. 이 명세의 상당한 분량의 텍스트는 Jim Barnett, Harald Alvestrand, Travis Leithead, Josh Soref, Martin Thomson, Jan-Ivar Bruaroey, Peter Thatcher, Dominique Hazaël-Massieux 및 Stefan Håkansson을 포함한 많은 사람이 제공했습니다. Dan Burnett은 이 명세 개발 과정에서 Voxeo와 Aspect로부터 받은 상당한 지원에 감사의 뜻을 전합니다.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: