1. 개요
이 API는 기본 녹화를 매우 간단하게 만드는 한편, 더 복잡한 사용 사례도 지원할 수 있도록 설계되었다. 가장 단순한 경우에는 애플리케이션이 MediaRecorder
객체를 생성하고 start()
를 호출한 다음 stop()
를 호출하거나 MediaStreamTrack(들)
[GETUSERMEDIA]
이 종료될 때까지 기다린다. 녹화 내용은 플랫폼의 기본 인코딩으로 ondataavailable
이벤트를 통해 제공된다. 플랫폼에서 사용 가능한 인코딩 집합을 질의하고, 필요하다면 원하는 인코딩을 선택할 수 있는 기능이 제공된다. 애플리케이션은 또한 한 번에 얼마나 많은 데이터를 받을지
선택할 수 있다. 기본적으로 전체 녹화를 포함하는 Blob
이 녹화가 끝날 때 반환된다. 그러나 애플리케이션은 정기적으로 더 작은 버퍼의 데이터를 받도록 선택할 수 있다.
2. Media Recorder API
[Exposed =Window ]interface :MediaRecorder EventTarget {constructor (MediaStream ,stream optional MediaRecorderOptions = {});options readonly attribute MediaStream stream ;readonly attribute DOMString mimeType ;readonly attribute RecordingState state ;attribute EventHandler onstart ;attribute EventHandler onstop ;attribute EventHandler ondataavailable ;attribute EventHandler onpause ;attribute EventHandler onresume ;attribute EventHandler onerror ;readonly attribute unsigned long videoBitsPerSecond ;readonly attribute unsigned long audioBitsPerSecond ;readonly attribute BitrateMode audioBitrateMode ;undefined start (optional unsigned long );timeslice undefined stop ();undefined pause ();undefined resume ();undefined requestData ();static boolean isTypeSupported (DOMString ); };type
2.1. 생성자
MediaRecorder(MediaStream stream, optional MediaRecorderOptions options = {})-
MediaRecorder()생성자가 호출되면, User Agent는 다음 단계를 반드시 실행해야 한다:- stream을 생성자의 첫 번째 인자로 설정한다.
- options를 생성자의 두 번째 인자로 설정한다.
- type을 options의
mimeType으로 설정한다. - is type supported를 type과 true
값으로 호출했을 때 false를 반환하면,
NotSupportedErrorDOMException을 발생시키고 이 단계를 중단한다. - recorder를 새로 생성한
MediaRecorder객체로 설정한다. - recorder에 [[ConstrainedMimeType]] 내부 슬롯을 생성하고,
options의
mimeType멤버의 값으로 초기화한다. - recorder에 [[ConstrainedBitsPerSecond]] 내부
슬롯을 생성하고, options의
bitsPerSecond멤버값이 있으면 그 값으로, 없으면null로 초기화한다. - recorder에 [[VideoKeyFrameIntervalDuration]] 내부
슬롯을 생성하고, options의
videoKeyFrameIntervalDuration멤버값이 있으면 그 값으로, 없으면null로 초기화한다. - recorder에 [[VideoKeyFrameIntervalCount]] 내부
슬롯을 생성하고, options의
videoKeyFrameIntervalCount멤버값이 있으면 그 값으로, 없으면null로 초기화한다. - recorder의
stream속성을 stream으로 초기화한다. - recorder의
mimeType속성을 recorder의 [[ConstrainedMimeType]] 슬롯의 값으로 초기화한다. - recorder의
state속성을inactive로 초기화한다. - recorder의
videoBitsPerSecond속성을 options의videoBitsPerSecond멤버의 값으로 초기화한다 (존재하면). 그렇지 않으면 User Agent가 동영상에 적당하다고 판단하는 값으로 선택한다. - recorder의
audioBitsPerSecond속성을 options의audioBitsPerSecond멤버의 값으로 초기화한다 (존재하면). 그렇지 않으면 User Agent가 오디오에 적당하다고 판단하는 값으로 선택한다. - 만약 recorder의 [[ConstrainedBitsPerSecond]] 슬롯이
null이 아니면, recorder의videoBitsPerSecond와audioBitsPerSecond속성값을 각 미디어 타입에 대해 User Agent가 적합하다고 판단하는 값으로 설정하되, 두 값의 합이 recorder의 [[ConstrainedBitsPerSecond]] 슬롯값에 가깝게 한다. - recorder가
BitrateMode(즉 options의audioBitrateMode멤버값) 를 지원하면, recorder의audioBitrateMode속성에 options의audioBitrateMode값을 할당한다. 그렇지 않으면 recorder의audioBitrateMode속성값을 "variable"로 초기화한다. - recorder를 반환한다.
2.2. 속성
stream, 유형 MediaStream, 읽기 전용- 기록할
MediaStream[GETUSERMEDIA]입니다. mimeType, 유형 DOMString, 읽기 전용-
MediaRecorder객체에서 사용하는 MIME 타입 [RFC2046]입니다. UA는 기록을 지원하는 모든 MIME 타입 재생이 가능해야 하며, 예를 들어 기록된 영상을 HTML <video> 태그에서 표시할 수 있어야 합니다. state, 유형 RecordingState, 읽기 전용MediaRecorder객체의 현재 상태입니다.onstart, 유형 EventHandler- start 이벤트를 처리할 때 호출됩니다.
onstop, 유형 EventHandler- stop 이벤트를 처리할 때 호출됩니다.
ondataavailable, 유형 EventHandler- dataavailable 이벤트를 처리할 때 호출됩니다. 이 이벤트에는 기록된
데이터의
Blob이 포함되어 있고,data속성으로 접근할 수 있습니다. onpause, 유형 EventHandler- pause 이벤트를 처리할 때 호출됩니다.
onresume, 유형 EventHandler- resume 이벤트를 처리할 때 호출됩니다.
onerror, 유형 EventHandlerErrorEvent를 처리할 때 호출됩니다.videoBitsPerSecond, 유형 unsigned long, 읽기 전용- 비디오 트랙 인코딩 시 사용할 목표 비트레이트입니다.
audioBitsPerSecond, 유형 unsigned long, 읽기 전용- 오디오 트랙 인코딩 시 사용할 목표 비트레이트입니다.
audioBitrateMode, 유형 BitrateMode, 읽기 전용- 오디오 트랙 인코딩에 사용되는
BitrateMode입니다.
2.3. 메서드
state를
동기적으로 변경하며
이벤트는 비동기적으로 발생시킨다. start(optional unsigned long timeslice)-
MediaRecorder객체의start()메서드가 호출되면, UA는 다음 단계를 반드시 실행해야 한다:- recorder를 메서드가
호출된
MediaRecorder객체로 설정한다. - timeslice를 메서드의 첫 번째 인자가 존재하면 해당 값으로,
아니면
undefined로 설정한다. - stream을 recorder의
stream속성 값으로 설정한다. - tracks를 stream의
트랙 집합 중
live트랙들의 집합으로 설정한다. - recorder의
state속성 값이inactive가 아니면,InvalidStateErrorDOMException을 throw 하며, 이 단계를 중단한다. - isolation 속성이 stream에 대해
recorder의 접근을 허용하지 않으면,
SecurityErrorDOMException을 throw 하며, 이 단계를 중단한다. - stream이 inactive 상태이면,
NotSupportedErrorDOMException을 throw 하며, 이 단계를 중단한다. - [[ConstrainedMimeType]] 슬롯에 미디어 종류, 컨테이너, 코덱이 지정된 경우, recorder의 설정을 해당 값에 맞게 제한한다.
- recorder의 [[ConstrainedBitsPerSecond]] 슬롯이
null이 아니면, recorder의videoBitsPerSecond와audioBitsPerSecond속성을 각각 대응하는 미디어 타입에 대해 UA가 적절하다고 판단하는 값으로 설정하고, tracks의 모든 트랙에 대해videoBitsPerSecond와audioBitsPerSecond의 합이 recorder의 [[ConstrainedBitsPerSecond]] 값에 가까워지도록 한다. - videoBitrate를 recorder의
videoBitsPerSecond속성 값으로 설정하고, recorder의 설정을 모든 비디오 트랙에 대해 videoBitrate 비트/초의 총 비트레이트를 목표로 제한한다. videoBitrate는 인코더에게 제시하는 힌트이며 실제로 초과될 수도, 달성되지 않을 수도, 오랜 시간 뒤에야 달성될 수도 있다. - audioBitrate를 recorder의
audioBitsPerSecond속성 값으로 설정하고, recorder의 설정을 모든 오디오 트랙에 대해 audioBitrate 비트/초의 총 비트레이트를 목표로 제한한다. audioBitrate 역시 인코더에 대한 힌트이며 실제로 초과 또는 달성 실패, 지연 달성 가능성이 있다. -
videoKeyFrameIntervalDuration을
recorder.[[VideoKeyFrameIntervalDuration]] 값으로,
videoKeyFrameIntervalCount를
recorder.[[VideoKeyFrameIntervalCount]]
값으로 설정한다. UA는 다음 규칙에 따라
recorder의 설정을 조정해야 한다:
- videoKeyFrameIntervalDuration이
null이 아니고, videoKeyFrameIntervalCount가null이면, 마지막 키 프레임 이후 videoKeyFrameIntervalDuration 밀리초가 지나고 도착한 첫 프레임에 인코더가 키프레임을 생성한다. - videoKeyFrameIntervalCount가
null이 아니고, videoKeyFrameIntervalDuration이null이면, 마지막 키 프레임 이후 videoKeyFrameIntervalCount 프레임 이후 도착한 첫 프레임에서 인코더가 키프레임을 생성한다. - 둘 다
null이 아니면,NotSupportedErrorDOMException을 throw 하며, 이 단계를 중단한다. - 둘 다
null이면, UA는 필요에 따라 키 프레임을 생성할 수 있다.
인코더는 상황에 따라 독립적으로 키프레임 생성 여부를 결정할 수 있다.
- videoKeyFrameIntervalDuration이
- recorder의
BitrateMode값을 이용해 모든 오디오 트랙의 인코딩 방식을 제한한다. - tracks의 각 트랙에 대해, User Agent가
현재 설정으로 해당 트랙을 기록할 수 없다면,
NotSupportedErrorDOMException을 throw 하며, 이 단계를 중단한다. -
recorder의
state를recording으로 설정하고, 다음 단계를 병렬로 실행한다:- 녹화에 사용할 컨테이너와 코덱이 아직 완전히 지정되지 않았다면, UA가
recorder의 현재 설정에서 이를 지정한다. UA는 tracks 내
트랙들의 소스를 고려해 컨테이너/코덱을 고를 수 있다.
tracks 내 트랙 소스를 이용해, 원격 트랙(RTCPeerConnection 등)인 경우 동일한 코덱을 선택함으로써 재인코딩을 피할 수 있다. 단, RTP 스트림 코덱이 녹화 중에 변경되면 UA는 끊김 방지를 위해 재인코딩해야 한다.
-
User Agent가 지정된 미디어 타입/서브타입, 코덱, 컨테이너 조합을 지원하지 않으면,
남은 단계를 중단하고, DOM 조작 태스크 소스를 이용해 태스크를 큐에 추가하여 다음 단계 실행:
- 녹화기 비활성화 를 recorder에 수행
- 에러 이벤트
NotSupportedError를 recorder에서 발생시킨다. - stop 이벤트를 recorder 에서 발생시킨다.
-
recorder의 현 설정을 이용해 tracks 내 모든
트랙을 녹화하고 데이터를
Blobblob에 수집한다. DOM 조작 태스크 소스에서 다음 단계를 큐에 추가:- extendedMimeType을 recorder의 [[ConstrainedMimeType]] 값으로 설정한다.
- MediaRecorder가 사용한 설정 반영 미디어 타입, 서브타입, 코덱 등의 파라미터를 extendedMimeType에 추가(이미 없을 시에 한함). [RFC6381] profile 파라미터나 추가 코덱별 파라미터 포함될 수 있음.
- recorder의
mimeType속성을 extendedMimeType로 지정. - start 이벤트를 recorder 에서 발생시킴.
-
녹화 도중 언젠가 stream의 isolation 속성이 변경되어
MediaRecorder의 접근이 더 이상 허용되지 않으면, UA는 데이터 수집을 중단 및 폐기하고, 다음 단계를 DOM 조작 태스크 소스에 큐잉한다.- 녹화기 비활성화 를 recorder에 수행
- SecurityError 이벤트를 recorder 에서 발생시킴
- dataavailable 블롭 이벤트를 recorder, blob과 함께 발생시킴
- stop 이벤트를 recorder 에서 발생시킴
-
녹화 도중 stream의
트랙 집합에 트랙이 추가 또는 제거되면,
UA는 데이터 수집을 중단하고, 다음 단계를 큐잉한다:
- 녹화기 비활성화를 recorder에 수행
- InvalidModificationError 이벤트를 recorder에서 발생시킴
- dataavailable 블롭 이벤트를 recorder, blob과 함께 발생시킴
- stop 이벤트를 recorder 에서 발생시킴
-
UA가 isolation 속성이나 stream의 트랙 집합 이외의 이유로
데이터 수집을 지속할 수 없게 되면,
UA는 다음 단계를 큐잉한다:
- 녹화기 비활성화를 recorder에 수행
- UnknownError 이벤트를 recorder에서 발생시킴
- dataavailable 블롭 이벤트를 recorder, blob과 함께 발생시킴
- stop 이벤트를 recorder 에서 발생시킴
-
timeslice가
undefined가 아니면, 최소 timeslice 밀리초 데이터가 수집되었거나 UA가 정한 최소값이 충족되면, 새Blobblob에 데이터를 수집하고, DOM 조작 태스크 소스에서 dataavailable 블롭 이벤트를 recorder, blob과 함께 발생시킬 태스크를 큐잉한다.timeslice가
undefined이면 가장 큰unsigned long값으로 간주됨. -
모든 녹화 트랙이
ended상태가 되면, 데이터 수집을 중단하고, 다음 단계를 큐잉한다:- 녹화기 비활성화 를 recorder에 수행
- dataavailable 블롭 이벤트를 recorder, blob과 함께 발생시킴
- stop 이벤트를 recorder 에서 발생시킴
- 녹화에 사용할 컨테이너와 코덱이 아직 완전히 지정되지 않았다면, UA가
recorder의 현재 설정에서 이를 지정한다. UA는 tracks 내
트랙들의 소스를 고려해 컨테이너/코덱을 고를 수 있다.
참고로
stop(),requestData(), 그리고pause()역시 녹화 동작에 영향을 준다.UA는
stream을 재생 시 원 트랙을 복구할 수 있도록 기록해야 한다.Blob이 여러 개 반환되는 경우(timeslice또는requestData()로 인해), 개별 Blob은 재생 불가여도 되나, 모든 Blob을 합치면 최종 결과는 반드시 재생 가능해야 한다.MediaStream내 어떤 트랙이muted되거나enabled가 아니면, UA는 해당 트랙의 출력(검은 프레임, 무음)만 기록한다.녹화기 비활성화 알고리즘, recorder가 주어지면, 아래를 따른다:
- recorder의
mimeType속성을 [[ConstrainedMimeType]] 슬롯의 값으로 지정한다. - recorder의
state속성을inactive로 지정한다. - recorder의 [[ConstrainedBitsPerSecond]] 슬롯이
undefined가 아니면, recorder의videoBitsPerSecond와audioBitsPerSecond속성을 각각 적절한 값으로 지정한다. 두 속성의 합이 recorder의 [[ConstrainedBitsPerSecond]] 값에 가깝도록 한다.
- recorder를 메서드가
호출된
stop()-
MediaRecorder객체의stop()메서드가 호출되면, UA는 다음 단계를 반드시 실행한다:- recorder를, 해당 메서드가 호출된
MediaRecorder객체로 설정한다. - recorder의
state속성이inactive이면, 이후 단계를 중단한다. - 녹화기 비활성화를 recorder에 실행한다.
-
DOM 조작 태스크 소스를 사용하여 아래 단계를 실행하는 태스크를 큐에 추가한다:
- 데이터 수집을 중단한다.
- 지금까지 수집된 데이터 Blob을 blob으로 하고, dataavailable이라는 블롭 이벤트를 recorder에 blob과 함께 발생시킨다.
- stop이라는 이벤트를 recorder에 발생시킨다.
undefined를 반환한다.
- recorder를, 해당 메서드가 호출된
pause()-
MediaRecorder객체의pause()메서드가 호출되면, UA는 반드시 다음 단계를 실행한다:state가inactive이면,InvalidStateErrorDOMException을 throw 하며, 이 단계를 중단한다.state가paused라면, 이 단계를 중단한다.state를paused로 지정하고, DOM 조작 태스크 소스에서 다음 단계를 실행한다:- blob에 데이터 수집을 중단한다 (단, 미래의 녹화 재개가 가능하도록 해당 blob은 유지).
- target을 MediaRecorder 컨텍스트 객체로 두고, pause 이벤트를 target에 발생시킨다.
undefined를 반환한다.
resume()-
MediaRecorder객체의resume()메서드가 호출되면, UA는 다음 단계를 반드시 실행한다:state가inactive이면,InvalidStateErrorDOMException을 throw 하며, 이 단계를 중단한다.state가recording이면, 이 단계를 중단한다.state를recording으로 지정하고, DOM 조작 태스크 소스에서 다음 실행:- 현재 blob에 데이터 수집 다시(계속) 시작
- target을 MediaRecorder 컨텍스트 객체로 하고, resume 이벤트를 target에 발생시킨다.
undefined를 반환한다.
requestData()-
MediaRecorder객체의requestData()메서드가 호출되면, UA는 다음 단계를 반드시 실행한다:-
state가inactive이면,InvalidStateErrorDOMException을 throw 하며 현재 단계를 종료한다. 아니면 UA는 다음을 DOM 조작 태스크 소스에서 큐잉한다:- blob을
Blob기반 현재까지 수집한 데이터로 설정, target을MediaRecorder컨텍스트 객체로 하여, dataavailable 이벤트를 target, blob과 함께 발생시킨다. (아직 데이터가 없다면 blob은 빈 값일 수 있음.) - 새 Blob을 생성해 이후 데이터는 새 Blob에 저장.
- blob을
undefined를 반환한다.
-
isTypeSupported(DOMString type)-
이 메서드는 더 이상 사용을 권장하지 않는다. 과거 호환성 유지를 위한 것임.
동기적으로 노출된 코덱 식별자 목록은:
"vp8","vp9","h264"또는"avc1","av1"또는"av01","hvc1","hev1","avc1","avc3","opus","pcm".하드웨어 지원 감지의 어려움으로 인해, 정확한 답변은 타이밍에 따라 달라질 수 있다. 사용자는MediaCapabilities를 통해 프로필 레벨이나 최신 코덱을 확인해야 한다:const { supported} = await navigator. mediaCapabilities. encodingInfo({ type: "record" , video: { contentType: "video/webm;codecs=av01.0.19M.08" , width: 640 , height: 480 , framerate: 30 , bitrate: 300000 , } }); MediaRecorder가 지정된 MIME 타입으로 녹화할 수 있는지 확인한다. true를 반환하더라도 단지MediaRecorder구현이 해당 MIME으로Blob객체를 기록할 수 있다는 뜻일 뿐이다. 실제 녹화는 미디어 인코딩을 위한 충분한 자원이 없으면 실패할 수 있다. 이 메서드가 호출되면 UA는 is type supported 알고리즘을, 첫 인자를 넘기고 false 값과 함께 실행한다.- is type supported 알고리즘은 type과 불린 deferNewerCodecsCheck 인자를 받아 다음을 따른다.
- type이 빈 문자열이면 true를 반환한다 (이 경우 UA가 컨테이너/코덱 모두 자유롭게 선택).
- type이 유효한 MIME 타입 문자열이 아니면 false 반환.
- MediaRecorder가 지정된 미디어 타입/서브타입/컨테이너 조합을 지원하지 않으면 false 반환.
- codecStrings를 리스트 형태로,
type에서
codecs=뒤를","로 엄격하게 분할해서 구하고, 없으면 빈 리스트로 한다. - codecStrings에 오디오/비디오 각각 코덱이 2개 이상 있으면 false 반환.
- codecIdentifiers는 빈 리스트로 한다.
-
codecStrings의 각 codecString에 대해:
- codecIdentifier를 codecString을
"."로 분할 후 첫 부분을 ASCII 소문자로 변환하여 얻는다. - codecIdentifiers 리스트에 codecIdentifier 추가.
나머지 알고리즘에서는 코덱 표기에서 점 이후 부분(예:"av01.0.19M.08")은 무시하고, 앞 부분(예:"av01")로 식별자 판단만 한다. - codecIdentifier를 codecString을
-
codecIdentifiers의 각 codecIdentifier에 대해,
동기 노출 여부 검사:
- MediaRecorder가 type에 지정된 미디어 타입/서브타입 및 컨테이너와 codecIdentifier의 조합을 지원하지 않으면, false를 반환한다.
- codecIdentifiers에 동기적으로 노출되지 않은 코덱이 하나라도 있으면, deferNewerCodecsCheck를 반환.
- true 반환.
- is synchronously exposed 알고리즘은 codecIdentifier가 주어졌을 때 다음 단계로 구성된다:
- 동기적으로 노출된 코덱 식별자 목록 중 어느 항목이라도 codecIdentifier와 정확히 일치하면 true를 반환하고, 아니라면 false를 반환한다.
2.4. 데이터 처리
blob 이벤트를 발생시키다
는 Blob
blob을(를) 사용하여
이벤트를 발생시키는 것을 의미한다.
이때 target에서 BlobEvent를 사용하고,
data
속성은 blob으로 초기화된다.
2.5. MediaRecorderOptions
dictionary {MediaRecorderOptions DOMString mimeType = "";unsigned long audioBitsPerSecond ;unsigned long videoBitsPerSecond ;unsigned long bitsPerSecond ;BitrateMode audioBitrateMode = "variable";DOMHighResTimeStamp videoKeyFrameIntervalDuration ;unsigned long videoKeyFrameIntervalCount ; };
2.5.1. 멤버
mimeType, 타입 DOMString, 기본값""- 녹화를 위한 컨테이너 및 코덱 포맷 [RFC2046]이며, 포맷에 정의된 파라미터도 포함될 수 있다.
audioBitsPerSecond, 타입 unsigned long- 오디오 트랙(들) 인코딩의 목표 총 비트레이트(비트/초, bps).
videoBitsPerSecond, 타입 unsigned long- 비디오 트랙(들) 인코딩의 목표 총 비트레이트(비트/초, bps).
bitsPerSecond, 타입 unsigned long- 모든 비디오 및 오디오 트랙 인코딩의
목표 총 비트레이트(비트/초, bps).
이 멤버는
audioBitsPerSecond또는videoBitsPerSecond값을 대체하며, 실제 분배는 UA가 결정할 수 있다. audioBitrateMode, 타입 BitrateMode, 기본값"variable"- 오디오 트랙 인코딩에 사용할
BitrateMode를 지정한다. videoKeyFrameIntervalDuration, 타입 DOMHighResTimeStamp- 인코딩된 비디오 스트림에서 키프레임 간의
예상 시간(밀리초 단위) 간격을 지정.
UA는 이 값과
videoKeyFrameIntervalCount를 함께 고려해 키프레임 생성을 제어한다. videoKeyFrameIntervalCount, 타입 unsigned long- 인코딩된 비디오 스트림에서 키프레임 사이의
프레임 수 간격을 지정.
UA는 이 값과
videoKeyFrameIntervalDuration을 함께 고려해 키프레임 생성을 제어한다.
2.6. BitrateMode
enum {BitrateMode "constant" ,"variable" };
2.6.1. 값
constant- 고정 비트레이트로 인코딩함.
variable- 가변 비트레이트로 인코딩하여 신호가 복잡할수록 공간을 더 많이, 덜 복잡할수록 공간을 적게 사용하도록 함.
2.7. RecordingState
enum {RecordingState "inactive" ,"recording" ,"paused" };
2.7.1. 값
inactive- 녹화가 진행 중이지 않음: 아직 시작되지 않았거나 이미 중지됨.
recording- 녹화가 시작되어 UA가 데이터를 수집 중임.
paused- 녹화가 시작되었다가 일시 정지된 상태이며, 아직 중지나 재개되지 않음.
3. Blob 이벤트
[Exposed =Window ]interface :BlobEvent Event {constructor (DOMString ,type BlobEventInit ); [eventInitDict SameObject ]readonly attribute Blob data ;readonly attribute DOMHighResTimeStamp timecode ; };
3.1. 생성자
BlobEvent(DOMString type, BlobEventInit eventInitDict)
3.2. 속성
data, 타입 Blob, 읽기 전용- 인코딩된
Blob으로, 해당type속성은 블롭 데이터의 인코딩을 나타낸다. timecode, 타입 DOMHighResTimeStamp, 읽기 전용- MediaRecorder 인스턴스의 경우,
최초로 생성된
BlobEvent의timecode값은 반드시 0을 포함해야 한다. 그 다음BlobEvent의timecode값에는 해당BlobEvent에서 생성된 첫 번째 청크의 타임스탬프와, 첫 번째BlobEvent에서 생성된 첫 번째 청크의 타임스탬프와의 차이가DOMHighResTimeStamp[HR-TIME] 형태로 포함된다.
3.3. BlobEventInit
dictionary :BlobEventInit EventInit {required Blob data ;DOMHighResTimeStamp timecode ; };
3.3.1. 멤버
data, 타입 BlobBlob객체로,BlobEvent를 통해 전달할 데이터를 포함한다.timecode, 타입 DOMHighResTimeStampBlobEvent초기화에 사용되는 타임코드이다.
4. 오류 처리
4.1. 일반 원칙
이 절은 비규범적(non-normative)이다.UA는 호출 시점에 오류를 감지할 수 있으면
DOMException
을 throw한다. 그 외의 경우, UA는
에러 이벤트를 발생시킨다.
녹화가 시작되어 아직 중지되지 않은 상태에서 오류가 발생하면,
blob을 지금까지 수집된 데이터의
Blob
으로 둔다; 에러를 발생시킨 후 UA는
dataavailable 이벤트를
blob과 함께 발생시킨다;
그리고 곧바로 UA는
stop이라는 이벤트를 발생시킨다.
UA는 지원하는 Blob
크기나, 동시에 기록 가능한
MediaStreamTrack
개수처럼 플랫폼별 제한을 둘 수 있다.
이러한 제한을 초과하면 치명적인 오류를 신호한다.
4.2. 오류 이벤트
오류 이벤트를 발생시킨다는 것은
ErrorEvent를
eventConstructor로 사용하여 이벤트를 발생시키는
것을 말한다.
4.3. 예외 요약
이 문서에 정의된 각 예외는
특정 타입을 가진 DOMException
입니다.
| 이름 | 설명 |
|---|---|
InvalidStateError
| 허용되지 않은 객체에 대해 연산이 호출되었거나, 허용되지 않은 시점에 호출했거나, 이미 삭제되거나 제거된 소스 객체에 대해 요청을 한 경우 발생합니다. |
NotSupportedError
| MIME 타입이 지원되지 않거나
주어진 트랙 집합을 해당 MIME 타입으로
기록할 수 없어서 연산을 수행할 수 없는 경우입니다.
User agent는 message 속성에
최대한 부가 정보를 제공해야 합니다.
|
SecurityError
| MediaStream의
격리 속성(isolation properties)
으로 인해 MediaRecorder가
접근할 수 없는 경우입니다.
|
InvalidModificationError
| 기록 중인 MediaStream의
MediaStreamTrack
집합이 변경되어 더 이상 기록이 불가능한 상황입니다.
|
5. 이벤트 요약
다음과 같은 추가 이벤트들이 MediaRecorder
객체에서 발생합니다:
| 이벤트 이름 | 인터페이스 | 발생 시점 |
|---|---|---|
start
| Event
| UA가 MediaStream에서 데이터 녹화를 시작했을 때 발생 |
stop
| Event
| UA가 MediaStream에서 데이터 녹화를 중단했을 때 발생 |
dataavailable
| BlobEvent
| UA가 데이터를 애플리케이션에 전달하기 위해 발생시키는 이벤트입니다.
이 이벤트의 data
속성에는 기록된 데이터의 Blob이
포함됩니다.
|
pause
| Event
| UA가 MediaStream에서 데이터 녹화를 일시 중지했을 때 발생 |
resume
| Event
| UA가 MediaStream에서 데이터 녹화를 다시 시작했을 때 발생 |
error
| ErrorEvent
| 메모리 부족 등 오류가 발생했거나,
녹화 중 stream에
변경이 발생해 더 이상 녹화가 불가능해진 경우
(예: 트랙이 추가/제거된 경우) 발생
|
6. 개인정보 보호 및 보안 고려사항
이 절은 비규범적(non-normative)이다.
MediaRecorder
의 데이터 소스는 항상 MediaStream
이므로, 보안의 대부분은 [GETUSERMEDIA]의 '개인정보 및 보안 고려사항' 절에 위임된다.
특히, 소스 MediaStream
이 신뢰된 보안 컨텍스트에서 공급된다는 것을 전제로 한다.
6.1. 자원 고갈
비디오/오디오 인코딩은 많은 시스템 자원을 소모할 수 있다. 악의적인 웹사이트는 매우 큰 프레임 해상도/프레임레이트 등으로 워크로드를 설정함으로써 UA를 방해하거나 다운시키려 할 수 있다.
MediaRecorder
는 start()
의 timeslice
파라미터로 인코딩 데이터를 일정기간 보관하도록 설정할 수 있는데, 너무 큰 timeslice 값을 넘기면 UA가 많은 데이터를 버퍼링해야 하여 랙 및 메모리 고갈 현상이 발생할 수 있다.
UA는 인코딩 및 버퍼링 과정에서 시스템 자원이 고갈되지 않도록 예방책을 마련해야 한다.
6.2. 지문 추적
MediaRecorder
는 isTypeSupported()
메서드를 통해 지원하는 비디오 및 오디오 MIME 타입 정보를 제공한다. 이 외에도 MediaRecorderOptions에
코덱/대역폭이 정의되지 않을 경우 적합한 값을 선택해, type
속성 등으로 해당 정보를 노출한다. 사용자가 명시한 MediaRecorderOptions
정보도 최대한 존중하려 시도한다.
악의적인 웹사이트가 다양한 방식(예: 지원 코덱/가속기/해상도, 플랫폼/버전 차이 등 분석, 성능 측정 등)으로 적극적 지문 추적에 쓸 수 있다.
-
사용자에이전트 역량(코덱/가속/최대해상도/프레임레이트 등)을 분석해 플랫폼, 하드웨어, OS, 버전 등을 추론할 수 있다.
-
시스템 기본 할당이나 부하 측정 등을 통한 하드웨어 특성 간접 추론을 할 수 있다.
UA는 지문 표면적(fingerprinting surface) 증가를 막기 위해 단일 MIME/코덱에 대한 폭넓은 지원을 하고, 아키텍처/하드웨어/버전별로 기능 차가 드러나지 않게 하며, 기본값을 조정해 식별 가능성을 낮추는 등의 조치를 취해야 한다.
7. 예제
7.1. MediaRecorder
와 콘텐츠 타입 지원 여부 확인
이 예제는 구현체가 몇 가지 인기 있는 코덱/컨테이너 조합을 지원하는지 확인합니다.
if ( window. MediaRecorder== undefined ) { console. error( 'MediaRecorder not supported, boo' ); } else { var contentTypes= [ "video/webm" , "video/webm;codecs=vp8" , "video/x-matroska;codecs=avc1" , "audio/webm" , "video/mp4;codecs=avc1" , "video/invalid" ]; contentTypes. forEach( contentType=> { console. log( contentType+ ' is ' + ( MediaRecorder. isTypeSupported( contentType) ? 'supported' : 'NOT supported ' )); }); }
7.2. 웹캠 비디오와 오디오 녹화
이 예제는 MediaStream
을 getUserMedia()로
비디오+오디오 캡처한 후,
이를 <video> 태그에 연결하고 녹화를 시도하며, ondataavailable
이벤트를 통해 기록된 청크를 받아옵니다. 참고: MediaRecorder를 stop()
하거나
기록되는 MediaStream의
모든
MediaStreamTrack
이 ended
될 때까지 녹화가 계속됩니다.
< html> < body> < video autoplay/> < script> var recordedChunks= []; function gotMedia( stream) { // |video| shows a live view of the captured MediaStream. var video= document. querySelector( 'video' ); video. src= URL. createObjectURL( stream); var recorder= null ; try { recorder= new MediaRecorder( stream, { mimeType: "video/webm" }); } catch ( e) { console. error( 'Exception while creating MediaRecorder: ' + e); return ; } recorder. ondataavailable= ( event) => { console. log( ' Recorded chunk of size ' + event. data. size+ "B" ); recordedChunks. push( event. data); }; recorder. start( 100 ); } navigator. mediaDevices. getUserMedia({ video: true , audio: true }) . then( gotMedia) . catch ( e=> { console. error( 'getUserMedia() failed: ' + e); }); < /script>< /body>< /html>