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에서 수행된 초기 작업을 기반으로 합니다.
이 문서가 제안 권고(Proposed Recommendation) 단계로 진행되기 전에, WebRTC 워킹 그룹은 광범위한 검토에서 제기된 이슈를 해결할 계획입니다.
이 문서는 웹 실시간 통신(Web Real-Time Communications) 워킹 그룹에서 권고 절차(Recommendation track)를 통해 후보 권고 초안(Candidate Recommendation Draft)으로 발행되었습니다.
후보 권고(Candidate Recommendation)로 발행되었다고 해서 W3C 및 회원의 승인이나 지지를 의미하지는 않습니다. 후보 권고 초안은 워킹 그룹이 이후 후보 권고 스냅샷에 포함할 예정인 이전 후보 권고의 변경사항을 통합합니다.
이 문서는 초안이며 언제든지 업데이트, 교체 또는 폐기될 수 있습니다. 진행 중인 작업 외에 이 문서를 인용하는 것은 적절하지 않습니다.
이 문서는 W3C 특허 정책(Patent Policy)에 따라 운영되는 그룹에 의해 제작되었습니다. W3C는 그룹 산출물과 관련된 공개 특허 공개 목록을 관리합니다; 해당 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 특정 특허에 대한 실질적 지식이 있고, 해당 특허가 필수 청구(Claim)를 포함한다고 믿는 개인은 W3C 특허 정책 6절에 따라 정보를 공개해야 합니다.
이 문서는 2025년 8월 18일 W3C 프로세스 문서에 따라 관리됩니다.
이 섹션은 비규범적입니다.
이 문서는 마이크나 비디오 카메라와 같은 로컬 멀티미디어 장치에 대한 접근을 요청하는 API를 정의합니다.
이 문서는 또한 멀티미디어 스트림 데이터가 어디에서 소비되는지 제어할 수 있는 수단과, 미디어를 생성하는 장치에 대한 일부 제어를 제공하는 MediaStream API를 정의합니다. 또한 미디어를 캡처하고 렌더링할 수 있는 장치에 대한 정보를 노출합니다.
비규범적으로 표시된 섹션과 마찬가지로, 이 명세서의 모든 저작 가이드라인, 도표, 예시, 그리고 노트는 비규범적입니다. 이 명세서의 나머지 모든 내용은 규범적입니다.
이 문서에 사용된 MAY, MUST, MUST NOT, NOT REQUIRED, SHOULD 등의 주요 용어는 BCP 14 [RFC2119] [RFC8174] 에서 설명된 대로, 여기와 같이 모두 대문자로 표시된 경우에만 해당 의미로 해석되어야 합니다.
이 명세서는 하나의 제품에 적용되는 적합성 기준을 정의합니다: 이 명세서에 포함된 인터페이스를 구현하는 User Agent입니다.
알고리즘이나 구체적 단계로 표현된 적합성 요구사항은 최종 결과가 동일하기만 하면 어떠한 방식으로든 구현할 수 있습니다. (특히, 이 명세서에 정의된 알고리즘은 이해하기 쉽게 작성되어 있으며, 성능을 목적으로 한 것은 아닙니다.)
이 명세서에서 정의된 API를 ECMAScript [ECMA-262]를 사용해 구현하는 경우, Web IDL 명세서 [WEBIDL]에 정의된 ECMAScript 바인딩에 따라 일관되게 구현해야 하며, 이 명세서는 해당 명세서의 용어와 개념을 사용합니다.
source는 미디어 스트림 트랙의 소스를 제공하는 "대상"입니다. source는 미디어 자체를 방송하는 역할을 합니다. source는 실제 웹캠, 마이크, 사용자의 하드 드라이브에 있는 로컬 비디오 또는 오디오 파일, 네트워크 리소스, 정적 이미지 등이 될 수 있습니다. 참고로, 이 문서에서는 마이크와 카메라 유형의 소스만 설명하며, 다른 유형의 소스 사용에 대해서는 다른 문서에서 다룹니다.
소스에 대해 사전 권한이 없는 애플리케이션은 사용 가능한 소스의 개수, 종류, 기타 장치와의 관계만 제공받습니다. 애플리케이션이 소스 사용 권한을 얻으면 추가 정보가 제공될 수 있습니다 (9.2.1 접근 제어 모델 참조).
source에는 제약조건이 없습니다 — 트랙에 제약조건이 있습니다. 소스가 트랙에 연결되면 해당 트랙에 있는 제약조건을 충족하는 미디어를 반드시 생성해야 합니다. 하나의 소스에 다수의 트랙이 연결될 수 있습니다. User Agent 처리(예: 다운샘플링)는 모든 트랙에 적절한 미디어가 제공되도록 MAY 사용될 수 있습니다.
source는 capabilities와 settings가 트랙에 노출되는 제약 가능한 속성을 가집니다. 제약 가능한 속성은 source가 "소유"하지만, source는 동시에 여러 요구사항을 수용할 수 MAY 있습니다. 따라서 capabilities는 같은 소스를 사용하는 모든(복수) 트랙에 공통적으로 적용되지만, settings는 트랙마다 다를 수 MAY 있습니다(예: 동일한 소스에 연결된 두 트랙 객체가 capability와 settings 정보를 요청하면, capability는 동일하게 반환되지만, 각 트랙의 제약조건에 맞게 다른 settings가 반환될 수 있습니다).
setting은 소스의 제약 가능한 속성의 즉각적이고 현재의 값을 의미합니다. settings는 항상 읽기 전용입니다.
카메라가 저조도 상태에서 낮은 프레임률로 전환되는 등 소스의 상태가 동적으로 변경될 수 있습니다. 이런 경우, 해당 소스와 관련된 트랙들이 더 이상 설정된 제약조건을 만족하지 못할 수 있습니다. 플랫폼은 이런 상황을 가능한 한 최소화해야 SHOULD 하지만, 제약조건을 만족할 수 없는 임시 또는 영구적 상황이 발생해도 미디어 제공은 계속됩니다.
settings는 소스의 속성이지만, 소스에 연결된 트랙을 통해서만 애플리케이션에 노출됩니다. 이는 ConstrainablePattern
인터페이스를 통해 노출됩니다.
각 제약 가능한 속성마다, 소스에서 지원 여부와 지원되는 값의 범위를 설명하는 capability가 있습니다. settings와 마찬가지로, capabilities도 ConstrainablePattern
인터페이스를 통해 애플리케이션에
노출됩니다.
지원되는 capability 값은 이 명세서에 정의된 범위와 열거형 타입에 맞게 표준화되어야 합니다.
트랙에서 getCapabilities
()
를 호출하면, 해당 소스에 연결된 모든 트랙에 대해 동일한 capability가 반환됩니다.
이 API는 의도적으로 단순화되어 있습니다. capability는 서로 다른 값 간의 상호작용을 설명할 수 없습니다. 예를 들어, 카메라가 저해상도에서 높은 프레임률, 고해상도에서 낮은 프레임률로 영상 스트림을 생성할 수 있는 경우, capability만으로 정확하게 설명할 수 없습니다. capability는 각 값의 전체 범위만 기술합니다. 제약조건 간의 상호작용은 실제로 제약조건을 적용해 봄으로써 드러납니다.
제약조건은 애플리케이션이 트랙에 적합한 소스를 선택하고, 선택된 이후에는 소스의 동작 방식을 제어할 수 있도록 하는 일반적인 제어 수단입니다.
제약조건은 소스가 트랙에 미디어를 제공할 때 사용할 수 있는 동작 모드의 범위를 제한합니다. 트랙 제약조건이 제공되지 않으면, 구현체는 소스의 capability에서 지원하는 전체 범위 중 자유롭게 설정을 선택할 수 있습니다. 또한, 구현체는 적용된 모든 제약조건의 범위 안에서 언제든 소스 설정을 조정할 수 있습니다.
getUserMedia
()
는 제약조건을
사용해 트랙에 적합한 소스를 선택하고 설정합니다. 또한, 트랙의 ConstrainablePattern
인터페이스에는 이후에도 동적으로
트랙의 제약조건을 변경할 수 있는 API가 포함되어 있습니다.
트랙의 초기 제약조건을 만족할 수 없으면, getUserMedia
()
를 통해
소스에 연결되지 않습니다. 하지만 트랙의 제약조건을 만족할 수 있는 능력은 시간이 지남에 따라 변할 수 있고, 제약조건도 변경될 수 있습니다. 만약 제약조건을 만족할 수 없는
상황이 발생하면, ConstrainablePattern
인터페이스가 애플리케이션에 적절한
오류를 제공합니다. 5. 모델: 소스, 싱크, 제약조건, 설정값에서는 제약조건의 상호작용에 대해 더 자세히 설명합니다.
각 제약 가능한 속성마다, 해당 소스의 setting 이름과 capability 이름과 일치하는 이름의 제약조건이 존재합니다.
제약조건은 구조 내에서 위치에 따라 세 가지 그룹 중 하나에 속합니다. 그룹은 다음과 같습니다:
advanced
키워드로 지정된 모든 제약조건입니다.
일반적으로, User Agent는 적용되는 제약조건이 적을수록 미디어 스트리밍 경험을 최적화할 수 있으므로, 애플리케이션 작성자는 필수 제약조건을 신중하게 사용하는 것을 강력히 권장합니다.
MediaStream API의 두 주요 구성요소는 MediaStreamTrack
및 MediaStream
인터페이스입니다. MediaStreamTrack
객체는 User Agent 내에서 하나의 미디어 소스에서 기원한 단일 유형의 미디어(예: 웹캠에서 생성된 비디오)를
나타냅니다. 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
은 복제된 인스턴스와 독립적인 제약조건 집합을 가지므로, 동일한 소스에서 온 미디어에 서로 다른 제약조건을 적용할 수 있습니다. consumer별로 다르게 미디어를 제공할 수 있습니다. MediaStream
객체는 [WEBRTC]와 같이 getUserMedia
이외의 문맥에서도 사용됩니다.
MediaStream
MediaStream constructor
는 기존 트랙으로부터 새로운 스트림을 구성합니다. 선택적으로 MediaStream
또는 MediaStreamTrack
객체 배열을 인자로 받을 수 있습니다. 생성자가
호출되면 User Agent는 다음 절차를 실행해야 합니다:
stream을 새롭게 생성된 MediaStream
객체로 둡니다.
stream.id
속성을 새로 생성된 값으로 초기화합니다.
생성자 인자가 존재한다면, 다음 절차를 실행합니다:
인자 타입에 따라 트랙 집합 tracks를 생성합니다:
MediaStream
객체인 경우:
tracks는 해당 MediaStreamTrack
객체들이
모두 포함된 MediaStream
의 트랙 집합입니다.
MediaStreamTrack
객체
시퀀스인 경우:
tracks는 제공된 시퀀스의 모든 MediaStreamTrack
객체들을
포함하는 집합입니다.
tracks 내의 각 MediaStreamTrack
track에 대해 다음 절차를 실행합니다:
stream을 반환합니다.
MediaStream
의 트랙들은 트랙
집합에 저장됩니다. 트랙 집합은 MediaStreamTrack
객체들을 반드시 포함해야 하며, 트랙의 상대적 순서는
User Agent가 정의하며 API에서는 순서에 대해 어떠한 요구사항도 없습니다. 특정 MediaStreamTrack
객체를 집합에서 찾는 올바른 방법은 그 id
로 조회하는 것입니다.
MediaStream
의 출력을 읽는 객체를 MediaStream
소비자라고 합니다. 현재 MediaStream
소비자 목록에는 미디어
요소(video
및
audio
)
[HTML], 웹 실시간 통신(WebRTC; RTCPeerConnection
)
[WEBRTC], 미디어 녹화(MediaRecorder
) [mediastream-recording], 이미지 캡처(ImageCapture
) [image-capture], 그리고 웹 오디오
(MediaStreamAudioSourceNode
)
[WEBAUDIO] 등이 포함됩니다.
MediaStream
소비자는 트랙 추가 및 제거를 처리할 수 있어야 합니다. 이
동작은 소비자별로 명세되어 있습니다.
MediaStream
객체는 하나 이상의 MediaStreamTrack
이 ended 상태가 아니라면 활성 상태라고 합니다. 트랙이 없거나 모든 트랙이 ended 상태인 MediaStream
은 비활성 상태입니다.
MediaStream
객체는 하나 이상의 MediaStreamTrack
의 [[Kind]]
가 "audio"
이고 ended 상태가 아닌 경우 청취 가능 상태라고 합니다. 오디오 트랙이 없거나 모든 오디오 트랙이
ended 상태인 MediaStream
은 청취 불가 상태입니다.
User Agent는 외부 이벤트 등에 대응하여 MediaStream
의 트랙 집합을 갱신할 수 있습니다. 이
명세서에서는 이런 경우를 명시하지 않지만, MediaStream API를 사용하는 다른 명세서에서는 명시될 수 있습니다. 예를 들어 WebRTC 1.0 [WEBRTC]에서는, 다른 피어로부터 받은 MediaStream
의 트랙 집합이 미디어 세션 변경에 따라 갱신될
수 있습니다.
트랙 추가 track을 MediaStream
stream에 추가하려면, User Agent는 다음 절차를 반드시 실행해야 합니다:
트랙 제거
track을 MediaStream
stream에서
제거하려면, User Agent는 다음 절차를 반드시 실행해야 합니다:
track이 stream의 트랙 집합에 없으면 절차를 중단합니다.
트랙 이벤트 removetrack
를 track
및 stream에 대해 발생시킵니다.
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
;
};
MediaStream
MediaStream 생성자 알고리즘을 참조하세요.
MediaStream
MediaStream 생성자 알고리즘을 참조하세요.
MediaStream
MediaStream 생성자 알고리즘을 참조하세요.
id
of type DOMString
,
readonlyid
속성은 객체가 생성될 때 초기화된 값을 반드시 반환해야 합니다.
MediaStream
이 생성되면
User Agent는 식별자 문자열을 생성하고, 객체의 id
속성을 해당 문자열로 반드시 초기화해야 합니다. 단,
특수 목적 알고리즘에 따라 스트림 id 초기화 방법이 지정된 경우는 제외합니다. 좋은 관행으로는 UUID [rfc4122]를
사용하는 것이며, 표준 형식에서는 36자입니다. 지문 채취를 방지하기 위해 구현체는 UUID 생성 시 RFC 4122 4.4 또는 4.5 섹션의 형식을
사용하는 것이 좋습니다.
스트림 id 초기화 방법을 명시하는 알고리즘의 예는, 네트워크 컴포넌트를 MediaStream
객체와 연결하는 알고리즘입니다.
[WEBRTC]
active
of type boolean
, readonly
active
속성은 이 MediaStream
이 활성 상태라면 true
, 아니면 false
를
반드시 반환해야 합니다.
onaddtrack
of type EventHandler
이 이벤트 핸들러의 이벤트 타입은 addtrack
입니다.
onremovetrack
of type EventHandler
이 이벤트 핸들러의 이벤트 타입은 removetrack
입니다.
getAudioTracks()
이 스트림의 오디오 트랙을 나타내는 MediaStreamTrack
객체 시퀀스를
반환합니다.
getAudioTracks
메서드는
반드시 해당 스트림의 트랙 집합 중 [[Kind]]
가 "audio"
인 모든 MediaStreamTrack
객체의 스냅샷을 나타내는
시퀀스를 반환해야 합니다. 트랙 집합에서 시퀀스로의 변환은 User Agent가
정의하며, 호출마다 순서가 고정될 필요는 없습니다.
getVideoTracks()
이 스트림의 비디오 트랙을 나타내는 MediaStreamTrack
객체 시퀀스를
반환합니다.
getVideoTracks
메서드는
반드시 해당 스트림의 트랙 집합 중 [[Kind]]
가 "video"
인 모든 MediaStreamTrack
객체의 스냅샷을 나타내는
시퀀스를 반환해야 합니다. 트랙 집합에서 시퀀스로의 변환은 User Agent가
정의하며, 호출마다 순서가 고정될 필요는 없습니다.
getTracks()
이 스트림의 모든 트랙을 나타내는 MediaStreamTrack
객체 시퀀스를
반환합니다.
getTracks
메서드는 반드시 해당 스트림의
트랙 집합의 모든 MediaStreamTrack
객체의 스냅샷을 반환해야
하며, [[Kind]]
값에 관계없이 반환합니다.
트랙 집합에서 시퀀스로의 변환은 User Agent가 정의하며, 호출마다 순서가 고정될
필요는 없습니다.
getTrackById()
getTrackById
메서드는 해당
스트림의 트랙 집합 중 [[Id]]
가 trackId와 같은 MediaStreamTrack
객체를 반환하거나, 해당
트랙이 없으면 null
을 반환해야 합니다.
addTrack()
지정한 MediaStreamTrack
을 이 MediaStream
에
추가합니다.
addTrack
메서드가 호출되면, User Agent는 반드시 다음 절차를 실행해야 합니다:
메서드 인자를 track으로, 메서드가 호출된 MediaStream
객체를
stream으로 둡니다.
track이 이미 stream의 트랙 집합에 있으면 절차를 중단합니다.
removeTrack()
지정한 MediaStreamTrack
객체를 이 MediaStream
에서
제거합니다.
removeTrack
메서드가 호출되면,
User Agent는 반드시 다음 절차를 실행해야 합니다:
메서드 인자를 track으로, 메서드가 호출된 MediaStream
객체를
stream으로 둡니다.
track이 stream의 트랙 집합에 없으면 절차를 중단합니다.
clone()
지정된 MediaStream
과 모든
트랙을 복제합니다.
clone
()
메서드가 호출되면
User Agent는 반드시 다음 절차를 실행해야 합니다:
streamClone을 새롭게 생성된 MediaStream
객체로 둡니다.
streamClone.MediaStream
.id
를 새로 생성된 값으로 초기화합니다.
이 MediaStream
객체의 각 트랙을 복제하여
streamClone의 트랙 집합에 추가합니다.
addtrack 또는 removetrack 이벤트를 발생시킬 것으로 예상하는 User Agent 코드는 대상 MediaStream
객체를 다른 객체에서 참조함으로써 반드시 생존시켜야
합니다.
addtrack 또는 removetrack 이벤트 리스너의 존재는 MediaStream
객체를 가비지 컬렉트할 때 반드시 고려할 필요는
없습니다.
MediaStreamTrack
MediaStreamTrack
객체는 User Agent 내의 미디어 소스를 나타냅니다. 예시 소스는 User Agent에 연결된 장치입니다. 다른 명세는 여기서 지정된 동작을 재정의하는 MediaStreamTrack
의 소스를 정의할 수 있습니다. 여러 MediaStreamTrack
객체들이 동일한 미디어 소스를 나타낼 수 있으며,
예를 들어 사용자가 연속적으로 두 번 getUserMedia
()
를 호출할 때 같은
카메라를 UI에서 선택한 경우입니다.
MediaStreamTrack
소스는 다음 속성을 정의합니다:
MediaStreamTrack
또는 MediaStreamTrack
의 서브타입으로 설정됩니다.
기본값은 MediaStreamTrack
입니다.
MediaStreamTrack
를 생성할
때 실행됩니다.
이 단계는 새로 생성된 MediaStreamTrack
를 입력으로
받습니다. 기본값은 빈 단계입니다.MediaStreamTrack
을 복제할
때 실행됩니다.
이 단계는 소스와 대상 MediaStreamTrack
들을
입력으로 받습니다. 기본값은 빈 단계입니다.MediaStreamTrack
객체의 데이터는 반드시 표준 바이너리 형식을 가질
필요는 없습니다; 예를 들어, 그냥 "사용자의 비디오 카메라에서 현재 들어오는 비디오"일 수 있습니다. 이렇게 하면 User Agent는 사용자 플랫폼에
가장 적합한 방식으로 미디어를 처리할 수 있습니다.
스크립트는 MediaStreamTrack
객체가 더 이상 소스를 필요로 하지 않을 때 stop
()
메서드를 사용할 수 있습니다. 소스를
사용하는 모든 트랙이 중지되거나 다른 방법으로 종료되면, 소스는 중지됨 상태가 됩니다. 만약 소스가 getUserMedia
()
로 노출되는
장치라면, 소스가 중지될 때 User Agent는 반드시 다음 절차를 실행해야 합니다:
mediaDevices를 해당 MediaDevices
객체로 둡니다.
deviceId를 소스 장치의 deviceId
로
둡니다.
mediaDevices.[[devicesLiveMap]]
[deviceId]를
false
로 설정합니다.
장치의 kind와 deviceId에 대한 권한의 permission state가
mediaDevices의 관련 설정
객체에 대해
"granted
"가
아니면,
mediaDevices.[[devicesAccessibleMap]]
[deviceId]를
false
로 설정합니다.
MediaStreamTrack 생성을 하려면, 기반 source와 mediaDevicesToTieSourceTo를 이용하여 다음 절차를 실행합니다:
track을 source의 MediaStreamTrack 소스 타입의 새 객체로 둡니다.
track을 다음 내부 슬롯 값으로 초기화합니다:
[[Source]], source로 초기화됨.
[[Id]],
새로 생성된 고유 식별자 문자열로 초기화됨. 이런 식별자 생성 방법은 MediaStream
.id
속성 가이드라인을 참고하세요.
[[Kind]],
source가 오디오 소스면 "audio"
, 비디오 소스면 "video"
로
초기화됨.
[[Label]],
User Agent가 제공하면 source의 레이블로, 없으면 ""
로 초기화됨. User Agent는 "내장 마이크", "외장 USB 웹캠"과 같이 오디오/비디오 소스에
레이블을 MAY 지정할 수 있습니다.
[[ReadyState]],
"live
"로 초기화됨.
[[Enabled]],
true
로 초기화됨.
[[Muted]],
source가 muted 상태면 true
, 아니면
false
로 초기화됨.
ConstrainablePattern
에 따라 초기화됨.
[[Restrictable]], false
로 초기화됨.
mediaDevicesToTieSourceTo가 null
이 아니면,
트랙 소스를
MediaDevices
에 연결합니다. 인자는 source,
mediaDevicesToTieSourceTo입니다.
source의 MediaStreamTrack 소스별 생성 단계를 track을 인자로 실행합니다.
track을 반환합니다.
기반 소스 초기화를 하려면, track의 기반을 source로 설정하여 다음 절차를 실행합니다:
track.[[Source]]
를
source로 초기화합니다.
track의 [[Capabilities]],
[[Constraints]], 그리고
[[Settings]]를
ConstrainablePattern
에 따라 초기화합니다.
트랙 소스를 MediaDevices
에 연결하려면,
source와 mediaDevices를 이용해 다음 절차를 실행합니다:
source를 mediaDevices.[[mediaStreamTrackSources]]
에
추가합니다.
모든 소스 중지를 global object globalObject에 대해 하려면, User Agent는 반드시 다음 절차를 실행해야 합니다:
globalObject의 MediaStreamTrack
객체 track
각각에 대해,
관련 global object가
globalObject라면,
track의 [[ReadyState]]
를
"ended
"로 설정합니다.
globalObject가 Window
라면,
globalObject의 연결된
MediaDevices
.[[mediaStreamTrackSources]]
의 각
source에 대해,
중지합니다.
User Agent는 다음 조건에서 globalObject의 모든 소스 중지를 반드시 실행해야 합니다:
globalObject가 Window
객체이고,
문서
언로드 정리 단계가
해당 연결된
문서에 대해 실행되는 경우.
globalObject가 WorkerGlobalScope
객체이고,
그 closing
플래그가 true로 설정된 경우.
구현은 소스 사용 추적을 위해 소스별 참조 카운트를 사용할 수 있지만, 구체적인 사항은 이 명세의 범위 밖입니다.
트랙 복제를 하려면 User Agent는 반드시 다음 절차를 실행해야 합니다:
track을 복제할 MediaStreamTrack
객체로 둡니다.
source를 track의 [[Source]]
로 둡니다.
trackClone을 MediaStreamTrack 생성 결과로 얻으며, 인자는
source와 null
입니다.
trackClone의 [[ReadyState]]
를 track의 [[ReadyState]]
값으로 설정합니다.
trackClone의 [[Capabilities]]를 track의 [[Capabilities]] 복제로 설정합니다.
trackClone의 [[Constraints]]를 track의 [[Constraints]] 복제로 설정합니다.
trackClone의 [[Settings]]를 track의 [[Settings]] 복제로 설정합니다.
source의 MediaStreamTrack 소스별 복제 단계를 track과 trackClone을 인자로 실행합니다.
trackClone을 반환합니다.
"live
" MediaStreamTrack
에
대해,
미디어 흐름과 관련된 두 가지 차원이 있습니다: 음소거됨/음소거되지 않음, 그리고 활성화됨/비활성화됨입니다.
음소거됨은 MediaStreamTrack
의 입력을 의미합니다.
MediaStreamTrack
이
자신의 소스가 음소거됨 상태일 때,
즉 트랙에 데이터를 일시적으로 제공할 수 없을 때 음소거됨 상태가 됩니다.
실시간 샘플은 MediaStreamTrack
이 음소거됨 상태일 때 제공되어서는 안 됩니다.
음소거됨 상태는 웹 애플리케이션에서 제어할 수 없지만,
muted
속성을 읽거나
mute
및 unmute
이벤트를 수신함으로써 관찰할 수 있습니다.
MediaStreamTrack
이
음소거됨 상태가 되는 이유는
해당 소스에 의해 정의됩니다.
카메라와 마이크 소스의 경우, 음소거 사유는 구현 정의입니다. 이는 사용자 에이전트가 프라이버시 보호를 구현할 수 있도록 합니다. 예를 들어, 사용자가 물리적 마이크 음소거 버튼을 누르거나, 내장 카메라가 있는 노트북 뚜껑을 닫거나, 운영 체제에서 컨트롤을 토글하거나, User Agent 크롬에서 음소거 버튼을 클릭하거나, User Agent가 사용자를 대신해 음소거하는 상황 등입니다.
일부 운영체제에서는 마이크 접근 권한이 User Agent에서 다른 고음질 우선권이 있는 애플리케이션으로
넘어갈 수 있습니다.
예를 들어, 모바일 OS에서 전화가 올 때 등이 해당합니다.
User Agent는 이러한 정보를
muted
속성과 관련 이벤트를 통해
웹 애플리케이션에 제공해야 합니다.
User Agent가 카메라 또는 마이크 소스에 대해 이러한 구현 정의 변화를 시작하면, 반드시 사용자 상호작용 태스크 소스를 사용해 트랙의 음소거 상태를 설정하는 태스크를 큐에 넣어야 합니다.
트랙의 음소거 상태 설정 을 newState로 할 때, User Agent는 반드시 다음 절차를 실행해야 합니다:
track을 해당 MediaStreamTrack
로 둡니다.
만약 track.[[Muted]]
가 이미
newState라면, 절차를 중단합니다.
track.[[Muted]]
를
newState로 설정합니다.
이벤트를 발생시킵니다. 이름은 eventName이고, 대상은 track입니다.
활성화/비활성화는 반대로,
애플리케이션이 enabled
속성을 통해 직접 제어(및 관찰)할 수
있습니다.
소비자 입장에서는 MediaStreamTrack
이
음소거되거나 비활성화된(혹은 둘 다) 경우
소비자는 정보가 없는 상태(오디오엔 무음, 비디오엔 검은 프레임)를 받습니다. 즉, 소스의 미디어는 MediaStreamTrack
이 음소거되지 않고 활성화되어 있을 때만
흐릅니다.
예를 들어, 오디오와 비디오가 모두 음소거되거나 비활성화된 MediaStream
만을 소스로 하는 비디오 요소는
재생은 되지만, 검은 비디오 프레임만 표시되며 무음 상태가 됩니다.
새로 생성된 MediaStreamTrack
객체의 경우,
별도의 명시가 없는 한 항상 활성화된 상태이며(예: 복제 시 제외),
음소거 상태는 트랙이 생성될 당시 소스 상태를 반영합니다.
MediaStreamTrack
은
생명주기에서 두 가지 상태를 가집니다: live와 ended.
새로 생성된 MediaStreamTrack
은
생성 방식에 따라 두 상태 중 하나일 수 있습니다.
예를 들어, 종료된 트랙을 복제하면 새 트랙도 종료된 상태가 됩니다.
현재 상태는 객체의 readyState
속성에 반영됩니다.
live 상태에서는 트랙이 활성이고,
(트랙이 MediaStreamTrack
이
음소거됨 또는 비활성화됨 상태라면 정보 없음)
소비자에게 미디어가 제공됩니다.
소스가 navigator.mediaDevices.
getUserMedia
()
로
노출되는 장치라면,
트랙이 음소거되거나 비활성화되어 해당 장치에 연결된 모든 트랙이 음소거, 비활성화 또는 중지된 경우,
UA는 선택적으로 deviceId
를
사용해
navigator.mediaDevices.
[[devicesLiveMap]]
[deviceId]를
false
로 설정할 수 있습니다.
단, 이 장치에 연결된 중지되지 않은 트랙이 음소거 해제 또는 활성화되면 즉시 true
로 돌려놔야 합니다.
"live
", 음소거되지 않음 및
활성화됨 상태의 트랙이 getUserMedia
()
로
노출되는 장치에서
음소거되거나 비활성화되고, 이로 인해 해당 장치에 연결된 모든 트랙(UA가 관리하는 모든 navigable에서)이
모두 음소거, 비활성화 또는 중지된 경우, UA는 가능하면 3초 이내에 사용자가 전환을 인지할 수 있는 합리적 시간을 둔 후
장치
반환을 해야 합니다.
UA는 장치에서 live 트랙이 다시 음소거 해제되고 활성화되면 즉시 장치를 다시 얻으려고 해야 하며,
그 트랙의 관련
global object의 연결된
Document
가
그 시점에 뷰에 있음이어야 합니다.
문서가 그 시점에 뷰에 있지 않으면,
UA는 해당 트랙을 음소거하는 태스크를 큐에 넣고, 문서가 뷰에 들어올 때까지
음소거 해제 태스크는 큐에 넣지 않아야 합니다.
장치 재획득에 실패하면, UA는 반드시 트랙 종료를 해야 합니다(장치 문제를 감지해 더 일찍 종료할 수도 있습니다).
사용자가 실제 카메라(및 마이크) 하드웨어의 물리적 램프가 꺼지는 것을 통해 프라이버시가 보장된다고 느끼도록, 물리적·논리적 “프라이버시 인디케이터”를 일치시키는 것이 목적입니다(최소한 해당 장치의 유일한 사용자인 경우).
동시에 해당 장치를 사용하는 다른 애플리케이션이나 문서가 있을 경우 이 의도가 간혹 방해받을 수 있으나, 이 명세에서 제시한 규칙에는 영향을 주지 않습니다.
MediaStreamTrack
객체는
소스가 연결 해제되거나 소진될 때 종료됨 상태가 됩니다.
동일한 소스를 사용하는 모든 MediaStreamTrack
이
종료됨 상태가 되면, 소스는 중지됨 상태가 됩니다.
애플리케이션이 stop
()
메서드를 호출했거나,
소스가 트랙에 실시간 샘플을 영구적으로 제공하지 않게 된 경우(둘 중 빠른 쪽),
MediaStreamTrack
은
종료됨 상태가 됩니다.
카메라와 마이크 소스의 경우,
stop
()
외에
소스가 종료되는 사유는
구현
정의입니다(예: 사용자가 페이지에 대한 권한을 취소하거나, UA가 어떤 이유로든 트랙 종료를 지시한 경우 등).
MediaStreamTrack
track이
stop() 메서드 호출 이외의 이유로 종료된 경우,
User Agent는 반드시 다음 절차를 큐에 넣어 실행해야 합니다:
track의 [[ReadyState]]
값이 이미
"ended
"라면,
절차를 중단합니다.
track의 [[ReadyState]]
를
"ended
"로 설정합니다.
track의 [[Source]]
에 track이
종료됨 상태임을 알리고,
해당 소스가 중지됨 상태가 될 수 있도록 해야 합니다(다른 MediaStreamTrack
객체가 의존하는 경우는
제외).
트랙이 사용자 요청으로 종료된 경우, 이 이벤트의 소스는 사용자 상호작용 이벤트 소스입니다.
장치 권한 철회 알고리즘을 permissionName으로 호출하려면, 다음 절차를 실행합니다:
tracks를 현재 "live
" 상태이고,
해당 트랙 종류("camera"
또는 "microphone"
)의 권한이
permissionName과 일치하는
MediaStreamTrack
집합으로 둡니다.
tracks의 각 track에 대하여, 종료합니다.
MediaStreamTrack
는 제약 가능 객체이며, 제약 가능
패턴 섹션에서 정의됩니다.
제약조건은 트랙에 설정되며, 소스에 영향을 줄 수 있습니다.
트랙 초기화 시
가 제공되었든 나중에 런타임에 설정되어야 하든,
Constraints
ConstrainablePattern
인터페이스에서 정의된 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
of type DOMString
,
readonlyid
of type DOMString
,
readonlylabel
of type DOMString
,
readonlyenabled
of type boolean
enabled
속성은 이 객체의 활성화 상태를 제어합니다.
조회 시,
this.[[Enabled]]
반드시 반환되어야 합니다.
설정 시,
this.[[Enabled]]
반드시 새 값으로 설정되어야 합니다.
따라서,
MediaStreamTrack
가
종료된 후에도 enabled
속성 값은 변경될 수 있지만, 해당 값에 대해 아무 동작도 하지 않습니다.
muted
of type boolean
,
readonlymuted
속성은
트랙이 음소거됨 상태인지 반영합니다.
반드시
this.[[Muted]]
값을 반환해야
합니다.
onmute
of type EventHandler
이 이벤트 핸들러의 이벤트 타입은 mute입니다.
onunmute
of type EventHandler
이 이벤트 핸들러의 이벤트 타입은 unmute입니다.
readyState
of type
MediaStreamTrackState
,
readonly
조회 시, readyState
속성은
반드시
this.[[ReadyState]]
값을 반환해야 합니다.
onended
of type EventHandler
이 이벤트 핸들러의 이벤트 타입은 ended입니다.
clone
clone
()
메서드가 호출되면,
User Agent는
반드시 트랙 복제 결과를 반환해야 합니다. 인자는 this입니다.
stop
MediaStreamTrack
객체의
stop
()
메서드가 호출되면, User Agent는 반드시 다음 절차를 실행해야 합니다:
track을 현재 MediaStreamTrack
객체로 둡니다.
track의 [[ReadyState]]
값이 "ended
"이면,
절차를 중단합니다.
track의 소스에 track이 종료됨임을 알립니다.
트랙 종료를 통보 받은 소스는
중지됨 상태가 되며,
다른 MediaStreamTrack
객체가 의존하는 경우는 제외됩니다.
track의 [[ReadyState]]
를 "ended
"로
설정합니다.
getCapabilities
이 MediaStreamTrack
가 나타내는 소스의
capability를 반환합니다.
제약 가능 객체입니다.
이 메서드의 정의는 ConstrainablePattern 인터페이스를 참조하세요.
이 메서드는 기반 장치에 대한 교차 출처, 지속적 정보(지문)를 제공하므로 fingerprint surface를
추가합니다.
getConstraints
이 메서드의 정의는 ConstrainablePattern 인터페이스를 참조하세요.
getSettings
MediaStreamTrack
객체의
MediaStreamTrack
.getSettings
()
메서드가 호출되면,
User Agent는 반드시 다음 절차를 실행해야 합니다:
track을 현재 MediaStreamTrack
객체로 둡니다.
track의 [[ReadyState]]
값이 "ended
"이면,
다음 하위 절차를 실행합니다:
settings를 MediaTrackSettings
딕셔너리의 새 인스턴스로 둡니다.
고유 제약 가능한 트랙 속성 목록의 각 property에 대해, track이 종료될 당시 해당 속성을 가지고 있었다면, settings에 종료 당시 값을 추가합니다.
settings를 반환합니다.
트랙의 현재 설정값을 ConstrainablePattern 인터페이스 정의대로 반환합니다.
applyConstraints
MediaStreamTrack
객체의
applyConstraints
()
메서드가 호출되면, User Agent는 반드시 다음 절차를 실행해야 합니다:
track을 현재 MediaStreamTrack
객체로 둡니다.
track의 [[ReadyState]]
값이 "ended
"이면,
다음 하위 절차를 실행합니다:
p를 새 프로미스로 둡니다.
resolve
p를 undefined
로 합니다.
p를 반환합니다.
applyConstraints 템플릿 메서드 결과를 호출 및 반환합니다:
MediaStreamTrack
이고,
MediaTrackSettings
딕셔너리의 인스턴스일 수 있습니다. User Agent는
고유 변경 불가 장치 속성은 고유
제약 가능한 트랙 속성 목록에 포함된 경우를 제외하고 멤버로 추가하면 안 됩니다. 또는 노출되어서는 안 됨
속성도 포함하면 안 됩니다.
다른 명세는 특정 시점에 노출되어서는 안 됨 제약 가능한 속성을 정의할 수 있습니다.
모든 settings 딕셔너리에서 resizeMode가 "none"이면, User Agent는 반드시 동일한 settings 딕셔너리를 resizeMode가 "crop-and-scale"로 설정하여 추가해야 합니다. 비네이티브 모드로 제약하는 것은 지원하지 않습니다.
실질적으로 crop-and-scale이 none의 상위집합임을 반영합니다.
WebIDLenum MediaStreamTrackState
{
"live
",
"ended
"
};
Enum value | 설명 |
---|---|
live |
트랙이 활성 상태입니다(트랙의 기반 미디어 소스가 실시간 데이터 제공을 최대로 시도 중). |
ended |
트랙이 종료됨 상태입니다(트랙의 기반 미디어 소스가 더 이상 데이터를 제공하지 않으며, 이 트랙에 대해 더 이상 데이터를 제공하지 않습니다). 트랙이 이 상태에 들어가면 다시는 빠져나오지 않습니다. 예를 들어, |
MediaTrackSupportedConstraints
는 MediaStreamTrack
객체의
Capabilities를 제어하기 위해 User Agent가 인식하는
제약조건 목록을 나타냅니다.
이 딕셔너리는 함수 반환값으로 사용되며, 연산 인자로 사용되지 않습니다.
향후 명세는 MediaTrackSupportedConstraints
딕셔너리를 partial dictionary와 boolean 타입의 멤버로 확장할 수 있습니다.
이 명세에서 정의된 제약조건은 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
객체의 Capabilities를 나타냅니다.
향후 명세는 적절한 타입의 멤버를 갖는 partial dictionary로 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
는 DOMString
타입이며,
의
ConstrainablePattern
Capabilities
에서
기대하는 sequence<DOMString>
이 아닙니다.
MediaTrackCapabilities
멤버width
타입 ULongRange
height
타입 ULongRange
aspectRatio
타입 DoubleRange
frameRate
타입 DoubleRange
facingMode
타입
sequence<DOMString
>
카메라는 여러 facing mode를 보고할 수 있습니다. 예를 들어, 여러 대의 카메라가 사용자 쪽을 보는 고급 텔레프레즌스 솔루션에서는, 사용자
왼쪽에 있는 카메라는 "left"(left
)와 "user"(user
)를 모두 보고할 수
있습니다. 추가 내용은 facingMode 참고.
resizeMode
of type
sequence<DOMString
>
User Agent는 선택적으로
크롭과 다운스케일을 사용하여 카메라가 자연스럽게 생성하는 것보다 더 다양한 해상도 옵션을 제공할 수 있습니다.
보고되는 시퀀스에는 UA가 이 카메라에 대해 해상도 옵션을 파생할 수 있는 모든 수단이 반드시 포함되어야
합니다. "none
" 값이 반드시
포함되어야 하며,
이는 UA가 크롭 및 다운스케일을 하지 않도록 제한할 수 있음을 의미합니다. 자세한 내용은 resizeMode를 참조하세요.
sampleRate
of type ULongRange
sampleSize
of type ULongRange
echoCancellation
of type
sequence<boolean
>
소스가 에코 캔슬링을 지원하지 않으면 리스트에 false
만 반드시 포함됩니다. 소스가
에코 캔슬링을 지원한다면 true
가 반드시 포함되어야 합니다. 스크립트가 기능을
제어할 수 있다면 리스트에 반드시 true
와 false
모두가 포함되어야 합니다.
또한, 소스가 어떤 오디오 소스를 캔슬링할지 제어할 수 있다면, EchoCancellationModeEnum
열거형의 지원 값도 포함되어야 하며, true
또는 false
가 포함되면 반드시 EchoCancellationModeEnum
값들보다 앞에 와야 합니다.
자세한 내용은 echoCancellation을 참조하세요.
autoGainControl
of type
sequence<boolean
>
소스가 자동 이득 제어를 지원하지 않으면 false
만 반환합니다. 자동 이득 제어를 끌 수 없다면
true
만 반환합니다. 스크립트가 기능을 제어할 수 있다면 true
와 false
모두 가능한 값으로 리스트에 포함됩니다. 자세한 내용은 autoGainControl을 참조하세요.
noiseSuppression
of type
sequence<boolean
>
소스가 노이즈 억제를 지원하지 않으면 false
만 반환합니다. 노이즈 억제를 끌 수 없다면 true
만
반환합니다. 스크립트가 기능을 제어할 수 있다면 true
와 false
모두 가능한 값으로 리스트에
포함됩니다. 자세한 내용은 noiseSuppression을
참조하세요.
latency
of type DoubleRange
channelCount
of type ULongRange
deviceId
of type DOMString
groupId
of type DOMString
backgroundBlur
of type
sequence<boolean
>
false
만 반환합니다. 배경 흐림 효과를 끌 수 없으면 true
만
반환합니다. 스크립트가 기능을 제어할 수 있다면 true
와 false
모두 값으로 포함됩니다. 자세한 내용은
backgroundBlur를 참조하세요.
WebIDLdictionary MediaTrackConstraints
: MediaTrackConstraintSet
{
sequence<MediaTrackConstraintSet
> advanced
;
};
MediaTrackConstraints
멤버advanced
타입
sequence<MediaTrackConstraintSet
>
이 요소의 정의는 Constraints와 ConstraintSet을 참고하세요.
향후 명세는
MediaTrackConstraintSet
딕셔너리를 partial dictionary와 적절한
타입의 멤버로 확장할 수 있습니다.
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
타입 ConstrainULong
height
타입 ConstrainULong
aspectRatio
타입 ConstrainDouble
frameRate
타입 ConstrainDouble
facingMode
타입 ConstrainDOMString
resizeMode
타입 ConstrainDOMString
sampleRate
타입 ConstrainULong
sampleSize
타입 ConstrainULong
echoCancellation
타입 ConstrainBooleanOrDOMString
autoGainControl
타입 ConstrainBoolean
noiseSuppression
타입 ConstrainBoolean
latency
타입 ConstrainDouble
channelCount
타입 ConstrainULong
deviceId
타입 ConstrainDOMString
groupId
타입 ConstrainDOMString
backgroundBlur
타입 ConstrainBoolean
MediaTrackSettings
는 설정값을 나타내며, MediaStreamTrack
객체에 대한 설정값을 제공합니다.
향후 명세는 MediaTrackSettings 딕셔너리를 partial dictionary와 적절한 타입의 멤버로 확장할 수 있습니다.
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
타입 double
frameRate
타입 double
facingMode
타입 DOMString
resizeMode
타입 DOMString
sampleRate
타입 unsigned long
sampleSize
타입 unsigned long
echoCancellation
타입 boolean
또는 DOMString
autoGainControl
타입 boolean
noiseSuppression
타입 boolean
latency
타입
double
channelCount
타입 unsigned long
deviceId
타입 DOMString
groupId
타입 DOMString
backgroundBlur
타입 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
|
픽셀 단위의 너비. capability일 때, 유효 범위는 비디오 소스의 사전 설정 너비 값 전체이며, min은 1이고 max는 가장 큰 너비입니다. User Agent는 반드시 최소 너비와 네이티브 해상도 너비 사이의 모든 값에 대해 다운샘플링을 지원해야 합니다. |
height | unsigned long
|
픽셀 단위의 높이. capability일 때, 유효 범위는 비디오 소스의 사전 설정 높이 값 전체이며, min은 1이고 max는 가장 큰 높이입니다. User Agent는 반드시 최소 높이와 네이티브 해상도 높이 사이의 모든 값에 대해 다운샘플링을 지원해야 합니다. |
frameRate | double |
초당 프레임 수(frame rate). 비디오 소스의 사전 설정에서 프레임률을 결정할 수 있다면 capability로서 유효 범위는 소스의 사전 설정 프레임률 값 전체이며, min은 0, max는 가장 큰 프레임률입니다. User Agent는 반드시 네이티브 해상도 프레임률의 정수 decimation으로 얻은 프레임률을 지원해야 합니다. 프레임률을 결정할 수 없으면(예: 소스가 네이티브로 프레임률을 제공하지 않거나, 프레임률을 소스 스트림에서 결정할 수 없는 경우), capability 값은 반드시 User Agent의 vsync 디스플레이 프레임률을 참조해야 합니다. 설정값으로서 이 값은 구성된 프레임률을 나타냅니다. decimation이 사용되면 네이티브 프레임률이 아닌 그 값이 됩니다. 예를 들어,
decimation으로 25fps로 설정되었고, 카메라의 네이티브 프레임률이 30fps인데 조명 조건 때문에 실제로 20fps만 나오는 경우, |
aspectRatio | double |
정확한 종횡비(픽셀 단위 너비/높이, 소수점 10자리까지 반올림된 double) 혹은 종횡비 범위입니다. |
facingMode | DOMString |
이 문자열은 VideoFacingModeEnum 멤버 중
하나입니다.
멤버들은 카메라가 사용자의 관점에서 볼 때 어느 방향을 보는지 설명합니다.
가
열거형에 없는 문자열에 대해서는
정확히 같은 문자열을 반환하지 않을 수 있습니다. 이는 향후 WebIDL enum이 해당 속성에 사용될 가능성을 남겨둡니다.
|
resizeMode | DOMString |
이 문자열은 VideoResizeModeEnum 멤버 중
하나입니다.
멤버들은 UA가 해상도를 어떻게 도출할 수 있는지 설명합니다. 즉, UA가 카메라 출력에 크롭과 다운스케일을 사용할 수 있는지 여부입니다.
UA는 선택적으로 다른 애플리케이션에서 카메라를 동시에 사용할 때,
다운스케일, 업스케일, 크로핑 등을 통해 "none" 사용 시 네이티브 해상도를 흉내낼 수 있습니다. 단, 이는 카메라가 User Agent 외부 애플리케이션에서 사용 중일 때만 가능합니다. 가
열거형에 없는 문자열에 대해 정확히 같은 문자열을 반환하지 않을 수 있습니다. 이는 향후 WebIDL enum이 해당 속성에 사용될 가능성을 남겨둡니다.
|
backgroundBlur | boolean |
일부 플랫폼이나 User Agent는 비디오 프레임(특히 카메라 비디오 스트림)에 대해 내장 배경 흐림 기능을 제공할 수 있습니다. 웹 애플리케이션은 배경 흐림이 소스 수준에서 적용되는지 제어하거나 인지하고 싶을 수 있습니다. 예를 들어, 웹 애플리케이션이 UI를 업데이트하거나 자체적으로 배경 흐림을 적용하지 않도록 할 수 있습니다. |
환경 변화에 따라 캡처된 비디오의 X, Y 축을 자동으로 뒤집는 것이 바람직한 시스템에서는, width
, height
, aspectRatio
제약과 capability는 모든 알고리즘에서 반드시 영향받지 않아야 하며, 기본 방향만 고려해야 합니다. 단, getSettings
()
알고리즘에서는 이 제약 속성의 설정값이 캡처된 비디오의 반환 차원과 일치하도록 필요시 뒤집어야 합니다.
기본 방향은 캡처된 비디오의 X, Y 축을 뒤집을 수 있는 시스템에서 특정 시스템에 대해 User Agent가 정의합니다.
자동으로 가로/세로 모드를 전환하는 시스템에서는, User Agent는 가로 모드를 기본 방향으로 만드는 것이 권장됩니다.
WebIDLenum VideoFacingModeEnum
{
"user
",
"environment
",
"left
",
"right
"
};
열거형 값 | 설명 |
---|---|
user |
소스가 사용자(셀프뷰 카메라) 쪽을 향함. |
environment |
소스가 사용자와 반대 방향(환경을 보는 방향)을 향함. |
left |
소스가 사용자의 왼쪽을 향함. |
right |
소스가 사용자의 오른쪽을 향함. |
아래는 사용자와의 관계에서 비디오 facing 모드를 설명합니다.
WebIDLenum VideoResizeModeEnum
{
"none
",
"crop-and-scale
"
};
열거형 값 | 설명 |
---|---|
none |
해상도와 프레임률은 카메라, 드라이버, OS에 의해 제공됩니다. 참고: UA는 선택적으로 동시 사용을 위장하기 위해 이 값을
보고할 수 있지만, 이는 카메라가 다른 navigable에서
사용 중일 때만 가능합니다. |
crop-and-scale |
해상도가 UA에 의해 더 높은 카메라 해상도에서 다운스케일되거나 크롭되었거나, 프레임률이 UA에 의해 decimation된 경우입니다. 미디어는 입력 소스에서 발생하지 않은 업스케일, 확대, 가짜 데이터 생성이 절대 허용되지 않습니다 (아래 예외 제외). 참고: UA는 선택적으로 동시 사용을 위장하기 위해 업스케일할 수
있지만, 이는 카메라가 UA 외부 애플리케이션에서 사용 중일 때만 가능합니다. |
다음 제약 가능한 속성들은 오디오 MediaStreamTrack
객체에만
적용됩니다:
속성 이름 | 값 | 설명 |
---|---|---|
sampleRate | unsigned long
|
오디오 데이터의 초당 샘플 수. |
sampleSize | unsigned long
|
비트 단위의 선형 샘플 크기. 제약조건으로서 오디오 장치가 선형 샘플을 생성할 때만 만족할 수 있습니다. |
echoCancellation | boolean 또는 DOMString |
이 값은 false , true 또는 EchoCancellationModeEnum 의
멤버 중 하나입니다.
여러 마이크로폰에서 다양한 오디오 스트림이 재생되는 과정에서, 마이크로폰이 녹음하는 입력 신호에서 재생 중인 소리를 제거하려는 시도가 종종 필요합니다.
이것을 에코 캔슬레이션(echo cancellation)이라고 합니다. 꼭 필요하지 않은 경우에는 오디오 왜곡이 발생하지 않도록 에코 캔슬레이션을 끄는 것이
바람직할 수 있습니다.
이를 통해 애플리케이션이 이러한 동작을 제어할 수 있습니다.
|
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
"만큼
에코를 반드시(MUST) 제거해야 하며, "all
"만큼
에코를 제거하도록 권장되어야 합니다(SHOULD).
MediaStreamTrack
객체는 종료되지 않았고 ended가 아니며,
mute, unmute
또는 ended 이벤트에 대해 등록된 이벤트 리스너가 하나라도 있다면 가비지 컬렉션되어서는 안 됩니다.
각 소스 타입은 추가적으로 가비지 컬렉션 규칙을 정밀하게 정의할 수 있으며, 어떤 소스는 특정 이벤트를 절대 발생시키지 않을 수도 있습니다.
MediaStreamTrack
의
stop()을 호출하는 것이 권장됩니다.
특히 캡처 트랙의 경우, 기반 리소스가 비용이 크고 사용자에게 보여지는 프라이버시 인디케이터에도 영향을 줄 수 있습니다.
addtrack
및 removetrack
이벤트는
MediaStreamTrackEvent
인터페이스를 사용합니다.
addtrack
및 removetrack
이벤트는
스크립트에 track set이
MediaStream
에서 User Agent에 의해
업데이트되었음을 알립니다.
이름이 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
, 필수본 섹션은 비규범적입니다.
User Agent는 소스에서 싱크로 이어지는 미디어 파이프라인을 제공합니다. User Agent에서
싱크란
<img
>,
<video
>,
및
<audio
>
태그를 의미합니다.
기존의 소스에는 스트리밍 콘텐츠, 파일, 웹 리소스가 포함됩니다. 이러한 소스가 생성하는 미디어는 일반적으로 시간이 지나도 변하지 않으므로, 이러한 소스는 정적(static)으로 간주할 수
있습니다.
사용자에게 이러한 소스를 표시하는 싱크(실제 태그들)는 소스 콘텐츠를 조작하는 다양한 컨트롤을 제공합니다.
예를 들어,
<img
>
태그는 1600x1200 픽셀의 큰 소스 이미지를 width="400"
, height="300"
으로 정의된 사각형에 맞게 축소합니다.
소스는 수명을 가집니다. 기본적으로 소스의 수명은 그것을 생성한 컨텍스트에 연결되어 있습니다. 예를 들어, MediaDevices
.getUserMedia
()
로 생성된 소스는
navigator.mediaDevices
컨텍스트에서 생성된 것으로 간주됩니다.
마찬가지로, RTCRtpReceiver
객체의 소스는
RTCPeerConnection
자체에 연결되어
있으며, 그것의 생성 컨텍스트에 연결되어 있습니다.
특정 소스의 정의에 명시적으로 기술된 경우를 제외하면,
소스는 생성 컨텍스트가 사라지면 항상 중지됨 상태가 됩니다.
서로 다른 컨텍스트의 두 소스가 동시에 같은 캡처 장치를 사용할 수 있다는 점도 주의해야 합니다.
한 소스는 다른 소스와 독립적으로 중지될 수 있습니다.
getUserMedia API는 마이크나 카메라 등 동적(dynamic) 소스를 추가합니다. 이러한 소스의 특성은 애플리케이션의 요구에 따라 변화할 수 있습니다. 이러한 소스들은 본질적으로
동적(dynamic)으로 간주할 수 있습니다.
동적 소스에서 미디어를 표시하는
<video
>
요소는 크기 조정(scaling)을 수행하거나 미디어 파이프라인을 따라 정보를 되돌려 보내 소스가 디스플레이에 더 적합한 콘텐츠를 생성하도록 할 수 있습니다.
참고: 이와 같은 피드백 루프는 단순히 "최적화"를 가능하게 하는 것이지만, 결코 사소하지 않은 이득을 가져옵니다. 이 최적화는 배터리 절약, 네트워크 혼잡 감소 등에 큰 도움이 될 수 있습니다.
MediaStream
싱크(예:
<video
>,
<audio
>,
그리고
RTCPeerConnection
)는
본 명세에서 기술하는 설정값,
Capabilities, Constraints
외에도
소스 스트림을 추가로 변환하는 메커니즘을 계속 가질 수 있습니다. (싱크 변환 옵션, 특히 RTCPeerConnection
의 옵션 등은 본
명세 범위에 포함되지 않습니다.)
트랙 제약조건을 변경하거나 적용하는 행위는 해당 소스를 공유하는 모든 트랙의 설정값에 영향을 미칠 수 있으며, 결과적으로 해당 소스를 사용하는 모든 하위 싱크에도 영향을
미칠 수 있습니다. 많은 싱크는 이러한 변경을 잘 받아들일 수 있는데, 예를 들어
<
요소나 video
>RTCPeerConnection
가 그렇습니다.
하지만 Recorder API 같은 싱크는 소스 설정 변경으로 인해 실패할 수 있습니다.
RTCPeerConnection
은 주목할 만한
객체로,
네트워크 스트림에 대해 싱크 그리고 소스 역할을 동시에 수행합니다. 싱크로서, 소스 변환 기능(비트레이트 하향, 해상도 확대/축소, 프레임률 조정 등)을 가지고
있으며,
소스 역할로서는 트랙 소스에 의해 자체 설정값이 변경될 수 있습니다.
주어진 소스의 변경이 다양한 싱크에 어떻게 영향을 미치는지 설명하기 위해 아래 예시를 들어봅니다. 이 예시에서는 width와 height만 사용하지만, 본 명세에서 노출된 모든 설정값에 동일한
원리가 적용됩니다. 첫 번째 그림에서 홈 클라이언트는 로컬 비디오 카메라로부터 비디오 소스를 얻었습니다. 소스의 width와 height 설정값은 각각 800픽셀, 600픽셀입니다.
홈 클라이언트의 세 개 MediaStream
객체에는 동일한 <deviceId
를 사용하는 트랙이
있습니다. 세 미디어 스트림은 각각 다른 싱크에 연결됩니다:
<
요소(A), 또 다른
video
><
요소(B), 그리고 피어 연결(C)입니다. 피어 연결은 소스 비디오를 원격 클라이언트로 스트리밍합니다. 원격 클라이언트에는 피어 연결을 소스로 사용하는 트랙이 포함된 두 개의 미디어 스트림이
있습니다. 이 두 미디어 스트림은 각각 두 개의
video
><
요소 싱크(Y, Z)에 연결됩니다.
video
>
이 시점에서, 홈 클라이언트의 모든 싱크는 원본 소스의 치수 설정값에 대해 변환을 적용해야 합니다. B는 비디오를 축소하고, A는 비디오를 확대(품질 저하)하며, C도 네트워크 전송을 위해 비디오를 약간 확대합니다. 원격 클라이언트의 싱크 Y는 비디오를 매우 축소하고, 싱크 Z는 크기 변환 없이 표시합니다.
applyConstraints
()
호출에 따라,
트랙 중 하나가 홈 클라이언트의 비디오 소스에서 더 높은 해상도(1920x1200 픽셀)를 요구합니다.
소스 변경은 즉시 홈 클라이언트의 모든 트랙과 싱크에 영향을 주지만, 원격 클라이언트의 싱크(또는 소스)에는 영향을 주지 않습니다. 홈 클라이언트 소스 비디오의 크기가 커지면 싱크 A는 더 이상 크기 변환이 필요 없어지고, 싱크 B는 이전보다 더 많이 축소해야 합니다. 싱크 C(피어 연결)는 원격 클라이언트로의 전송을 일정하게 유지하기 위해 이제 비디오를 축소해야 합니다.
도표에는 없지만, 원격 클라이언트 측에서 설정값 변경 요청이 똑같이 유효할 수 있습니다. 이는 Y, Z 싱크에 A, B, C와 동일하게 영향을 미칠 수 있으며, 홈 클라이언트의 피어 연결과 재협상을 유발해 홈 클라이언트 비디오 소스에 대한 변환을 변경할 수 있습니다. 이런 변경은 반드시 싱크 A, B 또는 홈 클라이언트의 비디오 소스에 영향을 주어야 할 필요는 없습니다.
이 명세는 원격 클라이언트의 비디오 소스 변경이 홈 클라이언트의 비디오 소스 변경을 자동으로 트리거하는 메커니즘을 정의하지 않습니다. 구현체는 애플리케이션이 설정한 제약 내에서만 이러한 소스-싱크 최적화를 선택적으로 할 수 있습니다. 다음 예제가 이를 보여줍니다.
주어진 소스의 변경이 싱크 소비자에 영향을 주는 것은 명백합니다. 하지만 어떤 상황에서는 싱크의 변경이 구현체가 소스 설정값을 조정하게 만들 수도 있습니다. 아래 그림에서 이를 설명합니다. 첫
번째 그림에서 홈 클라이언트의 비디오 소스는 1920x1200 픽셀 비디오 스트림을 전송하고 있습니다. 소스는 제약이 없으므로, 애플리케이션 입장에서 소스의 정확한 크기는 유연합니다. 두 개
MediaStream
객체에 동일한 deviceId
를 가진 트랙이
포함되어 있고, 해당 MediaStream
들은 두 개의
<
싱크(A, B)에 연결되어 있습니다. 싱크 A는 video
>width="1920"
, height="1200"
로 크기가 지정되어 있어 소스 비디오를 변환 없이
표시합니다. 싱크 B는 더 작게 지정되어 있으므로 320x200 사각형에 맞게 비디오를 축소합니다.
애플리케이션이 싱크 A의 크기를 더 작게(1920에서 1024 픽셀, 1200에서 768 픽셀) 변경하면, User Agent의 미디어 파이프라인은 어떤 싱크도 더 높은 소스 해상도를 필요로 하지 않음을 인식할 수 있으며, 소스와 싱크 A 모두 불필요한 작업을 하고 있음을 감지할 수 있습니다. 이러한 경우 및 소스가 더 높은 해상도 비디오를 계속 생성하도록 강제하는 다른 제약조건이 없다면, 미디어 파이프라인은 선택적으로 소스 해상도를 변경할 수 있습니다:
위 그림에서 홈 클라이언트의 비디오 소스 해상도는 싱크 A, B 중 더 큰 값으로 변경되어 재생이 최적화되었습니다. 위 그림에는 없지만, 같은 동작이 피어 연결이나 다른 싱크에도 적용될 수 있습니다.
Constraints가 트랙에 적용될 때,
소스가 해당 제약조건을 만족할 수 없는 경우가 있을 수 있습니다. 이는 소스 자체가 제약을 만족할 수 없거나, 이미 상충되는 다른 제약조건을 만족하고 있기 때문입니다. 이런 경우 applyConstraints
()
에서
반환된 promise는 reject되며, 새 제약조건은
적용되지 않습니다. 이 경우 제약조건에 변화가 없으므로 소스에도 변경이 필요하지 않습니다. 아래 예시가 이 동작을 보여줍니다.
이 예시에서는 두 개의 미디어 스트림 각각에 동일한 소스를 공유하는 비디오 트랙이 있습니다. 첫 번째 트랙은 처음에 제약조건이 없습니다. 싱크 N에 연결되어 있고, 싱크 N은 800x600 픽셀 해상도이며 소스(1024x768)를 축소해 표시합니다. 다른 트랙은 필수 제약조건으로 소스의 보조 조명을 강제로 끄도록 하고, 싱크 P에 연결되어 있으며, 싱크 P는 소스와 동일한 width와 height입니다.
이제 첫 번째 트랙이 필수 제약조건으로 보조 조명을 강제로 켜도록 추가합니다. 이 시점에서 두 필수 제약조건은 소스가 동시에 만족시킬 수 없습니다(보조 조명은 동시에 켜고 끌 수 없음). 이 상태는 첫 번째 트랙이 상충되는 제약조건을 적용하려고 했기 때문에 발생한 것이므로, 제약조건 적용이 실패하며 소스의 설정값이나 두 트랙의 제약조건에는 변화가 없습니다.
MediaStream
은 미디어 요소에 할당될 수 있습니다.
MediaStream
은 미리 로드(preload)되거나 탐색(seek)할 수 없으며,
단순하고 잠재적으로 무한한 선형
미디어 타임라인을 나타냅니다. 타임라인은 0에서 시작하여, 미디어
요소가
재생될 가능성이 있는 동안 실시간으로 선형적으로 증가합니다. MediaStream
의 재생이 일시정지(paused)되면 타임라인은 증가하지 않습니다.
User Agent가 본 명세를 지원하면 반드시
srcObject
속성을 지원해야 하며, 이는 [HTML]의
HTMLMediaElement
인터페이스에서 정의됩니다. 여기에는 MediaStream
객체의 재생 지원이 포함됩니다.
[HTML] 문서는
HTMLMediaElement
가
미디어 제공자 객체와 어떻게 동작하는지 설명합니다. 미디어 제공자 객체가 MediaStream
인 경우 다음이 적용됩니다:
AudioTrack
또는 VideoTrack
가
생성될 때, id
와 label
속성은 해당 MediaStreamTrack
의 속성으로 초기화되어야 하며,
kind
는 "main"
으로, language
는 빈 문자열로 초기화해야 합니다.
MediaStream
의 현재 데이터를 재생해야 하며 절대 버퍼링해서는 안 됩니다.
MediaStream
의 track set의 순서가 정의되어 있지 않으므로,
AudioTrackList
및 VideoTrackList
의
순서에 대한 요구사항은 없습니다.
요소가 HTMLVideoElement
인
경우,
비디오 재생이 끝났을 때 재생 종료로 간주하는데, 이는
다음과 같습니다:
요소의
readyState
값이 HAVE_METADATA
이상이고,
MediaStream
상태가 inactive이고, 이전에 active였거나,
MediaStream
상태가 active이고, 이전에 inactive였으며, 그 전에 active였고,
마지막으로 play
()
를
호출한 뒤이고,
autoplay
가
false
일 때.
재생이 종료되면, 새로운 MediaStreamTrack
가 MediaStream
에 추가되어도
autoplay
가
true
이거나, 웹 애플리케이션에서 play
()
를
호출해 요소가 재시작되지 않으면 재생이 재개되지 않습니다.
요소가 HTMLAudioElement
인
경우,
오디오 재생이 끝났을 때 재생 종료로 간주하는데, 이는
다음과 같습니다:
요소의
readyState
값이 HAVE_METADATA
이상이고,
MediaStream
상태가 inaudible이고, 이전에 audible였거나,
MediaStream
상태가 audible이고, 이전에 inaudible였으며, 그 전에 audible였고,
마지막으로 play
()
를
호출한 뒤이고,
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 이상의 정수. 초기값은 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 |
loop
속성을 설정해도 효과가 없습니다. MediaStream 은 끝이 정의되어 있지
않아 반복(loop)될 수 없습니다.
|
위에 나열된 setter는 HTMLMediaElement
의
내부 상태를 변경하지 않으므로, MediaStream
이 더 이상 요소의 할당된 미디어 제공자 객체가 아니게
되면, 나열된 속성들은 스트림을 할당하기 전의 값으로 다시 나타납니다.
MediaStream
은 할당된 미디어 제공자
객체에서 벗어납니다. 이는 srcObject
에
null
이나 비스트림 객체가 할당될 때, 미디어 요소 로드 알고리즘
직전에 발생합니다. 그 결과
ratechange
이벤트가(playbackRate
와
defaultPlaybackRate
가
스트림 할당 전에 달랐던 경우) 발생할 수 있습니다.
일부 연산은 OverconstrainedError
를 throw하거나 발생시킵니다. 이는 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"
로 설정합니다.
이 name은 레거시 code와 매핑되지 않으므로 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
|
User Agent에서 사용 가능한 미디어 장치 집합이 변경되었을 때. 현재 장치 목록은 devices 속성에서 확인할 수 있습니다.
|
이 섹션에서는 스크립트가 User Agent에 연결된 미디어 입력 및 출력 장치(예: 웹카메라나 헤드셋)에 대해 질의할 수 있는 API를 설명합니다.
MediaDevices
MediaDevices
객체는 User Agent에서 사용 가능한
미디어 장치를 검사하고 접근하기 위한 API의 진입점입니다.
MediaDevices를 생성하려면 realm이 주어졌을 때, 다음 단계를 수행합니다:
mediaDevices를 realm에서 새로운 MediaDevices
객체로 두고, 다음 내부 슬롯들로 초기화합니다:
[[devicesLiveMap]], 빈 map으로 초기화됩니다.
[[devicesAccessibleMap]], 빈 map으로 초기화됩니다.
[[kindsAccessibleMap]], 빈 map으로 초기화됩니다.
[[storedDeviceList]], list로 초기화되며, User Agent에서 사용 가능한 모든 미디어 입력 및 출력 장치를 포함합니다.
[[canExposeCameraInfo]], false
로 초기화됩니다.
[[canExposeMicrophoneInfo]], false
로
초기화됩니다.
[[mediaStreamTrackSources]], 빈 set으로 초기화됩니다.
settings를 mediaDevices의 관련 설정 객체로 둡니다.
MediaDevices
.getUserMedia
()
가
노출하는 각 장치 종류 kind에 대해 다음을 실행합니다:
mediaDevices.[[kindsAccessibleMap]]
[kind]
를, settings에 대해 kind와 연관된 권한의 permission state가
"granted
"이면
true
로, 아니면 false
로 설정합니다. (예: "camera"
, "microphone"
등)
MediaDevices
.getUserMedia
()
가
노출하는 각 개별 장치의 deviceId deviceId에 대해 다음을 실행합니다:
mediaDevices.[[devicesLiveMap]]
[deviceId]
를 false
로 설정하고,
mediaDevices.[[devicesAccessibleMap]]
[deviceId]
를, settings에 대해 장치 종류와 deviceId와 연관된 권한의 permission state가
"granted
"이면
true
, 아니면 false
로 설정합니다.
mediaDevices를 반환합니다.
getUserMedia
()
가 노출하는 각
장치 종류 kind에 대해, mediaDevices의 관련 설정 객체에
대해 권한 상태가 변화할 때마다 다음을 실행합니다:
만약 변화가 "granted
"로
변한 경우, mediaDevices.[[kindsAccessibleMap]]
[kind]
를 true
로 설정합니다.
만약 변화가 "granted
"에서
다른 값으로 변한 경우, mediaDevices.[[kindsAccessibleMap]]
[kind]
를 false
로 설정합니다.
getUserMedia
()
가 노출하는 각
장치에 대해, 해당 장치 종류와 deviceId deviceId에 대해 mediaDevices의 관련 설정
객체에서 권한
상태가 변화할 때마다 다음을 실행합니다:
만약 변화가 "granted
"로
변한 경우, mediaDevices.[[devicesAccessibleMap]]
[deviceId]
를 true
로(이미 true
가 아니면) 설정합니다.
만약 변화가 "granted
"에서
다른 값으로 변하고, 해당 장치가 현재 중지됨 상태라면, mediaDevices.[[devicesAccessibleMap]]
[deviceId]
를 false
로 설정합니다.
새로운 미디어 입력/출력 장치가 User Agent에서 사용 가능해지거나, 사용 가능한 입력/출력 장치가 더 이상 사용 불가해지거나, MediaDeviceKind
의 시스템 기본값이 변경되는 경우, User Agent는 true
인 장치 열거가 진행될 수 있음 조건을 만족하는 각 MediaDevices
객체 mediaDevices에 대해, 다음
장치 변경 알림 단계를 실행해야 하며, 그 외 MediaDevices
객체에는 실행하지 않습니다:
lastExposedDevices를 mediaDevices 및 mediaDevices.[[storedDeviceList]]
로 장치 정보 객체 리스트
생성의 결과로 둡니다.
deviceList를 User Agent에서 사용 가능한 모든 미디어 입력/출력 장치의 리스트로 둡니다.
newExposedDevices를 mediaDevices 및 deviceList로 장치 정보 객체 리스트 생성의 결과로 둡니다.
newExposedDevices 내 MediaDeviceInfo
객체들이
lastExposedDevices와 일치하고 순서도 동일하다면, 이하 단계는 중단합니다.
위 단계는 enumerateDevices
알고리즘에 의해, enumerateDevices
를
실제로 사용할 수 있는 문서에만 devicechange
이벤트가 발생하도록 제한합니다.
이는 특정 MediaDeviceKind
에 대해 장치를 열거할 수 있는
문서에 해당합니다.
mediaDevices.[[storedDeviceList]]
를
deviceList로 설정합니다.
작업 큐에 mediaDevices에서 DeviceChangeEvent
생성자와 devices
를
newExposedDevices로 초기화한 후 devicechange
라는 이름의 이벤트를 발생시키는 작업을 추가합니다.
User Agent는 여러 이벤트가 동시에 발생하거나, 여러 장치가 동시에 추가/제거될 때(예: 마이크가 달린 카메라) 여러 이벤트를 하나로 합쳐서 발생시킬 수 있습니다.
추가적으로, 열거된 MediaDevices
객체가 나중에 장치 열거가 진행될 수 있음 조건을 만족하게 되면(예: 뷰에 들어옴), User Agent는 그 시점에 해당
MediaDevices
객체에 대해 장치 변경 알림 단계를 실행해야 합니다.
이 이벤트들은 서로 다른 오리진의 문서에서 동시에 발생할 수 있습니다. User Agent는
이벤트 타이밍을 퍼징하여 크로스 오리진 활동 상관관계를 방지할 수 있습니다.
WebIDL[Exposed=Window, SecureContext]
interface MediaDevices
: EventTarget {
attribute EventHandler ondevicechange
;
Promise<sequence<MediaDeviceInfo
>> enumerateDevices
();
};
ondevicechange
타입 EventHandler
이 이벤트 핸들러의 이벤트 타입은 devicechange입니다.
enumerateDevices
User Agent에서 사용 가능한 미디어 입력 및 출력 장치 정보를 수집합니다.
이 메서드는 promise를 반환합니다. 이 promise는
이행될 때,
MediaDeviceInfo
객체들의 시퀀스를 반환합니다.
이는 User Agent에서 사용 가능한 미디어 입력 및 출력 장치를 나타냅니다.
열거(enumeration)가 성공하면 반환됩니다.
입력 장치를 나타내는 시퀀스의 요소들은 InputDeviceInfo
타입이며,
이는 MediaDeviceInfo
를 확장합니다.
카메라와 마이크 소스는 가능하면 열거되어야 합니다. 추가 소스 타입을 도입하는 명세는 해당 소스 타입이 열거 가능한지에 대한 권고안을 제공합니다.
enumerateDevices
()
메서드가 호출되면,
User Agent는 다음 단계를 실행해야 합니다:
p를 새로운 promise로 둡니다.
proceed를 장치 열거 진행 가능 여부의 결과로 둡니다. 인자는 this입니다.
mediaDevices를 this로 둡니다.
다음 단계는 병렬로 실행합니다:
proceed가 false
인 동안,
User Agent는
다음 단계로 진행하지 않고,
proceed를 장치 열거 진행 가능 여부의
결과로 mediaDevices에 대해 true
로 설정하는 작업이 큐에 들어올 때까지
기다려야 합니다.
resultList를 장치 정보 객체 리스트
생성의 결과로 둡니다. 인자는 mediaDevices와
mediaDevices.[[storedDeviceList]]
입니다.
resolve p를 resultList로 완료합니다.
p를 반환합니다.
장치 정보 객체 리스트 생성을 수행하려면, mediaDevices와 deviceList가 주어졌을 때 다음 단계를 실행합니다:
resultList를 빈 리스트로 둡니다.
microphoneList, cameraList, otherDeviceList를 빈 리스트로 둡니다.
document를 mediaDevices의
관련
글로벌 객체의 연결된
Document
로 둡니다.
deviceList의 각 발견된 장치 device에 대해 다음 하위 단계를 실행합니다:
device가 마이크가 아니거나, document가 "microphone" 기능을 사용할 수 없는 경우, 이하 하위 단계는 중단하고 다음 장치로 넘어갑니다.
deviceInfo를 장치 정보 객체 생성의 결과로 둡니다. 인자는 device와 mediaDevices입니다.
device가 시스템 기본 마이크라면, deviceInfo를 microphoneList 앞에 추가합니다. 아니라면 deviceInfo를 microphoneList 뒤에 추가합니다.
deviceList의 각 발견된 장치 device에 대해 다음 하위 단계를 실행합니다:
device가 카메라가 아니거나, document가 "camera" 기능을 사용할 수 없는 경우, 이하 하위 단계는 중단하고 다음 장치로 넘어갑니다.
deviceInfo를 장치 정보 객체 생성의 결과로 둡니다. 인자는 device와 mediaDevices입니다.
device가 시스템 기본 카메라라면, deviceInfo를 cameraList 앞에 추가합니다. 아니라면 deviceInfo를 cameraList 뒤에 추가합니다.
마이크
정보 노출 가능 여부가 mediaDevices에서 false
라면,
microphoneList를 첫 번째 항목만 남기고 잘라냅니다.
카메라 정보
노출 가능 여부가 mediaDevices에서 false
라면,
cameraList를 첫 번째 항목만 남기고 잘라냅니다.
deviceList의 각 발견된 장치 device에 대해 다음 하위 단계를 실행합니다:
device가 마이크이거나 카메라라면, 이하 하위 단계는 중단하고 다음 장치로 넘어갑니다.
카메라/마이크
이외 장치의 노출 결정 알고리즘을 실행합니다. 인자는 device,
microphoneList, cameraList,
mediaDevices입니다.
결과가 false
면 이하 하위 단계는 중단하고 다음 장치로 넘어갑니다.
deviceInfo를 장치 정보 객체 생성의 결과로 둡니다. 인자는 device와 mediaDevices입니다.
device가 시스템 기본 오디오 출력인 경우, 다음 하위 단계를 실행한다:
defaultAudioOutputInfo를 device를 나타내는 device info object 생성의 결과로, mediaDevices와 함께 한다.
defaultAudioOutputInfo의
deviceId
값을 "default"로 설정한다.
사용자 에이전트는 권장
defaultAudioOutputInfo의
label
값을 시스템 기본 오디오 출력임을 명확하게 하도록 업데이트해야 한다.
defaultAudioOutputInfo를 otherDeviceList의 앞에 추가한다.
resultList에 microphoneList의 모든 장치를 순서대로 추가한다.
resultList에 cameraList의 모든 장치를 순서대로 추가한다.
resultList에 otherDeviceList의 모든 장치를 순서대로 추가한다.
resultList를 반환한다.
이 메서드는 미디어 캡처 장치의 사용 가능 여부를 통해 브라우징 세션 및 오리진 간에 지속적인 정보를 반환하므로, User Agent가 노출하는 지문(fingerprinting) 표면을 넓힙니다.
해당 관련
글로벌 객체의 연결된
Document
가 캡처를 시작하지 않은 경우, 이 메서드는 두 비트의 정보만 노출합니다: 카메라가 있는지, 마이크가
있는지. User Agent는 예를 들어 관련
글로벌 객체의 연결된
Document
가 getUserMedia
()
를
합리적인 제약조건으로 호출하기 전까지 시스템에 카메라와 마이크가 있다고 가장할 수 있습니다.
해당 관련
글로벌 객체의 연결된
Document
가 캡처를 시작하면, 캡처 장치의 그룹 및 사람 읽기 가능한 라벨 등 모든 미디어 캡처 장치의 리스트를
통해 추가적인 지속적 크로스 오리진 정보를 제공합니다. 이는 지문 표면을 더욱 넓힙니다.
User Agent는 장치 라벨을 정제(sanitize)하여 노출을 제한할 수 있습니다. 예를 들어 사용자 이름을 삭제하고, 장치 제조사나 모델 정보만 유지할 수 있습니다.
정제된 라벨이 사용자가 해당 장치를 식별할 수 있도록 하는 것이 중요합니다.
위에서 설명한 알고리즘은 미디어 장치 정보에 접근할 수 있는지가 관련 글로벌
객체의 연결된
Document
가 캡처를 했는지에 따라 달라진다는 것을 의미합니다.
카메라와 마이크 장치의 경우, 관련 글로벌
객체의
연결된
Document
가 캡처를 하지 않았다면
(즉, getUserMedia
()
가 호출되지
않았거나 한 번도 성공적으로 resolve되지 않았다면), MediaDeviceInfo
객체는 kind
에는 유효한 값을 담고, deviceId
, label
, groupId
에는 빈 문자열을 담게 됩니다.
또한, 각 kind
별로 최대 한 개의 장치만 enumerateDevices
()
결과에 나타납니다.
그 외의 경우에는
MediaDeviceInfo
객체가 deviceId
, kind
,
label
, groupId
에 의미 있는 값을 담게 됩니다. 모든 사용 가능한
장치가 enumerateDevices
()
결과에 나타납니다.
발견된 장치 device를 나타내는 장치 정보 객체 생성을 수행하려면, mediaDevices가 주어졌을 때 다음 단계를 실행합니다:
deviceInfo를 device를 나타내는 새 MediaDeviceInfo
객체로 둡니다.
device에 대해 deviceInfo.kind
를 초기화합니다.
deviceInfo.kind
가
"videoinput"이고
카메라 정보 노출 가능
여부가 mediaDevices에서 false
이면 deviceInfo를 반환합니다.
deviceInfo.kind
가
"audioinput"이고
마이크 정보 노출 가능
여부가 mediaDevices에서 false
이면 deviceInfo를 반환합니다.
device에 대해 deviceInfo.label
을 초기화합니다.
device에 대해 저장된 deviceId
가 있으면
deviceInfo.deviceId
에 그 값을 할당합니다.
그렇지 않으면 deviceInfo.deviceId
를 deviceId
에 설명된 대로 새롭게 생성된
고유
식별자로 둡니다.
device가 document에 대해 이미 표현된 장치와 같은 물리적 장치에 속한다면,
deviceInfo.groupId
를
기존 groupId
값으로 초기화합니다.
그렇지 않으면 deviceInfo.groupId
를
groupId
에 설명된 대로 새롭게 생성된 고유
식별자로 둡니다.
deviceInfo를 반환합니다.
장치 열거 진행 가능 여부 검사를 수행하려면, mediaDevices가 주어졌을 때 다음 단계를 실행합니다:
User Agent는 장치 정보 노출 가능 여부가
mediaDevices에서 true
이면 true
를 반환할 수
있습니다.
mediaDevices로 뷰에 있음의 결과를 반환합니다.
장치 정보 노출 가능 여부 검사를 수행하려면 mediaDevices가 주어졌을 때 다음 단계를 실행합니다:
카메라 정보 노출 가능
여부가 mediaDevices에서 true
이면 true
를 반환합니다.
마이크 정보 노출 가능
여부가 mediaDevices에서 true
이면 true
를 반환합니다.
false
를 반환합니다.
카메라 정보 노출 가능 여부 검사를 수행하려면 mediaDevices가 주어졌을 때 다음 단계를 실행합니다:
로컬 장치 중 "videoinput" 종류의 장치가 mediaDevices의 관련
글로벌 객체의
연결된
Document
에 라이브 MediaStreamTrack
에 연결되어 있다면
true
를 반환합니다.
mediaDevices.[[canExposeCameraInfo]]
의 값을
반환합니다.
마이크 정보 노출 가능 여부 검사를 수행하려면 mediaDevices가 주어졌을 때 다음 단계를 실행합니다:
로컬 장치 중 "audioinput" 종류의 장치가 MediaStreamTrack
에 연결되어 있고,
mediaDevices의 관련
글로벌 객체의
연결된
Document
에 라이브라면 true
를 반환합니다.
mediaDevices.[[canExposeMicrophoneInfo]]
의
값을 반환합니다.
뷰에 있음 검사를 수행하려면 mediaDevices가 주어졌을 때 다음 단계를 실행합니다:
mediaDevices의 관련
글로벌 객체의 연결된
Document
가
완전히
활성화됨 상태이고 visibility
state
가 "visible"
이면 true
를 반환합니다. 아니면 false
를 반환합니다.
시스템 포커스가 있음 검사를 수행하려면 mediaDevices가 주어졌을 때 다음 단계를 실행합니다:
mediaDevices의 관련
글로벌 객체의 navigable의
top-level
traversable이
시스템 포커스를 가지고 있으면
true
를 반환합니다. 아니면 false
를 반환합니다.
장치 노출 확장 가능 여부 검사를 수행하려면 deviceType이 주어졌을 때 다음 단계를 실행합니다:
permission을 이름이 deviceType인 descriptor의 permission state를 읽은 결과로 둡니다.
permission이 "granted
"이면
true
를 반환합니다.
permission이 "prompt
"이면,
User Agent는 해당 origin에 대해 deviceType 접근이 이전에 허용된 것으로 알고 있다면 true
를
반환할 수 있습니다.
false
를 반환합니다.
장치 정보 노출 설정을 mediaDevices에 대해, requestedTypes set과 boolean value가 주어졌을 때, 다음 단계를 실행합니다:
"video"
가 requestedTypes에 포함되어 있다면,
다음 하위 단계를 실행합니다:
mediaDevices.[[canExposeCameraInfo]]
를 value로 설정합니다.
value가 true
이고 장치 노출 확장 가능 여부가
"microphone"에 대해 true
라면,
mediaDevices.[[canExposeMicrophoneInfo]]
를 true
로 설정합니다.
"audio"
가 requestedTypes에 포함되어 있다면,
다음 하위 단계를 실행합니다:
mediaDevices.[[canExposeMicrophoneInfo]]
를 value로 설정합니다.
value가 true
이고 장치 노출 확장 가능 여부가 "camera"에
대해 true
라면,
mediaDevices.[[canExposeCameraInfo]]
를 true
로 설정합니다.
User Agent는 언제든지 장치 정보 노출을 false
로 다시 설정할
수 있습니다,
예를 들어 User Agent가 특정 Document
에 대해 장치 접근을 철회하기로
결정한 경우입니다.
카메라/마이크 이외 장치의 노출 결정 알고리즘 은 device, microphoneList, cameraList, mediaDevices를 입력으로 받아, device에 대한 정보를 웹 페이지에 노출할지 여부를 결정하는 boolean 값을 반환합니다.
기본적으로 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
of type DOMString
,
readonly표현되는 장치의 식별자입니다. 장치는 반드시 그 식별자와 kind
으로
고유하게 식별되어야 합니다.
저장된 식별자가 인식되도록 하려면, 식별자는 반드시 Document
의 동일 출처
최상위
탐색 가능 내에서 동일해야 합니다.
하위
탐색 가능에서는,
식별자가 문서 간에 동일한지 여부는 반드시 User
Agent의 저장소 분할 규칙(예: localStorage
)
을 따라야 하며,
교차 사이트 상관관계에 대한 대응책을 방해하지 말아야 합니다.
만약 식별자가 사용자를 고유하게 식별할 수 있다면, 반드시 다른 출처의 문서에서는 추측할 수 없게 하여
해당 식별자가 동일 사용자를 여러 출처에서 상관할 수 없도록 해야 합니다.
식별자가 사용자가 연결되지 않고 다른 방식(예: User-Agent 문자열)으로 추측할 수 있다면 출처 간에 재사용할 수 있습니다.
이 출처의 페이지에서 라이브 MediaStreamTrack
에 어떤 로컬 장치가
연결됐거나,
이 출처에 로컬 장치 접근에 대한 저장된 권한이 부여된 경우,
이 식별자는 반드시 아래에 상세된 경우를 제외하고는 지속되어야 합니다. 고유하고 안정적인 식별자는 애플리케이션이 여러 번 방문 시에도 소스를 저장, 사용 가능
여부 확인, 특정 소스를 직접 요청할 수 있게 합니다.
하지만, 이 출처의 페이지에서 라이브 MediaStreamTrack에 어떤 로컬 장치도 연결되지 않았고, 저장된 권한도 부여되지 않았다면, User Agent는 이 출처의 마지막 브라우징 세션이 종료된 후에 이 식별자를 지울 수 있습니다. 만약 User Agent가 이 조건에서 식별자를 지우지 않기로 한다면, 반드시 사용자가 해당 식별자를 눈에 띄게 확인 및 삭제할 수 있게 제공해야 합니다(예: 쿠키처럼).
deviceId
는 브라우징 세션 간에
지속될 수 있으므로, 그 지문 특성을 줄이기 위해 반드시 deviceId
를 쿠키 등 다른 영구
저장소와 동일하게 취급해야 하며,
[COOKIES]에 따라,
User Agents는 반드시
쿠키 사용이 차단된 사이트에는 장치 식별자를 지속시키지 않아야 하며,
User Agents는 반드시
다른 영구 저장소가 지워질 때 출처별 장치 식별자를 회전시켜야 합니다.
kind
of
type MediaDeviceKind
,
readonly표현되는 장치의 종류입니다.
label
of type DOMString
,
readonly이 장치를 설명하는 라벨입니다(예: "외부 USB 웹캠"). 이 라벨은 최종 사용자가 장치들을 구분할 수 있도록 제공됩니다. 애플리케이션은 라벨에 특정 정보(장치 종류나 모델 등)가 반드시 포함되어 있다고 가정할 수 없습니다. 장치에 라벨이 없으면, 이 속성은 반드시 빈 문자열을 반환해야 합니다.
groupId
of type DOMString
,
readonly표현되는 장치의 그룹 식별자입니다. 두 장치가 동일한 그룹 식별자를 가지면, 동일한 물리적 장치에 속합니다. 예를 들어, 동일한 헤드셋의 스피커와 마이크를 나타내는 오디오 입력 및 출력 장치는 동일한 groupId를 가집니다.
그룹 식별자는 반드시 각 document 별로 고유하게 생성되어야 합니다.
toJSON
WebIDLenum MediaDeviceKind
{
"audioinput
",
"audiooutput
",
"videoinput
"
};
MediaDeviceKind 열거형 설명 |
|
---|---|
audioinput |
오디오 입력 장치를 나타냅니다. 예: 마이크. |
audiooutput |
오디오 출력 장치를 나타냅니다. 예: 헤드폰. |
videoinput |
비디오 입력 장치를 나타냅니다. 예: 웹캠. |
InputDeviceInfo
인터페이스는 표현되는 입력 장치의 기능(capabilities)에 접근할 수
있도록 합니다.
WebIDL[Exposed=Window, SecureContext]
interface InputDeviceInfo
: MediaDeviceInfo
{
MediaTrackCapabilities
getCapabilities
();
};
getCapabilities
장치의 MediaStream
의 주요
오디오 또는 비디오 트랙(해당 장치의 kind
값에 따라)에 대한 정보를 담은 MediaTrackCapabilities
객체를 반환합니다.
이 정보는 사용자 지정 제약조건이 없는 상태에서의 capabilities이며, 반드시 getCapabilities
()
를
MediaStreamTrack
의 첫 번째 인스턴스에
호출했을 때와 동일해야 하며,
이 트랙은 MediaStream
에서
getUserMedia({deviceId: id})
로 얻을 수 있고,
id는 이 deviceId
속성의 값입니다.
로컬 장치 접근이 부여된 적이 없고, 이 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
;
};
constructor()
this.devices
를
eventInitDict.devices
로부터
frozen array 생성의
결과로 초기화합니다.
devices
타입 FrozenArray<MediaDeviceInfo
>,
읽기 전용
devices
속성은
현재 사용 가능한 장치 목록을 나타내는 MediaDeviceInfo
객체들의 배열을 반환합니다.
userInsertedDevices
타입 FrozenArray<MediaDeviceInfo
>,
읽기 전용
userInsertedDevices
속성은 MediaDeviceInfo
객체들 중에서 사용자가
최근에 물리적으로 삽입하거나 활성화해서 이번 이벤트로 새롭게 노출된 장치들만을 포함하는 배열을 반환합니다.
그렇지 않으면 빈 리스트가 반환됩니다.
User Agent는 사용자가 getUserMedia
()
호출 전에 삽입하거나 활성화한 장치도 포함할 수 있습니다. 단, 이번 이벤트가 해당 장치의 첫 노출이고, 사용자가 getUserMedia
()
에서
해당 장치를 선택하지 않은 경우에 한합니다.
해당 MediaDeviceInfo
객체들은 반드시 devices
에도 존재해야 합니다.
사용자가 통화 중(혹은 바로 그 직전에) 장치를 삽입하는 경우, 해당 장치를 즉시 사용하고자 한다는 강한 신호일 수 있습니다.
애플리케이션은 장치 정보 노출의 변화로 인해 발생할 수 있는 devices
차이와 구분하기 위해 이 속성에 의존하는 것이 권장됩니다.
WebIDLdictionary DeviceChangeEventInit
: EventInit {
sequence<MediaDeviceInfo
> devices
= [];
};
devices
타입 sequence<MediaDeviceInfo
>,
기본값은 []
devices
멤버는 현재 사용
가능한 장치들을 나타내는 MediaDeviceInfo
객체의 배열입니다.
이 섹션은 Navigator
와
MediaDevices
를 확장하여 User Agent에서 사용 가능한 미디어 입력
장치에 대한 접근 권한을 요청하는 API를 제공합니다.
또는, 로컬 MediaStream
을 비디오 요소와 같은 특정 유형의 DOM 요소로부터 캡처할 수도 있습니다
[mediacapture-fromelement]. 이는 자동화된 테스트에 유용할 수
있습니다.
MediaDevices
인터페이스 확장getUserMedia
()
정의는 Navigator
에
수개월간 존재했던 메서드 정의와 두 가지 주요 변경점을 포함합니다.
첫째, getUserMedia
()
메서드의 공식 정의이자 개발자들이 사용하는 것이 권장되는 정의는 이제 여기 MediaDevices
에 있습니다.
이 결정은 원래 API가 Navigator.getUserMedia
에 계속 남아 있는
한 합의된 것입니다.
이는 Navigator
객체의 하위 호환성을 위해서입니다.
작업 그룹은 이 API의 초기 사용자들이 getUserMedia를 "var getUserMedia =
navigator.getUserMedia || navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;"로 정의하도록 권장받아 왔음을 인식하고 있습니다.
이로써 getUserMedia()가 현행 표준으로 구현되기 전후 모두 코드가 동작할 수 있었습니다.
기능적 동등성을 보장하기 위해, Navigator
의
getUserMedia() 메서드는 여기 정의의 동작을 따르도록 정의됩니다.
둘째, 여기서 정의된 메서드는 Promises 기반이며, Navigator
의
것은 아직 콜백 기반입니다.
Navigator
에서
getUserMedia()를 찾는 개발자들은 그곳의 상세 참고 사항을 반드시 읽어야 합니다.
getSupportedConstraints
메서드는
User Agent가 인식하는 제약조건을
애플리케이션이 확인할 수 있도록 제공합니다. 애플리케이션은 이 정보를 활용하여 필수 제약조건을 신뢰성 있게 사용하거나 고급 제약조건 조합에서 예측 가능한 결과를 얻을 수 있습니다.
WebIDLpartial interface MediaDevices
{
MediaTrackSupportedConstraints
getSupportedConstraints
();
Promise<MediaStream
> getUserMedia
(optional MediaStreamConstraints
constraints = {});
};
getSupportedConstraints
User Agent가 알고 있는 제약 가능(constrainable) 속성들을 멤버로 가지는 딕셔너리를 반환합니다. 지원되는 제약 가능 속성은 반드시 표현되어야 하며, User Agent가 지원하지 않는 제약 가능 속성은 반환되는 딕셔너리에 절대 포함되어서는 안 됩니다. 반환되는 값은 User Agent가 구현하는 것을 나타내며, 브라우징 세션 중에는 변경되지 않습니다.
사용자에게 웹캠이나 기타 비디오/오디오 입력 장치 사용 권한을 요청합니다.
constraints 인자는 MediaStreamConstraints
타입의 딕셔너리입니다.
이 메서드는 promise를 반환합니다. promise는 아래에 설명된 대로 사용자가 유효한 트랙을 허용하면 적절한 MediaStream
객체로 이행(fulfilled)됩니다.
promise는 유효한 트랙을 찾는 데 실패하거나 사용자가 권한을 거부한 경우, 아래에 설명된 대로 거부(rejected)됩니다.
getUserMedia()
메서드가 호출되면, User Agent는 반드시 다음 단계를
실행해야 합니다:
constraints를 메서드의 첫 번째 인자로 둡니다.
requestedMediaTypes를 constraints에서 딕셔너리 값이나
true
값을 가진 미디어 타입들의 집합으로 둡니다.
requestedMediaTypes가 비어 있으면, 거부된 promise를 TypeError
로
반환합니다.
WebIDL에 "optional"이라는 단어가 보이지만, 인자는 반드시 제공되어야 정상 호출이
됩니다.
document를 관련
글로벌 객체의 연결된
Document
로 둡니다.
document가 완전히
활성화된(fully active) 상태가 아니면,
거부된
promise를 DOMException
객체와 name
값을 "InvalidStateError
"로
반환합니다.
requestedMediaTypes에 "audio"가 있고, document가 "microphone" 권한 이름으로 식별되는 기능을 사용할 수 없는(allowed to use) 경우, 아래 Permission Failure 단계로 이동합니다.
requestedMediaTypes에 "video"가 있고, document가 "camera" 권한 이름으로 식별되는 기능을 사용할 수 없는 경우, 아래 Permission Failure 단계로 이동합니다.
mediaDevices를 this로 둡니다.
isInView를 뷰에 있음 알고리즘의 결과로 둡니다.
p를 새로운 promise로 둡니다.
다음 단계를 병렬로 실행합니다:
isInView가 false
인 동안,
User Agent는
반드시
뷰에 있음 알고리즘의
결과로 isInView를 true
로 설정하는 작업이 큐에 들어올 때까지 다음 단계로
진행하지 않아야 합니다.
finalSet을 (초기에는) 빈 집합으로 둡니다.
각 미디어 타입 kind에 대해 requestedMediaTypes에 있는 경우, 다음 단계를 실행합니다:
각 kind 타입의 미디어 소스 장치의 가능한 모든 구성에 대해, candidate를 해당 장치와 특정 settings
dictionary로 설정된 MediaStreamTrack
의
잠정적 위치로 둡니다.
이 후보들의 집합을 candidateSet이라 부릅니다.
candidateSet이 빈 집합이면, 아래 NotFound Failure 단계로 이동합니다.
true
이면
CS를 빈 제약 집합(제약 없음)으로 설정합니다. 그 외에는 CS를
constraints의 kind 엔트리 값으로 둡니다.
MediaStreamTrack
객체의 kind에 대해 정의되지 않은 제약 가능 속성은 제거합니다. 즉, "video"
안의 오디오 전용 제약이나
"audio"
안의 비디오 전용 제약은
OverconstrainedError
를 일으키지 않고 무시됩니다.
CS에 필수 제약조건이 포함되어 있고, 해당 이름이 장치 선택에 허용된 필수 제약조건 목록에 없다면, promise p를 TypeError로 거부하고, 이하 단계를 중단합니다.
각 candidateSet의 후보에 대해 SelectSettings 알고리즘을
CS와 함께 실행합니다. 결과가 undefined
이면 해당 후보를
candidateSet에서 제거합니다. 이는 장치가 제약조건을 만족하지 못할 때 후보에서
제외하는 과정입니다.
candidateSet이 빈 집합이면, failedConstraint를 해당
필수 제약조건 중에서
SelectSettings 알고리즘에서 모든 settings dictionary의 fitness distance가
무한(infinity)이었던 항목으로 둡니다(없으면 ""
). 그 후 아래
Constraint Failure 단계로 이동합니다.
이 오류는 사용자가 어떤 장치에 권한을 주기 전에 해당 장치가 불가능한 것이
무엇인지 정보를 제공하므로, 지문 표면(fingerprinting surface)이 될 수 있습니다.
현재 permission
state를 candidateSet의 모든 후보 장치에 대해 읽되, 현재 MediaStreamTrack
에
연결되어 있지 않은 경우에 한합니다. permission state가 "denied
"인
후보는 candidateSet에서 제거합니다.
이제 candidateSet이 비어 있으면, 해당 타입의 모든 장치가 "denied
"
상태이므로, 아래 PermissionFailure 단계로 이동합니다.
선택적으로, 예를 들어 사전 설정된 사용자 선호도나 보안, 플랫폼 제한으로 인해, 아래 Permission Failure 단계로 이동할 수 있습니다.
candidateSet의 모든 후보를 finalSet에 추가합니다.
stream을 새롭고 빈 MediaStream
객체로
둡니다.
각 미디어 타입 kind에 대해 requestedMediaTypes에 있는 경우, 다음 하위 단계를(가능하다면 동시에) 실행합니다:
User Agent는 서로 다른 종류의 미디어에 대한 동시 요청을 하나의 사용자 권한 프롬프트로 묶는 것이 권장됩니다.
권한
요청을 PermissionDescriptor
와
함께 실행합니다. name
멤버는 kind와 연관된 권한 이름(예: "camera"
는 "video"
에 대해, "microphone"
는
"audio"
에 대해)로
설정합니다. 현재 Document
에서
라이브이면서 동일
권한(same-permission)의 MediaStreamTrack
에
연결된 모든 장치들은 "granted
"
상태로 간주하며, 그 결과로 제공되는 미디어 집합을 얻습니다.
동일
권한(same-permission)이란, 현재 요청하는 것과 동일한 수준의 권한(예: 격리되지
않은 권한)으로 획득된 MediaStreamTrack
를
의미합니다.
사용자에게 권한을 요청할 때, User Agent는 권한이 선택된 장치만 부여되는지, 해당 kind의 모든 장치에 부여되는지 반드시 명시해야 합니다.
사용자가 응답하지 않으면, 이 알고리즘은 해당 단계에서 멈춥니다.
요청 결과가 "denied
"이면,
아래 Permission Failure 단계로 이동합니다.
hasSystemFocus를 false
로 둡니다.
hasSystemFocus가 false
인 동안, User Agent는
반드시 시스템 포커스 있음(has system focus)
알고리즘의 결과로 hasSystemFocus를 true
로 설정하는 작업이 큐에 들어올
때까지 다음 단계로 진행하지 않아야 합니다.
장치 정보 노출 설정을
mediaDevices에 대해 requestedMediaTypes
와
true
로 실행합니다.
각 미디어 타입 kind에 대해 requestedMediaTypes에 있는 경우, 다음 하위 단계를 실행합니다:
finalCandidate를 제공된 미디어로 둡니다. 이는 finalSet에서 kind 타입의 candidate가 정확히 하나여야 합니다. finalSet에서 어떤 candidate를 선택할지는 전적으로 User Agent의 결정에 달려 있으며, 사용자에게 물어 결정할 수 있습니다.
User Agent는 SelectSettings 알고리즘에서 계산된 fitness distance 값을 선택 알고리즘의 입력값으로 사용하는 것이 권장되지만, 사용자 선호도 등 내부적으로 사용 가능한 다른 정보도 사용할 수 있습니다.
이는 필수 제약 조건이 아닌 값들은 보장되지 않는다는 의미입니다.
User Agent는 기본적으로 사용자의 기본 또는 시스템 기본 장치를 kind에 대해 사용하는 것이 권장됩니다(가능하다면). User Agent는 사용자가 미리 녹음된 미디어 파일 등 모든 미디어 소스를 사용할 수 있습니다.
요청 결과가 "granted
"이면,
하드웨어 오류(OS/프로그램/웹페이지 락 등)로 인해 접근이 불가능하면 해당 kind 후보를
finalSet에서 제거합니다. finalSet에 해당
kind 후보가 없으면, promise p를
NotReadableError로 거부하고, 이하 단계를 중단합니다. 그렇지 않으면, 업데이트된
finalSet으로 하위 단계를 다시 시작합니다.
장치 접근이 위 조건 외 이유로 실패하면, 해당 kind 후보를 finalSet에서 제거합니다. finalSet에 해당 kind 후보가 없으면, promise p를 AbortError로 거부하고, 이하 단계를 중단합니다. 그렇지 않으면, 업데이트된 finalSet으로 하위 단계를 다시 시작합니다.
grantedDevice를 finalCandidate의 소스 장치로 둡니다.
grantedDevice의 deviceId deviceId를 사용해서
mediaDevices.[[devicesLiveMap]]
[deviceId]를
true
로(이미 true
가 아니면),
mediaDevices.[[devicesAccessibleMap]]
[deviceId]를
true
로(이미 true
가 아니면) 설정합니다.
track를 MediaStreamTrack
생성의 결과로 둡니다. 인자는 grantedDevice와
mediaDevices입니다. MediaStreamTrack
의
소스는 절대 변경되어서는 안 됩니다.
track을 stream의 트랙 집합에 추가합니다.
stream의 모든 트랙에 대해 ApplyConstraints
알고리즘을 적절한 제약과 함께 실행합니다. 결과가 undefined
가 아니면,
failedConstraint를 그 결과로 두고 아래 Constraint Failure 단계로
이동합니다.
stream의 각 track에 대해 트랙 소스를
MediaDevices
에 연결합니다. 인자는 track.[[Source]]
와
mediaDevices입니다.
promise p를 stream으로 resolve하고 이하 단계를 중단합니다.
NotFound Failure:
getUserMedia
특정 실패 허용 여부가 requestedMediaTypes에 대해
false
를 반환하면, 아래 Permission Failure 단계로
이동합니다.
Constraint Failure:
getUserMedia
특정 실패 허용 여부가 requestedMediaTypes에 대해
false
를 반환하면, 아래 Permission Failure 단계로
이동합니다.
message를 undefined
또는 사용자 친화적 메시지로 두고,
constraint를 장치 정보 노출 가능
여부가 true
이면 failedConstraint로,
아니면 ""
로 둡니다.
promise p를 새로운 OverconstrainedError(constraint, message)로 거부합니다.
Permission Failure: promise p를 NotAllowedError로 거부합니다.
p를 반환합니다.
getUserMedia 특정 실패 허용 여부를 확인하려면, requestedMediaTypes가 주어졌을 때, 다음 단계를 실행합니다:
requestedMediaTypes에 "audio"가 포함되어 있으면, 이름이 "microphone"인 descriptor의 permission state를
읽습니다. 요청 결과가
"denied
"이면,
false
를 반환합니다.
requestedMediaTypes에 "video"가 포함되어 있으면, 이름이 "camera"인 descriptor의 permission state를
읽습니다.
요청 결과가
"denied
"이면,
false
를 반환합니다.
true
를 반환합니다.
위 알고리즘에서는 제약조건을 두 번 확인합니다. 한 번은 장치 선택 시, 한 번은 접근 승인 후입니다. 그 사이에 시간이 경과할 수 있으므로, 선택된 장치가 더 이상 적합하지 않을 수도 있습니다. 이런 경우에는 NotReadableError가 발생합니다.
장치 선택에 허용된 필수 제약조건에는 다음 제약조건 이름이 포함됩니다: width, height, aspectRatio, frameRate, facingMode, resizeMode, sampleRate, sampleSize, echoCancellation, autoGainControl, noiseSuppression, latency, channelCount, deviceId, groupId.
MediaStreamConstraints
딕셔너리는 User Agent에게 MediaStreamTrack
를 어떤 종류로 MediaStream
에 포함시켜 getUserMedia
()
에서 반환할지
지시하는 데 사용됩니다.
WebIDLdictionary MediaStreamConstraints
{
(boolean or MediaTrackConstraints
) video
= false;
(boolean or MediaTrackConstraints
) audio
= false;
};
MediaStreamConstraints
멤버video
타입
(boolean
또는 MediaTrackConstraints
)
,
기본값은 false
true
인 경우, 반환되는 MediaStream
에
비디오 트랙이 포함되도록 요청합니다.
Constraints
구조가 제공되면, 비디오 트랙의 종류와
설정을 더 구체적으로 지정합니다.
false
이면, MediaStream
에는 반드시 비디오 트랙이 포함되지 않아야
합니다.
audio
타입
(boolean
또는 MediaTrackConstraints
)
,
기본값은 false
true
인 경우, 반환되는 MediaStream
에
오디오 트랙이 포함되도록 요청합니다.
Constraints
구조가 제공되면, 오디오 트랙의 종류와
설정을 더 구체적으로 지정합니다.
false
이면 MediaStream
에는 반드시 오디오 트랙이 포함되지 않아야
합니다.
이 섹션은 규범적이지 않습니다.
이 섹션의 getUserMedia() 정의는 원래 제안된 호출 형식을 반영하며, 하위 호환성을 유지하려는 브라우저를 위해서만 문서화되어 있습니다. 권장 인터페이스와는 두 가지 중요한 점에서 다릅니다.
첫째, getUserMedia() 메서드의 공식 정의이자 개발자에게 권장되는 버전은 이제 MediaDevices
에 있습니다. 이 결정은 원래 API가
Navigator 객체에 남아 있는 한 합의된 것으로, 작업 그룹은 이 API의 초기 사용자들이 "var getUserMedia = navigator.getUserMedia
|| navigator.webkitGetUserMedia || navigator.mozGetUserMedia;"와 같이 getUserMedia를 정의하도록 권장받아 왔음을
인식하고 있습니다. 이렇게 하면 현행 표준으로 구현되기 전후에 모두 코드가 동작합니다. 기능적 동등성을 보장하기 위해, 여기의 getUserMedia() 메서드는
MediaDevices의 메서드를 참조하여 정의됩니다.
둘째, 명세의 모든 다른 콜백 기반 메서드를 프라미스 기반으로 변경하기로 결정함에 따라 navigator.getUserMedia() 정의도 navigator.mediaDevices.getUserMedia()를 사용하도록 반영해야 했습니다. navigator.getUserMedia()는 이제 명세에서 남은 유일한 콜백 기반 메서드이므로, a) 이것이 여전히 명세에 남아 있어야 하는지, b) 남아 있다면 문법을 콜백 기반으로 유지할지 아니면 프라미스를 사용할 형태로 바꿔야 하는지에 대한 논의가 진행 중입니다. 특히 현재 이 기능을 실제로 사용하는 개발자의 의견을 환영합니다.
콜백 기반에서 프라미스 기반으로 변경된 다른 메서드들은 레거시 사용을 고려할 만큼 널리 구현된 적이 없다고 판단되어 별도의 레거시 고려가 필요하지 않았습니다.
명세에 부합하기 위해서 반드시 이 인터페이스를 구현할 필요는 없습니다.
WebIDL
getUserMedia
사용자에게 웹캠이나 기타 비디오 또는 오디오 입력 장치 사용 권한을 요청합니다.
constraints 인자는 MediaStreamConstraints
타입의 딕셔너리입니다.
successCallback은 사용자가 getUserMedia
()
및 MediaDevices
에서 설명된 대로
유효한 트랙을 허용하면 적절한 MediaStream
객체로 호출됩니다.
errorCallback은 getUserMedia
()
및 MediaDevices
에서 설명된 대로
유효한 트랙을 찾지 못하거나 사용자가 권한을 거부하면 호출됩니다.
getUserMedia
()
메서드가 호출되면,
User Agent는 반드시 다음 단계를 실행해야 합니다:
constraints를 메서드의 첫 번째 인자로 둡니다.
successCallback을 메서드의 두 번째 인자로 지정된 콜백으로 둡니다.
errorCallback을 메서드의 세 번째 인자로 지정된 콜백으로 둡니다.
getUserMedia() 알고리즘에 constraints를 인자로 하여 지정된 단계를 실행하고, 그 결과를 p라는 프라미스로 둡니다.
프라미스 이행(fulfillment) 시 p의 값 stream에 대해 다음 단계를 실행합니다:
successCallback을 stream을 인자로 호출합니다.
프라미스 거부(rejection) 시 p의 이유 r에 대해 다음 단계를 실행합니다:
errorCallback을 r을 인자로 호출합니다.
이 섹션은 규범적이지 않습니다.
User Agent는 getUserMedia
()
호출이
성공할 것으로 판단되면 자원을 미리 예약하는 것이 권장됩니다. 반환된 promise가 resolve되기 전에 자원을 예약하는 것이 바람직합니다.
이후 getUserMedia
()
의 추가
호출(이 페이지 또는 다른 페이지)에서는 이전에 할당된 자원과 다른 애플리케이션이 점유 중인 자원을 모두 사용 중(busy)으로 처리해야 합니다. busy로 표시된 자원은 사용자가
명시적으로 지정하지 않는 한 현재 웹페이지의 소스로 제공되어서는 안 됩니다. 선택적으로,
User Agent는 busy 상태의 소스로부터 스트림을 제공하되, 해당 소스를 점유 중인 원본 스트림의
소유자와 오리진이 일치하는 페이지만 허용할 수 있습니다.
이 문서에서는 권한 부여 대화상자 또는 장치 선택 인터페이스(있을 경우)에서 사용자가 페이지가 요청한 스트림의 소스로 사용할 수 있는 모든 사용 가능한 하드웨어를 선택할 수 있도록 하는 것을 권장합니다(자원이 명시된 필수 제약조건을 만족할 수 있는 경우에 한함). 특별히 권장되는 사항은 아니지만, 일부 User Agent는 비디오/오디오 소스를 로컬 파일 및 기타 미디어로 대체할 수 있도록 지원할 수 있습니다. 파일 선택기(file picker)를 통해 이 기능을 제공할 수도 있습니다.
또한 이 문서는 사용자가 이전 getUserMedia() 호출(이 페이지 또는 아직 살아 있는 다른 페이지에서 발생한)의 결과로 현재 busy 상태인 모든 자원을 볼 수 있게 하고, 해당 스트림을 종료하여 현재 페이지에서 그 자원을 사용하도록 선택할 수 있게 하는 것을 권장합니다. 현재 운영 환경에서 가능하다면, 다른 애플리케이션이 점유 중인 자원도 동일하게 표시하고 처리하는 것이 좋습니다. 사용자가 이 옵션을 선택하면, 영향을 받은 스트림을 제공한 페이지에서 해당 자원에 대응하는 트랙은 반드시 제거되어야 합니다.
기기 사용 권한이 요청될 때, User Agent는 동일 오리진에서 나중에 사용할 수 있도록 이 권한을 저장하도록 선택할 수 있습니다. 이렇게 하면 사용자가 나중에 다시 권한을 부여할 필요가 없어집니다. User Agent는 각 장치별, 특정 클래스의 모든 장치, 혹은 모든 장치에 대해 권한 저장 기능을 제공할지 선택할 수 있고, 이 선택은 사용자에게 명확하게 제공되어야 하며, 권한이 저장되는 전체 집합에 대해 실제로 권한이 부여되어야 합니다. 예를 들어, 모든 카메라 사용 권한을 저장하려면 사용자가 모든 카메라에 대한 권한을 실제로 부여했어야 하며, 단일 카메라만 허용한 경우에는 저장할 수 없습니다.
이 명세가 설명한 대로, 권한 부여가 저장된 권한을 의미하는지 여부는 명세에서 강제하지 않습니다. 권한이 저장되지 않은 경우, 권한은 해당 기기를 소스로 하는 모든 MediaStreamTrack이 중지될 때까지만 유지됩니다.
MediaStream
에는 두 개 이상의 비디오 및 오디오 트랙이 포함될 수
있습니다. 예를 들어, 여러 웹캠의 비디오를 하나의 스트림 객체에 포함시킬 수 있습니다. 단, 현재 API는 페이지에서 독립 소스로부터 여러 비디오 스트림을 요구하는 기능을
제공하지 않습니다.
같은 페이지에서 getUserMedia()를 여러 번 호출하여 여러 개의 분리된 비디오/오디오 스트림을 요청할 수 있도록 허용하는 것이 권장됩니다.
또한 페이지가 여러 번 getUserMedia()를 호출할 경우, 자원을 요청하는 순서와 완료되는 순서는 이 명세에서 제한하지 않습니다.
한 번의 getUserMedia() 호출은 항상 오디오 트랙 0~1개, 비디오 트랙 0~1개를 포함하는 스트림을 반환합니다. 스크립트가 안정된 상태에 도달하기 전 여러 차례 getUserMedia()를 호출하는 경우, UI 디자이너에게 권장되는 사항은 권한 대화상자를 통합하여 사용자가 여러 카메라 및/또는 미디어 소스에 동시에 권한을 부여할 수 있게 하는 것입니다. 각 getUserMedia 호출에 대한 제약조건을 활용해 각 스트림이 어떤 미디어 소스를 사용할지 결정할 수 있습니다.
deviceId
생성에 효율적인 방법은 프라이빗 키 +
(오리진 또는 오리진 + 최상위 오리진, user agent의 파티셔닝 규칙에 따름) + salt + 드라이버의 하드웨어 id를 조합해 암호학적 해시값을 생성하고, 결과 해시를
영숫자 문자열로 제공하는 것입니다.
해시값은 충돌 위험을 피하기 위해 32비트 이하(너무 낮게는 하지 말 것)가 권장됩니다.
저장소 비용을 감수한다면, 더 낮은 엔트로피 대안으로 각 오리진 또는 오리진+최상위 오리진(파티셔닝 규칙에 따름)에 대해 새로 발견되는 각 장치에 0~255의 숫자를 무작위로 부여하고, 번호가 다 소진되면 가장 오래 사용되지 않은 번호를 폐기하는 방법도 있습니다.
카메라나 마이크로부터 소스되는 트랙은 사용자의 프라이버시 관리를 위해 음소거될 수 있습니다. 하지만 이렇게 하면 웹 호환성 문제나 사용자 활동 정보 노출 위험이 생길 수 있으므로 주의가 필요합니다.
다음과 같은 경우에는 카메라나 마이크 트랙을 음소거하는 것이 모범 사례입니다:
OS 레벨 이벤트로 User Agent가 이미 전체 미디어 재생을 일시 중단하지만 JavaScript는 중단하지 않는 경우. 사용자가 이러한 상황에서 캡처가 계속된다면 놀랄 수 있으므로(의도적으로 설정한 경우가 아니라면), 캡처가 중단됨을 알리는 것이 합리적인 프라이버시 트레이드오프입니다. 만약 OS 이벤트로 이미 트랙에 프레임이 들어오지 않는다면, 새로운 사용자 활동 정보가 노출되지 않습니다. 그렇지 않은 경우에도, 캡처가 종료되는 사실을 알리는 것이 캡처가 계속되는 것보다 더 합리적인 선택입니다.
웹 페이지가 뷰에 있지 않은 상태에서 모든 소스 트랙이 비활성화된 이후, 트랙을 다시 활성화할 때, 캡처가 페이지가 뷰에 있을 때까지 재개를 지연시키기 위해서입니다.
다음과 같은 경우에는 이전에 음소거된 카메라/마이크 트랙을 음소거 해제(unmute)하는 것이 모범 사례입니다:
OS 레벨 이벤트로 User Agent가 이미 전체 미디어 재생을 재개하고, 그리고 페이지가 사용자에게 보이는 경우(예: 잠금화면 아님). User Agent는 이전 캡처 세션에 대한 사용자의 인식에 영향을 줄 만큼 충분히 시간이 지났다고 판단되면 해제 동작을 지연할 수 있습니다.
제약 가능 패턴은 해당 패턴을 구현하는 객체(즉, 제약 가능 객체)의 속성을 애플리케이션이 확인하고 조정할 수 있게 합니다. 이 패턴은 별도의 정의 집합으로 분리되어 있어 다른 명세에서
참조할 수 있습니다. 핵심 개념은 Capability(능력, 지원 가능성)이며, 이는 객체의 제약 가능한 속성과 그 속성의 가능한 값 집합(범위나 열거형으로 지정될 수 있음)으로 구성됩니다.
예를 들어, 카메라는 1초당 20~50 프레임(범위)이라는 프레임레이트(속성)를 지원할 수 있고, 사용자 쪽/반대쪽/왼쪽/오른쪽(열거된 집합)으로 위치시킬 수 있습니다. 애플리케이션은
getCapabilities()
접근자를 통해 제약 가능한 속성의 지원 Capability를 확인할 수 있습니다.
애플리케이션은 기본 및/또는 고급 ConstraintSet과 applyConstraints()
메서드를 사용하여 객체 Capability의 원하는 값(범위)을 선택할 수
있습니다. ConstraintSet은 객체의 하나 이상의 속성 이름과 각각의 원하는 값(혹은 값의 범위)으로 구성됩니다. 각 속성/값 쌍은 각각 하나의 개별 제약(constraint)으로 볼 수
있습니다. 예를 들어, 애플리케이션은 두 개의 constraint가 포함된 ConstraintSet을 설정할 수 있는데, 첫 번째는 카메라 프레임레이트를 1초당 30~40 프레임(범위)로 하고,
두 번째는 카메라가 사용자를 바라보도록(특정 값) 지정합니다. 각각의 constraint가 상호작용하는 방식은, 기본 Constraint 구조(추가 'advanced' 속성이 포함된
ConstraintSet)에서 제시되는지, 아니면 advanced 리스트 내의 ConstraintSet에 있는지에 따라 달라집니다. 동작 방식은 다음과 같습니다: 기본 Constraint 구조의
모든 'min', 'max', 'exact' constraint는 필수 제약조건으로 함께 처리되며, 해당 속성 이름에 대해 이 개별
constraint들을 동시에 만족시킬 수 없는 경우 User Agent는 반드시 반환되는 promise를 거부해야 합니다. 그렇지 않으면 필수 제약조건을 적용하게
됩니다. 그 다음,
advanced
리스트에
지정된 ConstraintSet들을 주어진 순서대로 고려하며, 각각의 ConstraintSet(즉, 해당 ConstraintSet의 모든 constraint를 함께)을 만족/적용하려고
시도하지만, 해당 ConstraintSet 전체를 만족/적용할 수 없는 경우에만 건너뜁니다. 그 다음, User Agent는 반드시 'ideal' constraint나 속성에 대해 값 자체만 지정된 constraint(선택적 기본 제약조건)을 개별적으로 적용하려고 시도해야 합니다.
이들 속성 중 반드시 가능한 최대한 많은(순서는 상관없음) constraint를 만족시켜야 합니다. 마지막으로 User Agent는 반드시 반환되는 promise를 resolve해야 합니다.
getSupportedConstraints()
를 통해 사용하려는 속성 이름들이 모두 User Agent에서 지원되는지 먼저
확인해야 합니다. 그 이유는 WebIDL이 제약 조건을 담는 딕셔너리에서 지원되지 않는 이름을 자동으로 제거하므로, User Agent에서 이를 볼 수
없고, 지원되지 않는 이름은 조용히 무시됩니다. 이로 인해 자바스크립트 코드에서는 제약조건을 설정한다고 생각하지만, User Agent에서는 무시되기
때문에 혼란스러운 프로그래밍 오류가 발생할 수 있습니다. 이름은 지원하지만 constraint를 만족시킬 수 없는 경우 User Agent는 오류를 생성하고,
제약 가능한 속성을 지원하지 않는 경우 User Agent는 오류를 생성하지 않습니다.
다음 예시들은 제약조건이 어떻게 동작하는지 이해하는 데 도움이 될 수 있습니다. 첫 번째는 기본 Constraint 구조를 보여줍니다. 세 개의 constraint가 주어지며, 각각 User Agent가 개별적으로 만족시키려고 시도합니다. 이 카메라에서 사용 가능한 해상도에 따라 세 개 모두 동시에 만족시킬 수 없을 수도 있습니다. 그렇다면 User Agent는 두 개만 만족시키거나, 두 개도 동시에 만족시킬 수 없다면 한 개만 만족시킬 수 있습니다. 세 개 모두 동시에 만족시킬 수 없다면, 두 개의 constraint 조합이 여러 가지일 수도 있는데, 이 경우 어떤 조합을 선택할지는 User Agent가 선택합니다.
const stream = await navigator.mediaDevices.getUserMedia({
video: {
width: 1280,
height: 720,
aspectRatio: 3/2
}
});
다음 예시는 약간의 복잡성이 추가된 것입니다. width와 height에 대해 이상적인 값(ideal)이 여전히 제공되지만, 각각에 대해 최소값(min) 요구사항과 반드시 만족시켜야 하는 최소 frameRate도 추가되었습니다. frameRate나 width, height의 최소값을 만족시킬 수 없다면 promise를 거부합니다. 그렇지 않으면 width, height, aspectRatio 목표값도 만족시키려고 시도한 뒤 promise를 resolve합니다.
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;
}
// Overconstrained. Try again with a different combination (no prompt was shown)
}
이 예시는 Constraints 구조에 'advanced' 속성을 추가하여 제약조건의 전체 제어가 가능한 것을 보여줍니다. 이 경우 User Agent는 필수 제약조건에 대해 이전과 동일하게 동작하지만, 이상적인 값(ideal)을 만족시키려고 시도하기 전에 'advanced' 리스트를 처리합니다. 이 예시에서 'advanced' 리스트에는 두 개의 ConstraintSet이 들어 있습니다. 첫 번째는 width와 height 제약조건을, 두 번째는 aspectRatio 제약조건을 지정합니다. advanced 리스트 안의 값들은 'exact' 값으로 처리됩니다. 이 예시는 다음을 의미합니다: "비디오가 최소 640px 너비, 최소 480px 높이여야 한다. 내가 원하는 건 정확히 1920x1280이지만, 불가능하다면 가능하면 4x3 aspectRatio를 달라. 그것도 안 되면 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;
}
// Overconstrained. Try again with a different combination (no prompt was shown)
}
고급 ConstraintSet의 순서는 중요합니다. 위 예시에서는 1920x1280 ConstraintSet과 4x3 aspect ratio ConstraintSet을 동시에 만족시키는 것은 불가능합니다. 1920x1280이 리스트에서 먼저 나오므로 User Agent가 먼저 그 값을 만족시키려고 시도합니다. 따라서 애플리케이션 작성자는 동일 속성에 대해 여러 개의 고급 ConstraintSet을 지정하여 백오프(backoff) 전략을 구현할 수 있습니다. 애플리케이션은 frame rate가 50 이상인 ConstraintSet과 40 이상인 ConstraintSet도 추가로 지정합니다. User Agent가 50 이상의 frame rate를 설정할 수 있다면 그렇게 하고, 이후 ConstraintSet은 자동으로 만족됩니다. 반면 User Agent가 50 이상의 frame rate를 설정할 수 없다면 해당 ConstraintSet은 건너뛰고 40 이상을 시도합니다. 두 ConstraintSet 모두 만족시킬 수 없다면, 기본 ConstraintSet의 'min' 값이 30 이상을 요구하므로 User Agent가 30 이상을 얻을 수 없으면 전체적으로 실패하게 됩니다. 가능하다면 50 이상, 그게 안 되면 40 이상을 선택하려고 시도합니다.
기본 제약조건과 달리, 고급 리스트의 ConstraintSet 내 제약조건들은 반드시 모두 함께 만족하거나, 모두 함께 건너뛰어야 합니다. 따라서 {width: 1920, height:
1280}은 특정 해상도를 요청하는 것이지 해당 width나 height 중 하나를 요청하는 것이 아닙니다. 기본 제약조건은 개별 제약의 'or'(비독점적) 요청으로, 각 고급
ConstraintSet은 해당 Set 내 개별 제약의 'and' 요청으로 볼 수 있습니다. 애플리케이션은 getConstraints()
접근자를 통해 적용 중인 전체
Constraint 집합을 확인할 수 있습니다.
User Agent가 제약 가능한 속성에 대해 선택하는 구체적 값은 Setting(설정값)이라고 불립니다. 예를 들어,
애플리케이션이 frameRate를 30 이상 40 이하로 설정하는 ConstraintSet을 적용했다면, Setting은 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()
메서드는 객체가 지원하는 제약 가능한 속성들의 이름 딕셔너리를 반환합니다. 호출 시 User
Agent는 반드시 [[Capabilities]] 내부 슬롯의 값을 반환해야 합니다.
하드웨어가 제약 가능한 속성에 대해 정의된 범위에 정확히 대응하지 않을 수 있습니다. 이런 경우, 항목은 하드웨어 설정을 해당 속성 값에 어떻게
변환/스케일링할지 정의하는 것이 권장됩니다. 예를 들어, 가상의 fluxCapacitance 속성이
-10(최소)~10(최대) 범위를 가진다고 할 때, 실제 하드웨어는 "off", "medium", "full"만 지원할 수 있습니다. 제약
가능한 속성 정의는 이런 하드웨어에 대해 User Agent가 -10을 "off", 10을 "full", 0을
"medium"으로 변환하도록 지정할 수 있습니다. ConstraintSet이 3으로 엄격하게 지정된 경우, User Agent는 하드웨어에 "medium"을 설정하려 시도하며,
getSettings
()
는 fluxCapacitance를 0으로 반환해야 합니다. 이는 "medium"에 대응되는 값입니다.
getConstraints
getConstraints()
메서드는 객체에서 최근
성공적으로 호출된 ApplyConstraints
알고리즘에 사용된 Constraints 인자를 순서대로 반환합니다. 반환된 advanced ConstraintSet 중 일부는 현재 만족되지
않을 수 있습니다. 현재 적용 중인 ConstraintSet을 확인하려면 getSettings
를
사용하세요.
위 설명과 정확히 일치하는 constraint를 반환하지 않고, 모든 상황에서 적용된 constraint와 동일한 효과를 갖는 constraint set을
반환할 수도 있습니다. 호출 시 User Agent는 반드시 [[Constraints]] 내부 슬롯의 값을
반환해야 합니다.
getSettings()
메서드는 객체의 모든 제약
가능한 속성의 현재 설정값을 반환합니다. 이 값은 플랫폼 기본값이거나 ApplyConstraints 알고리즘으로 설정된 값일 수
있습니다. 설정값은 제약조건을 만족시키는 목표값이며, 측정된 실제 성능과 다를 수 있습니다. 호출 시 User Agent는 반드시 [[Settings]] 내부 슬롯의 값을 반환해야
합니다.
applyConstraints 템플릿 메서드가 호출되면, User Agent는 반드시 다음 단계를 실행해야 합니다:
object를 이 메서드가 호출된 객체로 둡니다.
newConstraints를 이 메서드의 인자로 둡니다.
p를 새로운 프라미스로 둡니다.
다음 단계를 병렬로 실행하며, 이 메서드가 여러 번 호출될 경우 호출 순서를 유지합니다:
failedConstraint를 ApplyConstraints 알고리즘을 newConstraints 인자로 실행한 결과로 둡니다.
successfulSettings를 위 알고리즘 실행 후 객체의 현재 설정값으로 둡니다.
다음 단계를 실행하는 작업을 큐에 넣습니다:
failedConstraint가 undefined
가 아니면,
message를 undefined
또는 정보성 메시지로 둡니다. p를 새로운
OverconstrainedError(failedConstraint,
message)로 거부하고, 이하 단계는 중단합니다. 이 경우 기존
constraint는 그대로 유지됩니다.
object의 [[Constraints]]
내부 슬롯을 newConstraints 또는 newConstraints와
모든 상황에서 동일한 효과를 내는 Constraints
딕셔너리로 설정합니다.
object의 [[Settings]] 내부 슬롯을 successfulSettings로 설정합니다.
p를 반환합니다.
제약조건 적용을 위한 ApplyConstraints 알고리즘은 아래에 정의되어 있습니다. 알고리즘 설명에 사용되는 몇 가지 정의는 다음과 같습니다:
settings dictionary란 객체에 설정값으로 적용될 수 있는 값들의 집합입니다.
문자열 값 constraint의 경우, 아래의 "=="는 시퀀스 내 값 중 비교값과 정확히 같은 값이 있으면 true로 정의합니다.
settings dictionary와 constraint set CS의 fitness distance는 CS 내의 각 멤버(constraintName과 constraintValue 쌍)에 대해 다음 값을 합산한 것입니다:
constraintName이 User Agent에 의해 지원되지 않는 경우, fitness distance는 0이다.
만약 constraint가 required (constraintValue에 'min', 'max', 또는 'exact'라는 이름의 멤버가 하나 이상 포함되어 있거나, advanced ConstraintSet에서 자체적으로 값만 있는 경우)이고, settings dictionary의 constraintName 멤버의 값이 constraint를 만족하지 않거나 존재하지 않으면, fitness distance는 양의 무한대이다.
constraint가 이 객체 타입에 적용되지 않는 경우, fitness distance는 0이다 (즉, constraint는 fitness distance에 영향을 주지 않는다).
constraintValue가 boolean이지만, constrainable property가 boolean이 아닌 경우, fitness distance는 settings dictionary의 constraintName 멤버가 존재하는지에 따라 아래 공식에 의해 계산된다.
(constraintValue == exists) ? 0 : 1
settings dictionary의 constraintName 멤버가 존재하지 않으면, fitness distance는 1이다.
(actual == ideal) ? 0 : |actual - ideal| / max(|actual|, |ideal|)
(actual == ideal) ? 0 : 1
추가 정의:
SelectSettings 알고리즘은 다음과 같이 정의됩니다:
알 수 없는 속성은 WebIDL에 의해 버려지므로, 알 수 없거나 지원되지 않는 필수 constraint는 조용히 사라집니다. 이를 사용자에게
혼란을 주지 않도록, 애플리케이션 작성자는 아래 예시처럼 getSupportedConstraints
()
메서드 사용을 우선해야 합니다.
ConstrainablePattern
알고리즘이 적용되는 객체로 둡니다. copy를 object의 unconstrained 복제본(즉, 모든
ConstraintSet이 제거된 상태로 동작)으로 둡니다.
copy의 가능한 모든 settings dictionary에 대해 fitness distance를 계산하며, 속성의 bare value는 ideal로 처리합니다. fitness distance가 유한한 settings dictionary 집합을 candidates로 둡니다.
candidates가 비어 있으면, SelectSettings
알고리즘의 결과로 undefined
를 반환합니다.
candidates의 각 settings dictionary에 대해 fitness distance를 계산하며, bare value는 exact로 처리합니다.
fitness distance가 유한한 settings dictionary가 하나 이상 있으면, 해당 settings dictionary만 candidates에 남기고, 나머지는 버립니다.
fitness distance가 모든 settings dictionary에 대해 무한대면, 해당 ConstraintSet은 무시합니다.
candidates에서 하나의 settings dictionary를 선택하여 SelectSettings 알고리즘의 결과로 반환합니다. User Agent는 반드시 fitness distance가 가장 작은 것을 사용해야 하며(3단계에서 계산), 여러 개면 시스템 기본값 및 User Agent 기본값을 기준으로 선택합니다.
선택된 장치에 시스템 기본값이 있는 속성은, 위 알고리즘과 호환된다면 시스템 기본값을 사용하는 것이 권장됩니다. 이는 sampleRate나 sampleSize 같은 속성에 해당합니다. echoCancellation이나 resizeMode 같은 속성은 일반적으로 시스템 기본값이 없습니다. User Agent는 이런 속성에 대해 자체 기본값을 정의합니다. 구현자는 기본값 선정에 신중해야 하며, 이는 미디어 콘텐츠 생성 방식에 영향을 줍니다.
의미 있는 기본값을 선택하려면 기존 구현을 참고하는 것이 권장됩니다. 기본값은 시스템에 따라 다를 수 있습니다(예: 데스크톱 vs 모바일). 작성 시점 기준, User Agent 구현체는 RTCPeerConnection을 sink로 사용할 때 적합하도록 다음과 같은 기본값을 사용합니다:
width 640.
height 480.
frameRate 30.
echoCancellation
true
.
ApplyConstraints 알고리즘을 object에 newConstraints 인자로 적용하려면, User Agent는 반드시 다음 단계를 실행해야 합니다:
successfulSettings를 SelectSettings 알고리즘을 newConstraints constraint set으로 실행한 결과로 둡니다.
successfulSettings가 undefined
면,
failedConstraint를 필수 제약조건 중 SelectSettings 알고리즘
실행 시 모든 settings dictionary에서 fitness distance가 무한대였던 것을 선택하고(없으면
""
), 반환하고 이하 단계를 중단합니다.
undefined
반환.위 알고리즘과 동일한 결과를 내는 모든 구현은 허용됩니다. 즉, 구현은 constraint가 고려된 설정값에 대해 최대/최소값만 추적할 수도 있고, 가능한 모든 값을 추적할 수도 있습니다.
settings dictionary를 선택할 때, UA는 사용할 수 있는 모든 정보를 사용할 수 있습니다. 예시로는 선택이 getUserMedia 장치 선택의 일부로 이뤄지는지, 카메라 설정에 따라 에너지 사용량이 달라지는지, 설정값 사용 시 장치 드라이버가 리샘플링을 적용하는지 등이 있습니다.
User Agent는 객체의 제약 가능한 속성에 대해 언제든 새로운 설정값을 선택할 수 있습니다. 이때 반드시 위 알고리즘대로 모든 현재 Constraint를 만족시키려고 시도해야 하며, successfulSettings를 결과값으로 하여 다음 단계를 실행하는 작업을 큐에 넣습니다:
object를 제약 가능한 속성의 새로운 설정값이 변경된
객체로 둡니다.
ConstrainablePattern
object의 [[Settings]] 내부 슬롯을 successfulSettings로 설정합니다.
아래는 applyConstraints
()
에 전달하거나
constraints
값으로 반환될 수 있는 Constraints 예시입니다.
카메라에서 소스되는 제약 가능한 속성을 사용하며,
MediaStreamTrack
에 대해 정의되어 있습니다.
이 예시에서는 모든 constraint가 ideal 값이므로, 결과는 사용자의 카메라에 따라 "최대한 노력" 방식으로 반환됩니다:
await track.applyConstraints({
width: 1920,
height: 1080,
frameRate: 30,
});
const {width, height, frameRate} = track.getSettings();
console.log(`${width}x${height}x${frameRate}`); // 1920x1080x30, 또는 예를 들어
// 1280x720x30 같이 best effort
더 세밀한 제어를 위해, 애플리케이션은 정확한 일치(exact match)를 요구할 수 있으며, 실패 처리를 준비해야 합니다:
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
에도 전달할 수 있습니다. 이는 초기화의
편의뿐 아니라 장치 선택에도 영향을 줄 수 있습니다.
이 경우
고유 제약조건
또한 사용할 수 있습니다.
아래는 이전 방문에서 사용한 특정 카메라와 마이크를 선호하며, 해상도 요구 조건과 스테레오 선호를 포함하고, 권한이 부여되면 적용하고, 요청한 장치가 더 이상 사용 불가할 경우(혹은 일부 user agent에서 사용자가 변경한 경우) 적합한 대체 장치를 쉽게 찾도록 하는 constraints 활용 예시입니다.
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;
}
// Overconstrained. 적합한 대체 장치 없음
}
위 예제는 {exact: deviceId}
를 사용하지 않으므로,
브라우저가 사용자 선호도나 장치의 부재와 같은 장치에 대한 내부 정보를
제공된 deviceId
보다 우선적으로 사용할 수 있습니다.
또한, 예제에서는 새로운 선택일 수 있으므로
매번 권한이 부여될 때마다 deviceId
를 저장합니다.
반대로, 아래는 constraints를 사용하여 콘텐츠 내 카메라 선택기를 구현하는 예시입니다. 이 경우 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으로"라는 요구를 두 단계로 처리하는 예시입니다. 먼저 네이티브 모드를 찾고, 두 번째 단계에서 커스텀 프레임레이트를 적용합니다. 현재 설정에서 constraint를 유도하는 방법(회전될 수 있음)도 보여줍니다:
async function nativeResolutionButDecimatedFrameRate() {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
resizeMode: 'none', // 네이티브 해상도 및 프레임레이트 의미
width: 1280,
height: 720,
aspectRatio: 16 / 9 // aspect ratio는 정확하지 않을 수 있음
}
});
const [track] = stream.getVideoTracks();
const {width, height, aspectRatio} = track.getSettings();
// constraint는 가로 모드, setting은 회전되어 있을 수 있음
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
를 활용한 예시입니다. 이는 특정 constraint가 user agent에서 지원되지 않아 무시되는 경우를 애플리케이션이 허용하지 않을 때 사용할 수 있습니다:
async function getFrontCameraRes() {
const supports = navigator.mediaDevices.getSupportedConstraints();
for (const constraint of ["facingMode", "aspectRatio", "resizeMode"]) {
if (!(constraint in supports) {
throw new OverconstrainedError(constraint, "Not supported");
}
}
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 범위 등이 포함됩니다.
리스트 값은 반드시 논리합(disjunction)으로 해석해야 합니다. 예를 들어, 카메라 속성 'facingMode'의 유효 값이
["left", "right", "user", "environment"]로 정의되었다면 이는 'facingMode'가 "left", "right", "environment",
"user"의 값을 가질 수 있음을 의미합니다. 마찬가지로 Constraints
가 'facingMode'를 ["user", "left",
"right"]로 제한한다면 User Agent는 카메라를 선택하거나(가능하다면 카메라 방향을 조정) "facingMode"가 "user",
"left", "right" 중 하나가 되도록 해야 합니다. 이 제약조건은 카메라가 사용자를 등지지 않도록 요청하지만, User Agent가 사용자가 다른
방향을 선택할 수 있도록 허용할 수도 있습니다.
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 또는 ConstrainULongRange
) ConstrainULong
;
ConstrainULong
식별자는 ([Clamp] unsigned long 또는
ConstrainULongRange) 타입을 의미합니다.
WebIDLtypedef (double 또는 ConstrainDoubleRange
) ConstrainDouble
;
ConstrainDouble
식별자는 (double 또는 ConstrainDoubleRange) 타입을 의미합니다.
WebIDLtypedef (boolean 또는 ConstrainBooleanParameters
) ConstrainBoolean
;
ConstrainBoolean
식별자는 (boolean 또는 ConstrainBooleanParameters) 타입을 의미합니다.
WebIDLtypedef (DOMString 또는
sequence<DOMString> 또는
ConstrainDOMStringParameters
) ConstrainDOMString
;
ConstrainDOMString
식별자는 (DOMString 또는 sequence<DOMString> 또는
ConstrainDOMStringParameters) 타입을 의미합니다.
WebIDLtypedef (boolean 또는 DOMString 또는 ConstrainBooleanOrDOMStringParameters
) ConstrainBooleanOrDOMString
;
ConstrainBooleanOrDOMString
식별자는
(boolean 또는 DOMString 또는 ConstrainBooleanOrDOMStringParameters)
타입을 의미합니다.
Capabilities
는 하나 이상의 키-값 쌍을 포함하는 딕셔너리로, 각 키는 반드시 제약 가능한 속성이어야 하며, 각 값은 반드시 해당 속성에 대해 허용된 값 집합의
부분집합이어야 합니다. 값 표현의 정확한 문법은 속성 타입에 따라 다릅니다. Capabilities 딕셔너리는 제약 가능 객체에
constraints로 적용할 수 있는 제약 가능한 속성을 명시합니다. 제약 가능 객체의 Capabilities는 웹 플랫폼에 정의된
속성의 부분집합일 수 있으며, 해당 속성의 값 집합도 부분집합일 수 있습니다. Capabilities는 User Agent에서 애플리케이션으로
반환되며, 애플리케이션에서 지정할 수 없습니다. 하지만 애플리케이션은 Constraints를 통해 User Agent가 제약 가능한
속성에 대해 선택하는 Settings를 제어할 수 있습니다.
Capabilities 딕셔너리의 예시는 아래와 같습니다. 이 경우 제약 가능 객체는 매우 제한된 Capability를 가진 비디오 소스입니다.
{
frameRate: {min: 1.0, max: 60.0},
facingMode: ['user', 'left']
}
다음 예시는 범위 값에 대한 capabilities가 개별 제약 가능한 속성의 범위를 제공하며, 속성 조합이 아님을 강조합니다. 이는 특히 비디오 width와 height에서 중요하며, width와 height의 범위는 각각 따로 보고됩니다. 예시에서 제약 가능 객체가 640x480과 800x600 해상도만 제공할 수 있다면 관련 capabilities는 다음과 같습니다:
{
width: {min: 640, max: 800},
height: {min: 480, max: 600},
aspectRatio: {min: 4/3, max: 4/3}
}
위 예시에서 aspectRatio는 width와 height의 임의 조합이 불가능함을 명확히 해줍니다. 하지만 2개 이상의 해상도가 사용 가능하다는 암시도 할 수 있습니다.
A 현행 표준을 따르는 명세는 아래 딕셔너리를 서브클래싱하지 말고 자체 정의를 제공해야 합니다. 예시는MediaTrackCapabilities
를 참고하세요.
WebIDLdictionary Capabilities
{};
Settings
는 하나 이상의 키-값 쌍을 포함하는 딕셔너리입니다. 반드시 객체 타입에 대해 정의된 속성에 한해 getCapabilities()
에서 반환된 각 키를 포함해야 합니다. 예를
들어, 오디오 MediaStreamTrack
에는
"width" 속성이 없습니다. 각 키에는 반드시 단일 값만 있을 수 있고, 반드시 해당 속성에
대해 getCapabilities()
로 정의된 값 집합의 멤버여야 합니다. Settings
딕셔너리는 User Agent가 객체의 제약
가능한 속성에 대해 실제로 선택한 값을 포함합니다. 값의 정확한 문법은 속성 타입에 따라 다릅니다.
현행 표준을 따르는 User Agent는 이 명세에 정의된 모든 제약 가능한 속성을 반드시 지원해야 합니다.
Settings 딕셔너리의 예시는 아래와 같습니다. 실제 User Agent라면 이보다 더 많은 제약 가능한 속성을 지원해야 합니다.
{
frameRate: 30.0,
facingMode: 'user'
}
MediaTrackSettings
를 참고하세요.
WebIDL의 한계로 인해, Constrainable Pattern을 구현하는 인터페이스는 여기 정의된 Constraints와 ConstraintSet을 단순히 서브클래싱할 수 없습니다. 대신 이 패턴을 따르는 자체 정의를 제공해야 합니다. 예시는 MediaTrackConstraints를 참고하세요.
WebIDLdictionary ConstraintSet
{};
ConstraintSet
의 각 멤버는 제약 가능한 속성에 대응하며, 해당 속성의 유효 Capability
값 집합의 부분집합을 지정합니다. ConstraintSet을 적용하면 User Agent가 해당 제약 가능한 속성의 설정값을 지정된 값이나 값 범위로
제한하도록 지시합니다. 특정 속성은 기본 Constraints 집합과 advanced ConstraintSets 리스트 모두에 나타날 수
있으며, advanced 리스트의 각 ConstraintSet에는 최대 한 번만 나타날 수 있습니다.
WebIDLdictionary Constraints
: ConstraintSet
{
sequence<ConstraintSet
> advanced
;
};
advanced
타입 sequence<ConstraintSet
>이 리스트는 User Agent가 반드시 순서대로 만족시키려고
시도해야 하는 ConstraintSet 목록입니다. 만족시킬 수 없는 ConstraintSet만 건너뜁니다. 이 ConstraintSet의 순서는 중요합니다. 특히
applyConstraints
의 인자로 전달될 때, User
Agent는 반드시 지정된 순서대로 만족시키려고 시도해야 합니다. 따라서 advanced
ConstraintSets C1과 C2가 각각 개별적으로 만족될 수 있지만 함께 만족될 수 없다면, 이 목록에서 먼저 오는 C1 또는 C2가 만족되고, 다른 하나는
만족되지 않습니다. User Agent는 반드시 목록의 모든
ConstraintSet을 만족시키려고 시도해야 하며, 일부가 만족되지 않더라도 시도해야 합니다. 예를 들어, C3가 C1, C2 다음에 지정되었다면, C2가
만족되지 않더라도 User Agent는 C3를 만족시키려고 시도합니다. 특정 속성 이름은 각
ConstraintSet에 한 번만 나타날 수 있지만, 여러 ConstraintSet에 나타날 수 있습니다.
이 샘플 코드는 버튼을 노출합니다. 클릭하면 버튼이 비활성화되고 사용자에게 스트림을 제공하라는 프롬프트가 표시됩니다. 사용자는 스트림을 제공(예: 페이지에 로컬 카메라 접근 허용)한 후 그 스트림을 비활성화(예: 접근 권한 취소)하여 버튼을 다시 활성화할 수 있습니다.
<button id="startBtn">Start</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>Snapshot Kiosk</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>
이 명세는 강력한 기능 두 가지를
정의하며,
name으로 식별됩니다:
"camera"
와
"microphone"
.
다음 타입과 알고리즘을 정의합니다:
WebIDLdictionary CameraDevicePermissionDescriptor
: PermissionDescriptor {
boolean panTiltZoom
= false;
};
권한은 해당 종류의 장치 중 적어도 하나 이상에 대한 접근을 보장합니다.
descriptor의 의미는 해당 종류의 모든 장치에 대한 접근을 질의한다는 것입니다.
따라서 "camera"
권한 질의에 "granted
"가
반환되면,
클라이언트는 권한 프롬프트 없이 카메라 하나에 접근 가능함을 알 수 있고,
"denied
"가
반환되면,
카메라에 대해 getUserMedia 요청이 성공하지 않음을 알 수 있습니다.
User Agent가 해당 종류의 일부 장치에는 권한을 부여하고 일부에는 부여하지 않은 경우, 질의는
"granted
"를
반환합니다.
User Agent가 해당 종류의 모든 장치에 대해 권한을 거부한 경우, 질의는
"denied
"를
반환합니다.
{name: "camera", panTiltZoom: true}
는 더 강력함
{name: "camera", panTiltZoom: false}
보다.
"granted
"
권한은 getUserMedia가 성공한다는 보장과는 다릅니다.
사용자가 별도의 권한 프롬프트를 받지 않는다는 것만 의미합니다. constraint나 카메라 사용 중 등으로 인해 getUserMedia가 실패할 수 있는 다른 원인들이
많습니다.
name
을 인자로
호출한 결과입니다.
이 명세는 정책
제어 기능
두 가지를 정의하며, 각각 "camera"
와 "microphone"
입니다.
둘 다 기본 허용
목록
으로
"self"
를 갖습니다.
document의 permissions
policy
는 해당 document 내 모든 콘텐츠가
getUserMedia
를 사용하여 각각 카메라 또는 마이크를
요청할 수 있는지 결정합니다. 어떤 document에서든 비활성화되어 있으면, 해당 document의 모든 콘텐츠는 사용
가능하지 않습니다.
getUserMedia
로 카메라 또는 마이크를 요청할 수
없습니다.
이는 request permission to
use 알고리즘에 의해 강제됩니다.
또한 enumerateDevices
는 document가 사용 가능한
장치만 나열합니다.
이 명세는 프라이버시 인디케이터 요구사항을 하나의 MediaDevices
객체 관점에서 알고리즘으로
표현합니다.
구현자들은 이러한 원칙을 확장하여, iframe으로 인해 페이지에 공존할 수 있는 여러 MediaDevices
객체를 아우르는 인디케이터 표시를 통합하는 것이 권장됩니다.
getUserMedia
()
가 노출하는 각
kind의 장치에 대해,
[[kindsAccessibleMap]]
[kind] 값과 해당
kind의 모든 장치에 대한 [[devicesAccessibleMap]]
[deviceId]
값을 논리 OR로 정의합니다.
[[kindsAccessibleMap]]
[kind] 값과 해당
kind의 모든 장치에 대한 [[devicesLiveMap]]
[deviceId] 값을 논리 OR로
정의합니다.
anyAccessible는 모든 any<kind>Accessible 값의 논리 OR로 정의합니다.
anyLive는 모든 any<kind>Live 값의 논리 OR로 정의합니다.
그 다음은 User Agent에 대한 요구사항입니다:
[[devicesAccessibleMap]]
[deviceId]
값과 [[devicesLiveMap]]
[deviceId] 값이 변경될 때
반드시 최소한 그 변화를 표시해야 합니다.
그리고 아래는 User Agent에 권장되는 동작입니다:
[[devicesAccessibleMap]]
[deviceId]
값과 [[devicesLiveMap]]
[deviceId] 값의 현재 상태를
지속적으로 표시하는 것이 권장됩니다. 또한 해당 장치별 하드웨어 인디케이터 라이트가 [[devicesLiveMap]]
[deviceId] 값에 맞게
동작하는 것이 권장됩니다.이 섹션은 규범적이지 않습니다. 새로운 동작을 지정하지 않고, 명세의 다른 부분에 이미 존재하는 정보를 요약합니다.
이 명세는 웹 플랫폼에 미디어 입력 장치(특히 마이크와 카메라) 관리 기능을 확장합니다. 또한 오디오 출력 장치(스피커와 헤드폰) 등 기타 미디어 장치에 대한 정보 노출도 잠재적으로 허용하지만, 이에 대한 상세 내용은 다른 명세로 넘깁니다. 사용자의 마이크와 카메라로부터 오디오 및 비디오를 캡처하는 것은 개인 식별 정보를 애플리케이션에 노출하며, 이 명세는 이를 공유하기 전에 명시적 사용자 동의를 요구합니다.
카메라 또는 마이크 캡처 전에는 애플리케이션("드라이브-바이 웹")이 사용자가 카메라나 마이크가 있는지 여부만 알 수 있습니다(몇 개인지는 알 수 없음). 장치 식별자는 오리진 간 사용자를 추적할
수 있는 지문으로 활용되지 않도록 설계되었지만, 카메라/마이크 존재 자체가 지문 식별면을 2비트 늘립니다. 오리진별 영속 식별자 deviceId
는 쿠키 등 다른 영속 저장소처럼 취급할 것을 권장합니다.
카메라나 마이크 캡처가 시작되면, 이 명세는 해당 장치에서 미디어 데이터를 얻고 사용하는 방법을 설명합니다. 이 데이터는 민감할 수 있으며, 장치 사용 중임을 알리는 인디케이터를 제공할 것을 권고하지만, 권한 부여 및 사용 중 인디케이터의 성격은 플랫폼 결정에 따릅니다.
캡처 시작 권한은 건별로 부여될 수도 있고, 영속적으로 부여될 수도 있습니다. 건별 권한의 경우, 사용자가 "아니오"를 선택하여 권한 부여 전까지 사용자 상호작용이 UI에 의해 차단되지 않도록(예: "영속적 거부"를 제공하거나 모달 권한 대화상자를 사용하지 않음) 하는 것이 중요합니다.
카메라나 마이크 캡처가 시작되면, 웹 문서는 사용 가능한 모든 미디어 캡처 장치와 그 라벨을 나열할 수 있게 됩니다. 이 능력은 웹 문서가 닫힐 때까지 유지되며, 영속적으로 저장할 수 없습니다. 대부분의 경우 라벨은 오리진 간에도 안정적이므로, 특정 장치를 시간/오리진을 넘어서 추적하는 데 활용될 수 있습니다.
이 명세는 사용 중이지 않은 장치의 정보도 노출합니다. 이는 하위 호환 및 레거시 이유 때문입니다. 향후 명세는 이 모델을 따르지 말고, device enumeration design principles에서 권장하는 모범 사례를 따를 것을 권고합니다.
캡처가 시작되었거나 이루어진 열린 웹 문서, 또는 뷰에 있는 웹 문서에서는, devicechange 이벤트가 새로운 미디어 장치가 추가되거나 제거될 때마다 여러 navigable 및 오리진에서 동시에 발생할 수 있습니다. 사용자 에이전트는 이러한 이벤트의 타이밍을 퍼징하거나, 해당 웹 문서가 뷰에 들어올 때까지 이벤트 발생을 지연시켜 오리진 간 브라우징 활동의 상관 위험을 완화할 수 있습니다.
캡처 장치로부터 미디어 스트림 접근 권한을 얻으면, 해당 장치의 동작 capability(예: 카메라의 사용 가능한 해상도) 등 상세 정보를 얻을 수 있습니다. 이러한 capability들은 대부분 브라우저 세션 및 오리진을 넘어 영속적이며, 장치 추적에 활용될 수 있습니다.
캡처 장치에서 비디오 스트림 접근 권한을 얻으면, 해당 스트림은 해당 장치를 고유하게 식별(예: 데드 픽셀 탐지 등)하는 데 활용될 가능성이 높습니다. 오디오 스트림도 마찬가지로, 사용자의 위치를 방이나 여러 사용자 동시 점유까지 고유 식별(예: 주변 소리/특정 오디오 분석 등)하는 데 활용될 수 있습니다. 오디오/비디오 모두에 대한 사용자 수준 완화책은 카메라/마이크를 덮거나, User Agent 크롬 컨트롤을 통해 권한을 취소하는 것입니다.
제약조건을 활용하면, getUserMedia 호출 실패가 사용자 프롬프트 없이 시스템의 장치 정보를 반환하도록 할 수 있는데, 이는 지문 식별면을 추가로 늘립니다. User Agent는 이러한 식별면을 제한하기 위해 getUserMedia 실패 허용 빈도를 제한하는 것이 좋습니다.
캡처 시작을 위한 영속적 권한이 저장된 경우, 부여된 권한 목록을 쉽게 찾고, 사용자가 원하는 권한을 취소할 수 있어야 합니다.
권한이 부여되면, User Agent는 아래 두 가지를 사용자에게 명확히 알려야 합니다:
저장된 권한이 있는 사이트 개발자들은 권한이 악용되지 않도록 주의해야 합니다. 이러한 권한은 [permissions] API를 통해 취소할 수 있습니다.
특히, 권한이 부여된 미디어 장치의 오디오/비디오 스트림을 제3자가 선택한 엔드포인트로 자동 전송 가능하게 해서는 안 됩니다.
예를 들어, 사이트가 https://webrtc.example.org/?call=user
같은 URL로 자동 통화 및 오디오/비디오 전송을
설정하면, 다음과 같은 악용이 가능해집니다:
https://webrtc.example.org/
에 저장된 권한을 부여한 사용자가
https://webrtc.example.org/?user=EvilSpy
링크를 따라가거나 리다이렉트될 경우, 오디오/비디오 스트림이 공격자
EvilSpy
에게 전송될 수 있습니다.
이 섹션은 규범적이지 않습니다.
이 명세의 새 버전이 향후 제작될 수도 있지만, 다른 표준이 본 명세를 기반으로 새로운 capability를 정의해야 할 필요가 있을 것으로도 예상됩니다. 이 섹션의 목적은 그런 확장 규격 작성자에게 가이드를 제공하는 것입니다.
명세 내 WebIDL로 정의된 인터페이스, 메서드, 속성은 모두 확장될 수 있습니다. 확장지점으로 가장 흔한 것은 새로운 미디어 타입 정의와 새로운 제약 가능 속성 정의입니다.
kind
의 미디어 정의새로운 미디어 타입을 정의하려면 최소한 아래가 필요합니다.
MediaStream
인터페이스에 추가kind
속성의 추가 가능한 값으로 MediaStreamTrack
인터페이스에 추가MediaStream
을 HTMLMediaElement
가
어떻게 처리할지 설명(6.
미디어 요소에서의 MediaStream), 예를 들어 새 타입에 대응하는 audible/inaudible 코롤러리 추가 등MediaDeviceKind
업데이트
getCapabilities
()
및 getUserMedia
()
설명 업데이트
MediaStreamConstraints
딕셔너리에 추가추가적으로 다음도 포함할 수 있습니다.
MediaStreamTrackState
에서 어떻게 종료될 수 있는지
예시 제시이를 위해서는 해당 속성의 Constraints, Capabilities, Settings(3. 용어 참고)가 어떻게 동작할지 정의해야 합니다.
관련 텍스트는 MediaTrackSupportedConstraints
,
MediaTrackCapabilities
,
MediaTrackConstraints
,
MediaTrackSettings
, 4.3.8 제약 가능 속성,
MediaStreamConstraints
등입니다.
확장 명세 작성자는 명세 저장소에 사전 알림하는 것이 강하게
권장됩니다.
향후 이 명세 및 WebRTC 워킹 그룹에서 제작하는 기타 명세는 인지하고 있는 모든 확장사항을 고려하여 잠재적 사용 충돌을 줄이려 노력할 것입니다.
MediaStreamTrack
및 MediaStream
의 새로운 sink 정의다른 명세는 MediaStream
및/또는
MediaStreamTrack
의 새로운 sink를 정의할 수 있습니다. 최소한,
MediaStreamTrack
의 새로운 consumer는 아래를 정의해야 합니다:
MediaStreamTrack
이 mute 또는 disable 등 다양한
상태에서 어떻게 소비될지 정의(4.3.1
미디어 흐름과 생명주기 참고)MediaStreamTrack
정의
다른 명세는 MediaStreamTrack
의 새로운
source를 정의할 수 있습니다.
최소한, MediaStreamTrack
의 새로운 source는 아래를 정의해야 합니다:
kind
에 대해 MediaStreamTrack 생성 API 정의(getUserMedia는
카메라/마이크 source 전용임)kind
에 적용 가능한 제약 가능 속성(4.3.8 제약 가능 속성), 및
해당 속성이 이 source에서 어떻게 동작하는지 선언편집자들은 워킹 그룹 의장 및 팀 연락 담당자인 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: