미디어 소스 확장™

W3C 워킹 드래프트

이 문서에 대한 자세한 정보
현재 버전:
https://www.w3.org/TR/2025/WD-media-source-2-20251104/
최신 공개 버전:
https://www.w3.org/TR/media-source-2/
최신 편집자 초안:
https://w3c.github.io/media-source/
히스토리:
https://www.w3.org/standards/history/media-source-2/
커밋 히스토리
최신 권고안:
https://www.w3.org/TR/2016/REC-media-source-20161117/
편집자:
(Apple Inc.)
Mark Watson (Netflix Inc.)
이전 편집자:
(W3C 초청 전문가) -
Jerry Smith (Microsoft Corporation) -
Aaron Colwell (Google Inc.) -
Adrian Bateman (Microsoft Corporation) -
피드백:
GitHub w3c/media-source (풀 리퀘스트, 새 이슈, 오픈 이슈)
public-media-wg@w3.org 제목 [media-source-2] … 메시지 주제 … (아카이브)
브라우저 지원:
caniuse.com

요약

이 명세는 HTMLMediaElement [HTML]을 확장하여 JavaScript가 재생을 위한 미디어 스트림을 생성할 수 있도록 합니다. JavaScript로 스트림을 생성할 수 있게 되면 적응형 스트리밍, 라이브 스트림의 타임시프트 등 다양한 사용 사례를 지원할 수 있습니다.

이 문서의 상태

이 섹션은 이 문서가 공개될 당시의 상태를 설명합니다. 현재 W3C 출판물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 인덱스에서 확인할 수 있습니다.

편집상의 업데이트 외에도, W3C 권고안으로 2016년 11월에 공개된 이후 실질적인 변경 사항은 다음과 같습니다:

이전 버전 이후 변경된 전체 목록은 커밋 내역을 참고하세요.

작업 그룹은 편집자가 아직 해결하지 않은 모든 버그 리포트 목록을 관리합니다.

구현자는 이 명세가 안정적이지 않다는 점을 인지해야 합니다. 논의에 참여하지 않는 구현자는 명세가 호환되지 않는 방식으로 변경될 수 있으니 주의해야 합니다. 이 명세가 최종적으로 후보 권고안 단계에 도달하기 전에 구현을 원하는 벤더는 GitHub 저장소를 추적하고 논의에 참여해야 합니다.

이 문서는 미디어 워킹 그룹에서 권고안 경로를 따라 워킹 드래프트로 공개되었습니다.

워킹 드래프트로 공개되었다고 해서 W3C 및 회원사의 보증을 의미하지는 않습니다.

이 문서는 초안 문서이며 언제든지 업데이트, 대체 또는 폐기될 수 있습니다. 진행 중인 작업 외의 문서로 인용하는 것은 적절하지 않습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C공개 특허 공개 목록을 관리하며, 해당 그룹의 결과물과 관련해 특허 공개 방법도 안내합니다. 어떤 개인이 필수적 청구를 포함한다고 믿는 특허를 실제로 알고 있다면, W3C 특허 정책 6항에 따라 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받습니다.

1. 소개

이 섹션은 규범적이지 않습니다.

이 명세는 JavaScript가 <audio>와 <video>를 위한 미디어 스트림을 동적으로 구성할 수 있도록 합니다. HTMLMediaElement에 미디어 데이터를 공급할 수 있는 MediaSource 객체를 정의합니다. MediaSource 객체는 하나 이상의 SourceBuffer 객체를 가집니다. 애플리케이션은 SourceBuffer 객체에 데이터 세그먼트를 추가하고, 시스템 성능 및 기타 요소에 따라 추가되는 데이터의 품질을 조정할 수 있습니다. SourceBuffer 객체의 데이터는 오디오, 비디오, 텍스트 데이터의 트랙 버퍼로 관리되어 디코딩 후 재생됩니다. 이러한 확장에 사용되는 바이트 스트림 명세는 바이트 스트림 포맷 레지스트리 [MSE-REGISTRY]에서 확인할 수 있습니다.

미디어 소스 파이프라인 모델 다이어그램
그림 1 미디어 소스 파이프라인 모델 다이어그램

1.1 목표

이 명세는 다음 목표를 염두에 두고 설계되었습니다:

이 명세는 다음을 정의합니다:

2. 정의

활성 트랙 버퍼

트랙 버퍼코딩된 프레임을 제공하는 버퍼로, enabled audioTracks, selected videoTracks, 그리고 "showing" 또는 "hidden" textTracks에 해당합니다. 이 모든 트랙은 SourceBuffer 객체와 activeSourceBuffers 목록에 연결됩니다.

Append 윈도우

프레젠테이션 타임스탬프 범위로, 코딩된 프레임을 추가할 때 필터링하는 데 사용됩니다. append window는 단일 시작 시간과 종료 시간을 가진 연속적인 시간 범위를 나타냅니다. 프레젠테이션 타임스탬프가 해당 범위 내에 있는 코딩된 프레임만 SourceBuffer에 추가될 수 있고, 범위를 벗어난 프레임은 제외됩니다. append window의 시작과 종료 시간은 appendWindowStartappendWindowEnd 속성으로 제어됩니다.

코딩된 프레임

프레젠테이션 타임스탬프, 디코드 타임스탬프, 그리고 코딩된 프레임 지속시간을 가진 미디어 데이터 단위입니다.

코딩된 프레임 지속시간

코딩된 프레임의 지속시간입니다. 비디오와 텍스트의 경우, 프레임 또는 텍스트가 얼마나 표시되어야 하는지 나타냅니다. 오디오의 경우, 해당 프레임에 포함된 모든 샘플의 합이 지속시간입니다. 예를 들어, 오디오 프레임에 441개의 샘플(@44100Hz)이 있으면 지속시간은 10밀리초가 됩니다.

코딩된 프레임 종료 타임스탬프

코딩된 프레임프레젠테이션 타임스탬프코딩된 프레임 지속시간의 합입니다. 이는 해당 프레임 바로 다음의 프레젠테이션 타임스탬프를 의미합니다.

코딩된 프레임 그룹

인접하며 디코드 타임스탬프가 단조 증가하고 중간에 간격이 없는 코딩된 프레임의 그룹입니다. 코딩된 프레임 처리 알고리즘이나 abort() 호출로 인해 새로운 코딩된 프레임 그룹이 시작됩니다.

디코드 타임스탬프

디코드 타임스탬프는 해당 프레임과 이 프레임에 의존하는 모든 프레임이 즉시 디코딩 및 렌더링된다고 가정할 때 디코딩이 필요한 가장 늦은 시점을 나타냅니다(이는 프레젠테이션 타임스탬프 중, 이 프레임에 의존하는 가장 이른 프레임의 표시 순서와 같습니다). 프레임이 표시 순서와 다르게 디코딩될 수 있다면, 디코드 타임스탬프는 반드시 바이트 스트림에 포함되어 있거나 파생할 수 있어야 합니다. 그렇지 않으면 사용자 에이전트는 append error 알고리즘을 실행해야 합니다. 프레임이 표시 순서대로만 디코딩되고 바이트 스트림에 디코드 타임스탬프가 없는 경우, 디코드 타임스탬프는 프레젠테이션 타임스탬프와 동일합니다.

초기화 세그먼트

미디어 세그먼트 시퀀스를 디코딩하는 데 필요한 모든 초기화 정보를 담은 바이트 시퀀스입니다. 여기에는 코덱 초기화 데이터, 멀티플렉스 세그먼트의 트랙 ID 매핑, 타임스탬프 오프셋(예: 편집 목록)이 포함됩니다.

Note

바이트 스트림 포맷 레지스트리 [MSE-REGISTRY]에 있는 바이트 스트림 포맷 명세에 포맷별 예시가 포함되어 있습니다.

미디어 세그먼트

미디어 타임라인의 일부에 대한 패킷화 및 타임스탬프가 지정된 미디어 데이터를 담은 바이트 시퀀스입니다. 미디어 세그먼트는 항상 가장 최근에 추가된 초기화 세그먼트와 연결됩니다.

Note

바이트 스트림 포맷 레지스트리 [MSE-REGISTRY]에 있는 바이트 스트림 포맷 명세에 포맷별 예시가 포함되어 있습니다.

MediaSource 객체 URL

MediaSource 객체 URL은 blob URLcreateObjectURL()로 생성한 고유 URL입니다. HTMLMediaElement에 MediaSource 객체를 연결할 때 사용합니다.

이 URL은 blob URL과 동일하지만, 해당 기능 정의에서 FileBlob 객체를 참조하는 부분은 MediaSource 객체에도 적용합니다.

MediaSource 객체 URL의 originrelevant settings object입니다. this에서 createObjectURL()를 호출할 때 결정됩니다.

Note

예를 들어, MediaSource 객체 URL의 origin은 미디어 요소가 canvas에서 사용될 때 방식에 영향을 줍니다.

상위 미디어 소스

SourceBuffer 객체의 상위 미디어 소스는 해당 객체를 생성한 MediaSource 객체입니다.

프레젠테이션 시작 시간

프레젠테이션 시작 시간은 프레젠테이션의 가장 이른 시점으로, 재생 위치가장 이른 위치를 지정합니다. 이 명세로 생성된 모든 프레젠테이션의 시작 시간은 0입니다.

참고

HTMLMediaElementbuffered에 현재 재생 위치를 포함하는 TimeRanges가 있는지 판단할 때, 구현체는 선택적으로 현재 재생 위치가 presentation start time과 그 이후이면서 첫 번째 TimeRanges보다 이전일 때, 만약 해당 TimeRangespresentation start time 이후 1초와 같이 비교적 짧은 시간 이내에 시작된다면 첫 번째 TimeRanges를 재생할 수 있도록 허용할 수 있습니다. 이러한 허용은 멀티플렉스(muxed) 스트림에서 모든 트랙이 presentation start time에 정확히 시작되지 않는 현실을 반영한 것입니다. 구현체는 이러한 허용 여부에 관계없이 실제 버퍼링된 범위를 반드시 보고해야 합니다.

프레젠테이션 구간

코딩된 프레임의 프레젠테이션 구간은 해당 프레임의 프레젠테이션 타임스탬프에서 프레젠테이션 타임스탬프 + 코딩된 프레임 지속시간까지의 시간 구간입니다. 예를 들어, 코딩된 프레임의 프레젠테이션 타임스탬프가 10초이고 코딩된 프레임 지속시간이 100밀리초라면, 프레젠테이션 구간은 [10-10.1)입니다. 구간의 시작은 포함(포함), 종료는 제외(미포함)입니다.

표시 순서

코딩된 프레임이 프레젠테이션에서 렌더링되는 순서입니다. 표시 순서는 코딩된 프레임프레젠테이션 타임스탬프 기준으로 단조 증가하는 순서로 정렬하여 달성됩니다.

프레젠테이션 타임스탬프

프레젠테이션 내 특정 시간을 참조합니다. 코딩된 프레임의 프레젠테이션 타임스탬프는 해당 프레임이 언제 렌더링되어야 하는지 나타냅니다.

랜덤 액세스 포인트

미디어 세그먼트 내에서 디코딩 및 연속 재생을 이전 데이터에 의존하지 않고 시작할 수 있는 위치입니다. 비디오의 경우 I-프레임 위치가 이에 해당합니다. 오디오의 경우 대부분의 오디오 프레임이 랜덤 액세스 포인트로 간주될 수 있습니다. 비디오 트랙은 랜덤 액세스 포인트의 분포가 더 드물기 때문에 멀티플렉스 스트림에서는 이러한 포인트의 위치가 랜덤 액세스 포인트로 간주됩니다.

SourceBuffer 바이트 스트림 포맷 명세

SourceBuffer 인스턴스에서 허용되는 바이트 스트림 형식을 설명하는 바이트 스트림 포맷 명세입니다. 바이트 스트림 포맷 명세SourceBuffer 객체에 대해, typeaddSourceBuffer()로 전달하여 객체를 생성할 때 초기 선택되며, changeType() 호출로 변경될 수 있습니다.

SourceBuffer 구성

단일 MediaSource 인스턴스가 소유하는 하나 이상의 SourceBuffer 객체에 분배된 특정 트랙 집합입니다.

구현체는 다음 MediaSource 객체 구성을 최소 1개 이상 지원해야 합니다:

  • 오디오 트랙 1개 및/또는 비디오 트랙 1개를 처리하는 단일 SourceBuffer
  • 오디오 트랙 1개를 처리하는 SourceBuffer와 비디오 트랙 1개를 처리하는 SourceBuffer, 총 2개

MediaSource 객체는 위의 각 구성을 지원해야 하며, 동시에 하나의 구성만 지원하면 됩니다. 여러 구성을 동시에 지원하거나 추가 구성을 지원하는 것은 구현 품질에 따라 다릅니다.

트랙 설명

바이트 스트림 포맷에 따라 특정 트랙의 트랙 ID, 코덱 구성, 기타 메타데이터를 제공하는 구조입니다. 하나의 초기화 세그먼트 내 각 트랙 설명에는 고유한 트랙 ID가 있습니다. 트랙 ID가 초기화 세그먼트 내에서 고유하지 않으면, 사용자 에이전트는 append error 알고리즘을 실행해야 합니다.

트랙 ID

트랙 ID는 바이트 스트림 포맷에 따라 특정 트랙의 일부임을 표시하는 식별자입니다. 트랙 설명 내 트랙 ID는 해당 미디어 세그먼트의 어느 부분이 해당 트랙에 속하는지 식별합니다.

3. MediaSource 인터페이스

MediaSource 인터페이스는 HTMLMediaElement에 미디어 데이터를 공급하는 소스를 나타냅니다. 이 인터페이스는 해당 소스의 readyState와 프레젠테이션에 미디어 데이터를 추가할 수 있는 SourceBuffer 객체 목록을 관리합니다. MediaSource 객체는 웹 애플리케이션에서 생성된 후 HTMLMediaElement에 연결됩니다. 애플리케이션은 SourceBuffer 객체를 sourceBuffers를 통해 사용하여 미디어 데이터를 소스에 추가합니다. HTMLMediaElement는 재생 시 필요한 미디어 데이터를 MediaSource 객체에서 가져옵니다.

MediaSource 객체는 [[live seekable range]] 내부 슬롯을 가지며, 이는 정규화된 TimeRanges 객체를 저장합니다. MediaSource 객체가 생성될 때 빈 TimeRanges 객체로 초기화되며, setLiveSeekableRange()clearLiveSeekableRange()로 관리됩니다. 또한 10. HTMLMediaElement 확장에서 HTMLMediaElementseekable 동작을 수정하는 데 사용됩니다.

MediaSource 객체는 [[has ever been attached]] 내부 슬롯을 가지며, boolean 값을 저장합니다. MediaSource 객체 생성 시 false로 초기화되고, HTMLMediaElement리소스 가져오기 알고리즘에서 true로 설정됩니다. 이 확장된 리소스 가져오기 알고리즘MediaSourceMediaSourceHandleHTMLMediaElementsrcObject 속성에 설정할 때 조건부로 연결을 실패시킬 때 이 슬롯을 사용합니다.

WebIDLenum ReadyState {
  "closed",
  "open",
  "ended",
};
closed
소스가 현재 미디어 요소에 연결되어 있지 않음을 나타냅니다.
open
소스가 미디어 요소에 의해 열렸고, SourceBuffer 객체에 데이터를 추가할 준비가 되어 있음을 나타냅니다. MediaSourcesourceBuffers에서 사용됩니다.
ended
소스가 여전히 미디어 요소에 연결되어 있지만, MediaSourceendOfStream()가 호출된 상태입니다.
Issue 276: MSE-in-Workers: "closing" readyState를 추가하여 종료 중 발생하는 새로운 `InvalidStateError` 예외를 설명하는 방안 검토 mse-in-workers
WebIDLenum EndOfStreamError {
  "network",
  "decode",
};
network

재생을 종료하고 네트워크 오류가 발생했음을 신호합니다.

Note

JavaScript 애플리케이션은 네트워크 오류 발생 시 재생을 종료할 때 이 상태 코드를 사용해야 합니다. 예를 들어, 미디어 데이터를 가져오는 중에 네트워크 오류가 발생한 경우입니다.

decode

재생을 종료하고 디코딩 오류가 발생했음을 신호합니다.

Note

JavaScript 애플리케이션은 디코드 오류가 발생할 때 재생을 종료하기 위해 이 상태 코드를 사용해야 합니다. 예를 들어, 외부 미디어 데이터를 처리하는 중 파싱 오류가 발생한 경우입니다.

WebIDL[Exposed=(Window,DedicatedWorker)]
interface MediaSource : EventTarget {
    constructor();

    [SameObject, Exposed=DedicatedWorker]
    readonly  attribute MediaSourceHandle handle;
    readonly  attribute SourceBufferList sourceBuffers;
    readonly  attribute SourceBufferList activeSourceBuffers;
    readonly  attribute ReadyState readyState;

    attribute unrestricted double duration;
    attribute EventHandler onsourceopen;
    attribute EventHandler onsourceended;
    attribute EventHandler onsourceclose;

    static readonly attribute boolean canConstructInDedicatedWorker;

    SourceBuffer addSourceBuffer(DOMString type);
    undefined removeSourceBuffer(SourceBuffer sourceBuffer);
    undefined endOfStream(optional EndOfStreamError error);
    undefined setLiveSeekableRange(double start, double end);
    undefined clearLiveSeekableRange();
    static boolean isTypeSupported(DOMString type);
};

3.1 handle 속성

전용 워커에서 MediaSource 객체를 HTMLMediaElementsrcObject로 연결할 때 유용한 handle을 포함합니다. 이 handle은 해당 MediaSource 객체의 속성 접근 동안 동일한 객체로 유지되지만, 각 MediaSource 객체마다 별개의 객체입니다.

Note

이 명세는 향후 MediaSource 객체의 이 속성을 메인 Window 컨텍스트에서 보이게 할 수 있습니다. 만약 그렇게 된다면, 이 속성에 접근할 때 예외가 발생하는 등 기존과 호환되지 않는 변경을 방지하기 위해 명세의 세심한 관리가 필요합니다.

속성을 얻을 때 다음 단계를 실행합니다:

  1. 해당 MediaSource 객체의 handle이 아직 생성되지 않았다면 다음 단계를 실행합니다:
    1. created handle을 새 MediaSourceHandle 객체와 관련 리소스를 생성해 내부적으로 이 MediaSource에 연결하는 결과로 합니다.
    2. 속성 값을 created handle로 갱신합니다.
  2. 이 속성의 값인 MediaSourceHandle 객체를 반환합니다.

3.2 sourceBuffers 속성

MediaSource에 연결된 SourceBuffer 객체 목록을 포함합니다. MediaSourcereadyState가 "closed"일 때 이 목록은 비어 있습니다. readyState가 "open"으로 변경되면 addSourceBuffer()를 사용해 SourceBuffer 객체를 추가할 수 있습니다.

3.3 activeSourceBuffers 속성

sourceBuffersselected 비디오 트랙, enabled 오디오 트랙(들), 그리고 "showing" 또는 "hidden" 텍스트 트랙(들)을 제공하는 하위 집합을 포함합니다.

이 목록의 SourceBuffer 객체는 sourceBuffers 속성에 나타나는 순서와 동일하게 정렬되어야 합니다; 예를 들어, sourceBuffers[0]과 sourceBuffers[3]만 activeSourceBuffers에 있다면, activeSourceBuffers[0]은 sourceBuffers[0]과 같아야 하고, activeSourceBuffers[1]은 sourceBuffers[3]과 같아야 합니다.

Note

3.15.5 선택/활성화된 트랙 상태 변경에서 이 속성이 어떻게 갱신되는지 설명합니다.

3.4 readyState 속성

MediaSource 객체의 현재 상태를 나타냅니다. MediaSource가 생성될 때 readyState는 "closed"로 설정되어야 합니다.

3.5 duration 속성

웹 애플리케이션이 프레젠테이션의 지속 시간을 설정할 수 있습니다. MediaSource 객체가 생성될 때 초기값은 NaN입니다.

속성을 얻을 때 다음 단계를 실행합니다:

  1. readyState 속성이 "closed"이면 NaN을 반환하고 단계를 중단합니다.
  2. 속성의 현재 값을 반환합니다.

속성을 설정할 때 다음 단계를 실행합니다:

  1. 설정하는 값이 음수이거나 NaN이면 TypeError 예외를 발생시키고 단계를 중단합니다.
  2. readyState 속성이 "open"이 아니라면 InvalidStateError 예외를 발생시키고 단계를 중단합니다.
  3. updating 속성이 SourceBuffer 중 하나라도 true라면 InvalidStateError 예외를 발생시키고 단계를 중단합니다.
  4. duration change 알고리즘을 new duration을 이 속성에 할당된 값으로 실행합니다.
    Note

    duration change 알고리즘은 버퍼링된 코딩된 프레임의 종료 시간이 더 길면 new duration을 더 크게 조정합니다.

    Note

    appendBuffer()endOfStream() 호출 시 상황에 따라 duration 값을 갱신할 수 있습니다.

3.6 canConstructInDedicatedWorker 속성

true를 반환합니다.

Note

이 속성은 메인 스레드와 전용 워커에서 MediaSource 객체 생성 및 사용 지원 여부를 감지할 수 있게 해주며, 특히 기능이 지원되지 않는 경우 전용 워커에서 MediaSource 객체 생성 시도와 같은 높은 지연의 폴리필 필요성을 줄여줍니다.

3.7 addSourceBuffer() 메서드

SourceBuffersourceBuffers에 추가합니다.

  1. type이 빈 문자열이면 TypeError 예외를 발생시키고 단계를 중단합니다.
  2. type이 지원되지 않는 MIME 타입을 포함하거나, 다른 SourceBuffer 객체에 지정된 타입들과 함께 지원되지 않는 MIME 타입을 포함하면, NotSupportedError 예외를 발생시키고 단계를 중단합니다.
  3. 사용자 에이전트가 더 많은 SourceBuffer 객체를 처리할 수 없거나, type을 기반으로 SourceBuffer를 생성하면 지원되지 않는 SourceBuffer 구성이 된다면, QuotaExceededError 예외를 발생시키고 단계를 중단합니다.
    Note

    예를 들어, 사용자 에이전트는 미디어 요소가 HAVE_METADATA readyState에 도달했을 때 QuotaExceededError 예외를 발생시킬 수 있습니다. 이는 미디어 엔진이 재생 중에 트랙 추가를 지원하지 않을 경우 발생할 수 있습니다.

  4. readyState 속성이 "open" 상태가 아니면 InvalidStateError 예외를 발생시키고 단계를 중단합니다.
  5. bufferManagedSourceBuffer의 새 인스턴스로 생성합니다(현재 thisManagedMediaSource인 경우), 아니면 SourceBuffer의 새 인스턴스를 생성하고, 각각의 관련 리소스를 할당합니다.
  6. buffer[[generate timestamps flag]] 값을 Media Source Extensions™ Byte Stream Format Registry에서 type에 해당하는 "Generate Timestamps Flag" 열의 값으로 설정합니다.
  7. buffer[[generate timestamps flag]]가 true이면 buffermode를 "sequence"로 설정합니다. 아니면 buffermode를 "segments"로 설정합니다.
  8. Append bufferthissourceBuffers에 추가합니다.
  9. Queue a task이벤트를 발생시킵니다. 이벤트 이름은 addsourcebuffer이며, thissourceBuffers에서 발생시킵니다.
  10. buffer를 반환합니다.

3.8 removeSourceBuffer() 메서드

SourceBuffersourceBuffers에서 제거합니다.

  1. sourceBuffersourceBuffers에 없는 객체를 지정하면, NotFoundError 예외를 던지고 단계를 중단합니다.
  2. sourceBuffer.updating 속성이 true이면 다음 단계를 실행합니다:
    1. buffer append 알고리즘이 실행 중이면 중단합니다.
    2. sourceBuffer.updating 속성을 false로 설정합니다.
    3. 작업을 큐에 추가하여 이벤트 발생 이름은 abort이고, sourceBuffer에서 발생시킵니다.
    4. 작업을 큐에 추가하여 이벤트 발생 이름은 updateend이고, sourceBuffer에서 발생시킵니다.
  3. SourceBuffer audioTracks listsourceBuffer.audioTracks에서 반환된 AudioTrackList 객체로 설정합니다.
  4. SourceBuffer audioTracks list가 비어있지 않으면 다음 단계를 실행합니다:
    1. SourceBuffer audioTracks list의 각 AudioTrack 객체에 대해 다음 단계를 실행합니다:
      1. sourceBuffer 속성을 해당 AudioTrack 객체에서 null로 설정합니다.
      2. AudioTrack 객체를 SourceBuffer audioTracks list에서 제거합니다.
        Note

        이는 AudioTrackList [HTML] 로직에 따라 작업 큐 추가removetrack 이벤트 발생을 트리거해야 합니다. enabled 속성이 true였으면 change 이벤트도 트리거해야 합니다.

      3. mirror if necessary 알고리즘을 사용하여 Window에서 해당 AudioTrack 객체(혹은 Window mirror 객체)를 미디어 요소에서 제거합니다:
        1. HTMLMediaElement audioTracks list를 HTMLMediaElement의 audioTracks에서 반환된 AudioTrackList 객체로 설정합니다.
        2. AudioTrack 객체를 HTMLMediaElement audioTracks list에서 제거합니다.
          Note

          이는 AudioTrackList [HTML] 로직에 따라 작업 큐 추가removetrack 이벤트 발생을 트리거해야 합니다. enabled 속성이 true였으면 change 이벤트도 트리거해야 합니다.

  5. SourceBuffer videoTracks listsourceBuffer.videoTracks에서 반환된 VideoTrackList 객체로 설정합니다.
  6. SourceBuffer videoTracks list가 비어있지 않으면 다음 단계를 실행합니다:
    1. SourceBuffer videoTracks list의 각 VideoTrack 객체에 대해 다음 단계를 실행합니다:
      1. sourceBuffer 속성을 해당 VideoTrack 객체에서 null로 설정합니다.
      2. VideoTrack 객체를 SourceBuffer videoTracks list에서 제거합니다.
        Note

        이는 VideoTrackList [HTML] 로직에 따라 작업 큐 추가removetrack 이벤트 발생을 트리거해야 합니다. selected 속성이 true였으면 change 이벤트도 트리거해야 합니다.

      3. mirror if necessary 알고리즘을 사용하여 Window에서 해당 VideoTrack 객체(혹은 Window mirror 객체)를 미디어 요소에서 제거합니다:
        1. HTMLMediaElement videoTracks list를 HTMLMediaElement의 videoTracks에서 반환된 VideoTrackList 객체로 설정합니다.
        2. VideoTrack 객체를 HTMLMediaElement videoTracks list에서 제거합니다.
          Note

          이는 VideoTrackList [HTML] 로직에 따라 작업 큐 추가removetrack 이벤트 발생을 트리거해야 합니다. selected 속성이 true였으면 change 이벤트도 트리거해야 합니다.

  7. SourceBuffer textTracks listsourceBuffer.textTracks에서 반환된 TextTrackList 객체로 설정합니다.
  8. SourceBuffer textTracks list가 비어있지 않으면 다음 단계를 실행합니다:
    1. SourceBuffer textTracks list의 각 TextTrack 객체에 대해 다음 단계를 실행합니다:
      1. sourceBuffer 속성을 해당 TextTrack 객체에서 null로 설정합니다.
      2. TextTrack 객체를 SourceBuffer textTracks list에서 제거합니다.
        Note

        이는 TextTrackList [HTML] 로직에 따라 작업 큐 추가removetrack 이벤트 발생을 트리거해야 합니다. mode가 "showing" 또는 "hidden"이었으면 change 이벤트도 트리거해야 합니다.

      3. mirror if necessary 알고리즘을 사용하여 Window에서 해당 TextTrack 객체(혹은 Window mirror 객체)를 미디어 요소에서 제거합니다:
        1. HTMLMediaElement textTracks list를 HTMLMediaElement의 textTracks에서 반환된 TextTrackList 객체로 설정합니다.
        2. TextTrack 객체를 HTMLMediaElement textTracks list에서 제거합니다.
          Note

          이는 TextTrackList [HTML] 로직에 따라 작업 큐 추가removetrack 이벤트 발생을 트리거해야 합니다. mode가 "showing" 또는 "hidden"이었으면 change 이벤트도 트리거해야 합니다.

  9. sourceBufferactiveSourceBuffers에 있으면, sourceBufferactiveSourceBuffers에서 제거하고, 작업 큐 추가removesourcebuffer 이벤트 발생SourceBufferList에서 발생시킵니다.
  10. sourceBuffersourceBuffers에서 제거하고, 작업 큐 추가removesourcebuffer 이벤트 발생SourceBufferList에서 발생시킵니다.
  11. sourceBuffer의 모든 리소스를 소멸시킵니다.

3.9 endOfStream() 메서드

스트림의 종료를 신호합니다.

  1. readyState 속성이 "open" 상태가 아니라면 InvalidStateError 예외를 던지고 단계를 중단합니다.
  2. updating 속성이 SourceBuffer 중 하나라도 true라면 InvalidStateError 예외를 던지고 단계를 중단합니다.
  3. end of stream 알고리즘을 error 파라미터를 error로 설정해 실행합니다.

3.10 setLiveSeekableRange() 메서드

[[live seekable range]] 값을 갱신하며, 이는 10. HTMLMediaElement 확장에서 HTMLMediaElementseekable 동작을 수정하는 데 사용됩니다.

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

  1. readyState 속성이 "open"이 아니면 InvalidStateError 예외를 던지고 단계를 중단합니다.
  2. start가 음수이거나 end보다 크면, TypeError 예외를 던지고 단계를 중단합니다.
  3. [[live seekable range]] 값을, 시작 위치가 start이고 종료 위치가 end인 단일 범위를 가진 새로운 정규화된 TimeRanges 객체로 설정합니다.

3.11 clearLiveSeekableRange() 메서드

[[live seekable range]] 값을 갱신하며, 이는 10. HTMLMediaElement 확장에서 HTMLMediaElementseekable 동작을 수정하는 데 사용됩니다.

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

  1. readyState 속성이 "open"이 아니면 InvalidStateError 예외를 던지고 단계를 중단합니다.
  2. [[live seekable range]]가 범위를 포함하면, [[live seekable range]] 값을 새로운 빈 TimeRanges 객체로 설정합니다.

3.12 isTypeSupported() 메서드

MediaSource가 지정된 MIME 타입에 대해 SourceBuffer 객체를 생성할 수 있는지 확인합니다.

Note

이 메서드가 true를 반환해도 MediaSource 구현이 지정된 MIME 타입에 대해 SourceBuffer 객체를 생성할 수 있음을 의미할 뿐입니다. addSourceBuffer() 호출은 새 SourceBuffer 추가를 지원할 충분한 리소스가 없을 경우 실패할 수 있습니다.

Note

이 메서드가 true를 반환하면 HTMLMediaElementcanPlayType() 결과가 "maybe" 또는 "probably"일 것임을 의미합니다. MediaSource가 HTMLMediaElement가 재생할 수 없는 타입을 지원하는 것은 말이 되지 않기 때문입니다.

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

  1. type이 빈 문자열이면 false를 반환합니다.
  2. type에 유효한 MIME 타입 문자열이 없으면 false를 반환합니다.
  3. type이 MediaSource가 지원하지 않는 미디어 타입 또는 미디어 서브타입을 포함하면 false를 반환합니다.
  4. type이 MediaSource가 지원하지 않는 코덱을 포함하면 false를 반환합니다.
  5. MediaSource가 지정된 미디어 타입, 미디어 서브타입, 코덱 조합을 지원하지 않으면 false를 반환합니다.
  6. true를 반환합니다.

3.13 이벤트 요약

이벤트 이름 인터페이스 언제 디스패치되는지...
sourceopen Event MediaSourcereadyState가 "closed"에서 "open" 또는 "ended"에서 "open"로 변경될 때 디스패치됩니다.
sourceended Event MediaSourcereadyState가 "open"에서 "ended"로 변경될 때 디스패치됩니다.
sourceclose Event MediaSourcereadyState가 "open"에서 "closed" 또는 "ended"에서 "closed"로 변경될 때 디스패치됩니다.

3.14 크로스 컨텍스트 통신 모델

Window HTMLMediaElementDedicatedWorkerGlobalScopeMediaSource에 연결되면, 각각의 컨텍스트는 서로의 정보를 필요로 하는 알고리즘을 갖게 됩니다.

Note

HTMLMediaElementWindow 컨텍스트에만 노출되지만, 이 명세에서 정의된 MediaSource 및 관련 객체는 WindowDedicatedWorkerGlobalScope 컨텍스트 모두에 노출됩니다. 이를 통해 애플리케이션은 두 컨텍스트 중 어느 쪽에서든 MediaSource 객체를 생성하고, MediaSource 객체 URL 또는 MediaSourceHandle을 사용하여 HTMLMediaElement 객체를 Window 컨텍스트에 연결할 수 있습니다. MediaSource 객체는 Transferable가 아니며, 생성된 컨텍스트에서만 볼 수 있습니다.

이하 내용은 Window 미디어 요소가 DedicatedWorkerGlobalScopeMediaSource에 연결될 때 정보 지연을 제한하는 모델을 설명합니다. 모델은 메시지 전달을 통한 통신을 설명하지만, 구현체는 공유 메모리와 락 등 더 빠른 통신 방식을 선택할 수 있습니다. WindowMediaSource에 대한 연결은 이미 정보를 가지고 있으므로 컨텍스트 간 통신이 필요하지 않습니다.

MediaSourceDedicatedWorkerGlobalScope에서 생성된 경우, [[port to main]] 내부 슬롯을 가지며, 이는 연결 중 설정되고 분리 중 null이 되는 MessagePort를 저장합니다. Window[[port to main]]은 항상 null입니다.

이 명세로 확장되고 DedicatedWorkerGlobalScopeMediaSource에 연결된 HTMLMediaElement[[port to worker]] 내부 슬롯도 가지며, 이는 연결 중 설정되고 분리 중 null이 되는 MessagePort를 저장합니다. 또 [[channel with worker]] 내부 슬롯도 가지며, 이는 연결 중 설정되고 분리 중 null이 되는 MessageChannel를 저장합니다. [[port to worker]][[channel with worker]]DedicatedWorkerGlobalScopeMediaSource에 연결되지 않은 경우 null입니다.

이 명세의 알고리즘이 WindowHTMLMediaElement에서 연결된 DedicatedWorkerGlobalScopeMediaSource로 혹은 그 반대로 정보를 전달할 필요가 있으면, 이러한 내부 포트를 암묵적으로 사용하여 상대방에게 메시지를 전달하며, 해당 메시지의 암묵적 핸들러가 알고리즘에 명시된 단계를 실행합니다.

3.15 알고리즘

3.15.1 미디어 요소에 연결

MediaSource를 미디어 요소에 연결하는 메커니즘은 해당 MediaSource 객체가 Window에서 생성되었는지 또는 DedicatedWorkerGlobalScope에서 생성되었는지에 따라 달라집니다:

리소스 가져오기 알고리즘이 미디어 제공자 객체로 MediaSource 객체, MediaSourceHandle 객체, 또는 객체가 MediaSource인 URL 레코드로 호출된 경우, 모드를 local로 설정하고 (그렇지 않으면 모드를 remote로 설정할 수 있는) 리소스 가져오기 알고리즘의 첫 번째 단계를 건너뛴 뒤 알고리즘 실행을 계속합니다.

Note

리소스 가져오기 알고리즘의 첫 단계는, 객체가 미디어 제공자 객체인 URL 레코드에 대해 로컬 모드를 선택하는 방향으로 결국 일치되도록 조정될 것으로 예상됩니다. 의도는 HTMLMediaElementsrc 특성이나 선택된 자식 sourcesrc 특성이, 해당 src 특성이 마지막으로 변경되었을 때 MediaSource 객체 URL과 일치하는 blob: URL이라면, MediaSource 객체가 리소스 가져오기 알고리즘의 로컬 모드 로직에서 미디어 제공자 객체이자 현재 미디어 리소스로 사용된다는 것입니다. 이는 MediaSource 객체가 연결된 경우, preload 특성 준수를 포함하는 원격 모드 로직이 건너뛰어진다는 의미이기도 합니다. 설령 [HTML]에 그러한 향후 변경이 이루어지더라도, 현재 미디어 리소스가 MediaSource 객체인 경우에는 로컬 모드 로직 시작 시 아래 단계들의 실행이 여전히 필요합니다.

리소스 가져오기 알고리즘의 “그 외(모드가 로컬)” 섹션 시작 시, 아래의 추가 단계를 실행합니다.

Note

미디어 요소의 리소스 선택 알고리즘을 트리거한 동작에 비추어 보면, 이 단계들은 비동기적입니다. 리소스 가져오기 알고리즘은 리소스 선택 알고리즘을 호출한 작업이 계속 진행되어 안정 상태에 도달한 뒤에 실행됩니다. 구현체는 아래 “그 외” 절의 단계를 MediaSource 객체가 사용할 준비가 될 때까지 지연할 수 있습니다.

  1. 리소스 가져오기 알고리즘이 미디어 제공자 객체로 MediaSource 객체, MediaSourceHandle 객체, 또는 객체가 MediaSource인 URL 레코드로 호출된 경우:
    미디어 제공자 객체가, 예컨대 DedicatedWorkerGlobalScope에서 생성된 MediaSourceMediaSource 객체 URL을 사용하려는 경우처럼, 객체가 MediaSource인 URL 레코드인 경우
    리소스 가져오기 알고리즘미디어 데이터 처리 단계 목록에서 "네트워크 오류로 인해 미디어 데이터를 전혀 가져올 수 없어, 사용자 에이전트가 리소스 가져오기를 포기하는 경우" 단계를 실행합니다.
    Note
    이는 DedicatedWorker의 MediaSource 연결에 MediaSource 객체 URL을 사용하는 것을 방지합니다. DedicatedWorker에서 Window 컨텍스트로 MediaSourcehandle을 전달하고 미디어 요소의 srcObject 특성에 할당하는 것이 그러한 MediaSource를 연결하는 유일한 방법입니다.
    미디어 제공자 객체가 MediaSourceHandle이고, 그 내부 슬롯 [[Detached]]가 true인 경우
    리소스 가져오기 알고리즘미디어 데이터 처리 단계 목록에서 "네트워크 오류로 인해 미디어 데이터를 전혀 가져올 수 없어, 사용자 에이전트가 리소스 가져오기를 포기하는 경우" 단계를 실행합니다.
    미디어 제공자 객체가 MediaSourceHandle이고, 그 기저의 MediaSource[[has ever been attached]] 내부 슬롯이 true인 경우
    리소스 가져오기 알고리즘미디어 데이터 처리 단계 목록에서 "네트워크 오류로 인해 미디어 데이터를 전혀 가져올 수 없어, 사용자 에이전트가 리소스 가져오기를 포기하는 경우" 단계를 실행합니다.
    Note
    이는 MediaSourceWindow에서 생성되었고 이전에 MediaSource 객체 URL을 사용해 로드되었더라도, 동일한 기저 MediaSourceMediaSourceHandle로 두 번 이상 로드하는 것을 방지합니다. 다만, 이후에는 WindowMediaSource에 대해 MediaSource 객체 URL을 사용하는 것이 성공하는 것을 배제하지는 않습니다.
    readyState가 "closed"로 설정되어 있지 않은 경우
    리소스 가져오기 알고리즘미디어 데이터 처리 단계 목록에서 "네트워크 오류로 인해 미디어 데이터를 전혀 가져올 수 없어, 사용자 에이전트가 리소스 가져오기를 포기하는 경우" 단계를 실행합니다.
    그 외의 경우
    1. MediaSource[[has ever been attached]] 내부 슬롯을 true로 설정합니다.
    2. 미디어 요소의 delaying-the-load-event-flag를 false로 설정합니다.
    3. MediaSourceDedicatedWorkerGlobalScope에서 생성된 경우, 워커 연결 통신을 설정하고 MediaSource를 엽니다:
      1. [[channel with worker]]를 새로운 MessageChannel로 설정합니다.
      2. [[port to worker]]port1의 값으로 설정합니다(대상: [[channel with worker]]).
      3. StructuredSerializeWithTransfer를 실행하되, port2를 값이자 transferList의 유일한 멤버로 사용하고, 그 결과를 serialized port2로 둡니다.
      4. 작업을 큐에 추가하여 MediaSourceDedicatedWorkerGlobalScope에서 다음을 수행하도록 합니다:
        1. StructuredDeserializeWithTransferserialized port2DedicatedWorkerGlobalScoperealm으로 실행하고, [[port to main]]을 전송된 port2의 역직렬화된 복제본으로 설정합니다(대상: [[channel with worker]]).
        2. readyState 특성을 "open"으로 설정합니다.
        3. 작업을 큐에 추가하여 이벤트 sourceopenMediaSource에서 발생시킵니다.
      그 외의 경우, MediaSourceWindow에서 생성된 경우:
      1. [[channel with worker]]를 null로 설정합니다.
      2. [[port to worker]]를 null로 설정합니다.
      3. [[port to main]]을 null로 설정합니다.
      4. readyState 특성을 "open"으로 설정합니다.
      5. 작업을 큐에 추가하여 이벤트 sourceopenMediaSource에서 발생시킵니다.
    4. 리소스 가져오기 알고리즘을 계속 수행하되, 남은 "그 외(모드가 로컬)" 단계를 다음 요구사항과 함께 실행합니다:
      1. 리소스 가져오기 알고리즘이나 미디어 데이터 처리 단계 목록에서 "the download", "bytes received", "whenever new data for the current media resource becomes available" 같은 표현은 appendBuffer()를 통해 전달된 데이터를 의미합니다.
      2. 리소스 가져오기 알고리즘미디어 데이터 처리 단계 목록의 HTTP에 관한 언급은 적용되지 않습니다. 이는 MediaSource가 연결된 경우 HTMLMediaElement가 HTTP로 미디어 데이터를 가져오지 않기 때문입니다.
Note

연결된 MediaSource는 리소스 가져오기 알고리즘의 원격 모드 단계를 사용하지 않으므로, 미디어 요소는 "suspend" 이벤트를 발생시키지 않습니다. 향후 이 명세의 버전에서는 MediaSource가 연결된 미디어 요소에서 "progress" 및 "stalled" 이벤트도 제거될 가능성이 높지만, 이 버전에 부합하는 사용자 에이전트는 이 명세 구현이 안정화된 이후 [HTML] 참조가 변경되었기 때문에 여전히 이 두 이벤트를 발생시킬 수 있습니다.

3.15.2 미디어 요소에서 분리

다음 단계는 미디어 요소가 NETWORK_EMPTY로 전환하고, 미디어 요소에서 작업을 큐에 추가하여 이벤트를 발생시키는데 이름이 emptied인 경우에 항상 실행됩니다. 이러한 단계는 전환 직전에 실행되는 것이 권장됩니다.

  1. MediaSourceDedicatedWorkerGlobalScope에서 생성된 경우:
    1. 내부 detach 메시지를 [[port to worker]]에 게시하여 MediaSource에 알립니다.
    2. [[port to worker]]를 null로 설정합니다.
    3. [[channel with worker]]를 null로 설정합니다.
    4. detach 알림에 대한 암묵적 메시지 핸들러는 나머지 단계들을 DedicatedWorkerGlobalScopeMediaSource에서 실행합니다.
    그 외의 경우, MediaSourceWindow에서 생성된 경우:
    나머지 단계들을 WindowMediaSource에서 계속 실행합니다.
  2. [[port to main]]을 null로 설정합니다.
  3. readyState 특성을 "closed"로 설정합니다.
  4. thisManagedMediaSource인 경우, streaming 특성을 false로 설정합니다.
  5. duration을 NaN으로 업데이트합니다.
  6. SourceBuffer 객체를 모두 activeSourceBuffers에서 제거합니다.
  7. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 removesourcebuffer이며, 대상은 activeSourceBuffers입니다.
  8. SourceBuffer 객체를 모두 sourceBuffers에서 제거합니다.
  9. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 removesourcebuffer이며, 대상은 sourceBuffers입니다.
  10. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 sourceclose이며, 대상은 MediaSource입니다.
Note

앞으로, 이 알고리즘은 외부에서 호출되어, 연결된 MediaSource(있는 경우)를 미디어 요소에서 분리해야 하는 모든 경우에 실행되도록 의도되었습니다. 이는 HTMLMediaElement [HTML]의 load() 같은 동작이나 리소스 가져오기 알고리즘의 실패 시에도(또는 이에 대신하여) 호출될 수 있습니다. 이는 미디어 요소가 NETWORK_EMPTY로 전환할 때뿐만 아니라 적용됩니다. 리소스 가져오기 알고리즘 실패란 리소스 가져오기 알고리즘 또는 리소스 선택 알고리즘을 중단시키는 실패를 의미하되, [HTML]의 “Final step”은 분리를 유발하는 실패로 간주되지 않습니다.

3.15.3 탐색

다음 단계를 탐색 알고리즘의 “사용자 에이전트가 새 재생 위치의 미디어 데이터가 사용 가능한지 여부를 파악하고, 사용 가능하다면 해당 위치를 재생할 만큼 충분한 데이터를 디코딩할 때까지 기다린다” 단계의 일부로 실행합니다:

  1. Note

    미디어 요소는 SourceBuffer의 각 객체(대상: activeSourceBuffers)에서, media segmentsnew playback position을 포함하는 것을 찾습니다. 현재 HTMLMediaElementbuffered 특성 값의 TimeRanges 내 임의의 위치는 해당 위치에 필요한 모든 미디어 세그먼트가 버퍼링되어 있습니다.

    new playback positionTimeRanges 중 어느 것에도 포함되어 있지 않은 경우(대상: HTMLMediaElementbuffered)
    1. HTMLMediaElementreadyState 특성이 HAVE_METADATA보다 크면, HTMLMediaElementreadyState 특성을 HAVE_METADATA로 설정합니다.
      Note

      HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

    2. 미디어 요소는 appendBuffer() 호출이 coded frame processing 알고리즘을 통해 HTMLMediaElementreadyState 특성을 HAVE_METADATA보다 큰 값으로 설정할 때까지 대기합니다.
      Note

      웹 애플리케이션은 bufferedHTMLMediaElementbuffered를 사용하여 재생 재개에 필요한 것이 무엇인지 판단할 수 있습니다.

    그 외의 경우
    계속 진행
    Note

    readyState 특성이 "ended"이고, new playback position이 현재 TimeRanges 중 하나에 포함되어 HTMLMediaElementbuffered에 나타나 있다면, 현재 선택 또는 활성화된 트랙 버퍼 중 하나 이상의 최대 범위 종료 타임스탬프가 new playback position보다 작더라도, 탐색 동작은 여기서 완료될 때까지 계속되어야 합니다. 이 조건은 buffered의 로직이 readyState가 "ended"일 때 발생시키는 경우에만 나타나야 합니다.

  2. 미디어 요소는 모든 디코더를 재설정하고, 각 디코더를 적절한 initialization segment의 데이터로 초기화합니다.
  3. 미디어 요소는 활성 트랙 버퍼에서 coded frames를 디코더에 공급하되, new playback position 이전의 가장 가까운 random access point부터 시작합니다.
  4. 탐색 알고리즘의 “안정 상태를 대기” 단계에서 재개합니다.

3.15.4 SourceBuffer 모니터링

다음 단계는 재생 중 주기적으로 실행되어, SourceBuffer 객체들이 activeSourceBuffers 내에서 중단 없는 재생을 보장할 만큼 충분한 데이터를 보유하는지 확인합니다. 또한 activeSourceBuffers의 변경은 상태 전환을 트리거하는 조건에 영향을 미치므로, 이러한 단계의 실행을 유발합니다.

중단 없는 재생을 보장할 만큼 충분한 데이터가 있다는 것은, 사용자 에이전트가 현재 의미 있는 시간 동안 정지 없이 프레젠테이션을 재생할 수 있을 만큼 충분한 데이터가 있다고 판단하는 구현별 조건입니다. 이 조건은 미디어 요소를 HAVE_ENOUGH_DATA 준비 상태로 들어가거나 빠져나가게 할 시점을 결정하기 위해 지속적으로 평가됩니다. 이러한 전환은 사용자 에이전트가 충분한 데이터가 버퍼링되었다고 믿는지, 아니면 더 많은 데이터가 필요한지를 각각 나타냅니다.

Note

구현은 버퍼링된 바이트 수, 버퍼링된 시간, append 속도 또는 적절하다고 판단하는 다른 지표를 사용하여 충분한 데이터가 있는 시점을 판단할 수 있습니다. 사용되는 지표는 재생 중 변경될 수 있으므로, 웹 애플리케이션은 더 많은 데이터가 필요한지 여부를 판단하기 위해 HTMLMediaElementreadyState 값에만 의존하는 것이 권장됩니다.

Note

미디어 요소에 더 많은 데이터가 필요할 때, 사용자 에이전트는 웹 애플리케이션이 중단 없이 대응할 수 있도록 충분히 이른 시점에 HAVE_ENOUGH_DATA에서 HAVE_FUTURE_DATA로 전환하는 것이 권장됩니다. 예를 들어, 현재 재생 위치가 버퍼링된 데이터의 끝보다 500ms 앞설 때 전환하면, 애플리케이션은 재생이 중단되기 전에 대략 500ms 동안 더 많은 데이터를 append할 수 있습니다.

HTMLMediaElementreadyState 특성이 HAVE_NOTHING인 경우:
  1. 이 단계를 중단합니다.
HTMLMediaElementbuffered가 현재 재생 위치를 포함하는 TimeRanges를 포함하지 않는 경우:
  1. HTMLMediaElementreadyState 특성을 HAVE_METADATA로 설정합니다.
    Note

    HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

  2. 이 단계를 중단합니다.
HTMLMediaElementbuffered가 현재 재생 위치를 포함하고, 또한 중단 없는 재생을 보장할 만큼 충분한 데이터가 있는 TimeRanges를 포함하는 경우:
  1. HTMLMediaElementreadyState 특성을 HAVE_ENOUGH_DATA로 설정합니다.
    Note

    HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

  2. 이전에 HAVE_CURRENT_DATA로 전환하면서 재생이 일시 중단되었다면, 이 시점에 재생이 재개될 수 있습니다.
  3. 이 단계를 중단합니다.
HTMLMediaElementbuffered가 현재 재생 위치를 포함하고, 현재 위치 이후의 일부 시간도 포함하는 TimeRanges를 포함하는 경우, 다음 단계를 실행합니다:
  1. HTMLMediaElementreadyState 특성을 HAVE_FUTURE_DATA로 설정합니다.
    Note

    HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

  2. 이전에 HAVE_CURRENT_DATA로 전환하여 재생이 일시 중단되었다면, 이 시점에 재생이 재개될 수 있습니다.
  3. 이 단계를 중단합니다.
HTMLMediaElementbuffered가 현재 재생 위치에서 끝나고, 현재 위치 직후를 덮는 범위가 없는 TimeRanges를 포함하는 경우:
  1. HTMLMediaElementreadyState 특성을 HAVE_CURRENT_DATA로 설정합니다.
    Note

    HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

  2. 미디어 요소는 미디어 타임라인을 전진시키기에 충분한 데이터가 없으므로, 이 시점에 재생이 일시 중단됩니다.
  3. 이 단계를 중단합니다.

3.15.5 선택/활성화된 트랙 상태 변경

재생 중, activeSourceBuffers는 다음의 경우 업데이트되어야 합니다. 즉, 비디오 트랙의 selected 상태, 오디오 트랙(들)의 enabled 상태, 또는 텍스트 트랙의 mode가 변경될 때입니다. 이러한 변경이 하나 이상 발생하면 다음 단계를 따라야 합니다. 또한 MediaSourceDedicatedWorkerGlobalScope에서 생성된 경우, 내부 create track mirror 메시지의 암묵적 핸들러가 이전에 생성한 트랙의 Window 미러에 발생하는 각 변경도 반드시 [[port to worker]]에 게시되는 내부 update track state 메시지를 사용하여 해당 DedicatedWorkerGlobalScope 트랙에도 반영되어야 하며, 암묵적 핸들러가 변경을 적용하고 다음 단계를 실행합니다. 마찬가지로 DedicatedWorkerGlobalScope의 트랙에 발생하는 각 변경도 반드시 [[port to main]]에 게시되는 내부 update track state 메시지를 사용하여 해당 트랙의 Window 미러에도 반영되어야 하며, 암묵적 핸들러가 미러에 변경을 적용합니다.

선택된 비디오 트랙이 변경되면 다음 단계를 실행합니다:
  1. 이전에 선택된 비디오 트랙과 연관된 SourceBuffer가 다른 활성화된 트랙과 연관되어 있지 않다면, 다음 단계를 실행합니다:
    1. 해당 SourceBufferactiveSourceBuffers에서 제거합니다.
    2. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 removesourcebuffer이며, 대상은 activeSourceBuffers입니다.
  2. 새로 선택된 비디오 트랙과 연관된 SourceBuffer가 아직 activeSourceBuffers에 없다면, 다음 단계를 실행합니다:
    1. 해당 SourceBufferactiveSourceBuffers에 추가합니다.
    2. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 addsourcebuffer이며, 대상은 activeSourceBuffers입니다.
오디오 트랙이 비활성화되고, 이 트랙과 연관된 SourceBuffer가 다른 활성화되거나 선택된 트랙과 연관되어 있지 않다면, 다음 단계를 실행합니다:
  1. 해당 오디오 트랙과 연관된 SourceBufferactiveSourceBuffers에서 제거합니다.
  2. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 removesourcebuffer이며, 대상은 activeSourceBuffers입니다.
오디오 트랙이 활성화되고, 이 트랙과 연관된 SourceBuffer가 아직 activeSourceBuffers에 없다면, 다음 단계를 실행합니다:
  1. 해당 오디오 트랙과 연관된 SourceBufferactiveSourceBuffers에 추가합니다.
  2. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 addsourcebuffer이며, 대상은 activeSourceBuffers입니다.
텍스트 트랙의 mode"disabled"로 바뀌고, 이 트랙과 연관된 SourceBuffer가 다른 활성화되거나 선택된 트랙과 연관되어 있지 않다면, 다음 단계를 실행합니다:
  1. 해당 텍스트 트랙과 연관된 SourceBufferactiveSourceBuffers에서 제거합니다.
  2. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 removesourcebuffer이며, 대상은 activeSourceBuffers입니다.
텍스트 트랙의 mode"showing" 또는 "hidden"으로 바뀌고, 이 트랙과 연관된 SourceBuffer가 아직 activeSourceBuffers에 없다면, 다음 단계를 실행합니다:
  1. 해당 텍스트 트랙과 연관된 SourceBufferactiveSourceBuffers에 추가합니다.
  2. 작업을 큐에 추가하여 이벤트를 발생시키는데 이름은 addsourcebuffer이며, 대상은 activeSourceBuffers입니다.

3.15.6 Duration 변경

durationnew duration 값으로 변경할 때 다음 단계를 따릅니다.

  1. 현재 duration 값이 new duration과 같으면 return합니다.
  2. new durationsourceBuffers 내 모든 SourceBuffer의 버퍼된 coded frames 중 가장 높은 presentation timestamp보다 작으면, InvalidStateError 예외를 던지고 단계를 중단합니다.
    Note

    현재 버퍼링된 미디어를 잘라내는 Duration 감소는 허용되지 않습니다. 잘라내야 할 경우 remove()로 버퍼링 범위를 먼저 줄인 뒤 duration을 업데이트하세요.

  3. highest end timesourceBuffers 내 모든 SourceBuffertrack bufferstrack buffer ranges의 최대 종료값으로 합니다.
  4. new durationhighest end time보다 작으면
    Note

    이 조건은 coded frame removal 알고리즘이 제거 범위 시작 이전의 coded frame을 남겨두기 때문에 발생할 수 있습니다.

    1. new durationhighest end time으로 업데이트합니다.
  5. duration 값을 new duration으로 업데이트합니다.
  6. mirror if necessary 알고리즘을 사용해 Window에서 미디어 요소의 duration을 업데이트하는 다음 단계를 실행합니다:
    1. 미디어 요소의 durationnew duration으로 업데이트합니다.
    2. HTMLMediaElement duration change algorithm을 실행합니다.

3.15.7 스트림 종료

이 알고리즘은 애플리케이션이 endOfStream()를 호출하거나, 어떤 알고리즘에서 디코드 오류 신호가 필요할 때 호출됩니다. 이 알고리즘은 오류가 신호되어야 하는지 여부를 나타내는 error 파라미터를 받습니다.

  1. readyState 특성 값을 "ended"로 변경합니다.
  2. 작업을 큐에 추가하여 이벤트 이름이 sourceended인 이벤트를 MediaSource에서 발생시킵니다.
  3. error가 설정되지 않은 경우
    1. duration change 알고리즘을 sourceBuffers의 모든 SourceBuffertrack bufferstrack buffer ranges 중 가장 큰 end time을 new duration으로 설정해 실행합니다.
      Note

      이렇게 하면 duration이 append된 미디어 세그먼트의 끝을 제대로 반영하게 됩니다. 예를 들어 duration이 10초로 명시적으로 설정되어 있는데 endOfStream() 호출 전에 0~5초 미디어 세그먼트만 append되었다면, duration은 5초로 업데이트됩니다.

    2. 미디어 요소에 모든 미디어 데이터가 준비되었음을 알립니다.
    error가 "network"로 설정된 경우
    mirror if necessary 알고리즘을 사용해 Window에서 다음 단계를 실행합니다:
    HTMLMediaElementreadyState 특성이 HAVE_NOTHING과 같으면
    resource fetch algorithmmedia data processing steps list에서 "네트워크 오류로 인해 미디어 데이터를 전혀 가져올 수 없어, 사용자 에이전트가 리소스 가져오기를 포기하는 경우" 단계를 실행합니다.
    HTMLMediaElementreadyState 특성이 HAVE_NOTHING보다 크면
    resource fetch algorithmmedia data processing steps list에서 "일부 미디어 데이터가 수신된 뒤 연결이 중단되어, 사용자 에이전트가 리소스 가져오기를 포기하는 경우" 단계를 실행합니다.
    error가 "decode"로 설정된 경우
    mirror if necessary 알고리즘을 사용해 Window에서 다음 단계를 실행합니다:
    HTMLMediaElementreadyState 특성이 HAVE_NOTHING과 같으면
    resource fetch algorithmmedia data processing steps list에서 "미디어 데이터를 가져올 수 있으나 검사 결과 지원되지 않는 포맷이거나, 전혀 렌더링할 수 없는 경우" 단계를 실행합니다.
    HTMLMediaElementreadyState 특성이 HAVE_NOTHING보다 크면
    media data is corrupted 단계와, resource fetch algorithmmedia data processing steps list 단계를 실행합니다.

3.15.8 필요 시 미러

이 알고리즘은 Window에서 MediaSource가 동일 Window 또는 DedicatedWorkerGlobalScope에서 연결되어 있을 때, 일반적으로 연결된 HTMLMediaElement의 상태를 업데이트하기 위해 Window에서 실행할 steps 목록을 받습니다.

MediaSourceDedicatedWorkerGlobalScope에서 생성된 경우:
내부 mirror on window 메시지를 [[port to main]]에 게시하면, Window의 암묵적 핸들러가 steps를 실행합니다. 이 메시지 핸들러가 메시지를 받을 때까지 기다리지 않고 바로 제어를 반환합니다.
Note
미러 메시지 메커니즘의 목적은 다음을 보장하는 것입니다:
  1. stepsWindow에서 자체 작업으로 비동기적으로 실행되고, steps가 다른 Window 작업 중간에 실행되지 않도록 함
  2. stepsDedicatedWorkerGlobalScope에서 이 알고리즘의 동기 실행과 반환을 막지 않도록 함
그 외의 경우:
steps를 실행합니다.

4. MediaSourceHandle 인터페이스

MediaSourceHandle 인터페이스는 MediaSource 객체의 프록시를 나타내며, DedicatedWorkerGlobalScope에서 생성된 MediaSourceWindowHTMLMediaElementsrcObject를 통해 연결할 때 유용합니다. 자세한 내용은 미디어 요소에 연결 알고리즘을 참고하세요.

Note

이 별도의 객체는 교차 컨텍스트의 MediaSource를 미디어 요소에 연결하기 위해 필요합니다. MediaSource 객체 자체는 이벤트 타겟이기 때문에 transferable이 아니기 때문입니다.

MediaSourceHandle 객체는 [[has ever been assigned as srcobject]] 내부 슬롯을 가지며, boolean 값을 저장합니다. 이 값은 MediaSourceHandle 객체 생성 시 false로 초기화되며, HTMLMediaElementsrcObject setter에서 true로 설정됩니다. (자세한 내용은 10. HTMLMediaElement 확장 참고.) 이 값이 true이면, MediaSourceHandle의 성공적인 전송이 4.1 Transfer에서 설명된 대로 방지됩니다.

MediaSourceHandle 객체는 Transferable이며, 각 객체는 [[Detached]] 내부 슬롯을 가지며, 이 슬롯은 핸들 객체 인스턴스가 한 번 전송된 이후 다시 전송할 수 없음을 보장하는 데 사용됩니다.

WebIDL[Transferable, Exposed=(Window,DedicatedWorker)]
interface MediaSourceHandle {};

4.1 전송

MediaSourceHandletransfer stepstransfer-receiving steps는 구현이 기본 MediaSource를 참조하는 암묵적 내부 슬롯을 유지하여, srcObject를 활용한 미디어 요소에 연결 및 그에 따른 크로스 컨텍스트 통신 모델 설정이 가능하도록 해야 합니다.

Note

구현자는 Transferable에서 암시된 "move" 의미가 항상 실제로 보장되는 것은 아니라는 점을 알아야 합니다. 예를 들어 postMessage의 확장 또는 내부 broadcast 구현은 전송된 MediaSourceHandle의 복수 수신자를 의도치 않게 만들 수 있습니다. 이 이유로, 구현은 기본 MediaSourceHandle의 어떤 핸들이 아직 연결에 유효한지, 미디어 요소의 리소스 선택 알고리즘의 비동기 부분에서 사용되기 전까지 확정하지 않는 것이 좋습니다. 이는 MediaSource 객체 URL을 통한 연결의 기존 동작과 비슷합니다. 객체 URL은 쉽게 복제 가능하며, 해당 URL은 (그 많은 복제본 중) 최대 한 번만 연결 시작에 유효합니다.

구현은 MediaSourceHandle의 기본 MediaSource 객체에 대해, srcObject를 통한 연결(load)이 한번만 성공하도록 반드시 지원해야 합니다. 이는 Transferable의 다양한 구현으로 인해 MediaSourceHandle가 복제될 수 있더라도 마찬가지입니다.

Note

이 동작이 미디어 요소의 리소스 선택 알고리즘의 비동기 부분에서 어떻게 강제되는지는 미디어 요소에 연결을 참고하세요.

MediaSourceHandleWindowDedicatedWorkerGlobalScope 컨텍스트에서만 노출되며, 서로 다른 agent cluster [ECMASCRIPT] 간에는 성공적으로 전송할 수 없습니다. MediaSourceHandle 객체의 전송은 동일한 agent cluster 내에서만 성공할 수 있습니다.

Note

예를 들어 MediaSourceHandle 객체를 WindowDedicatedWorkerGlobalScope에서 SharedWorker나 ServiceWorker로 전송하면 성공하지 않습니다. 개발자는 MediaSource 객체 URLDOMString이므로 여러 방식으로 전달될 수 있다는 점과의 차이를 인지해야 합니다. 다만 미디어 요소에 연결MediaSource 객체 URL로 할 경우, MediaSourceWindow 컨텍스트에서 생성되어야만 성공할 수 있습니다. 또한 Web Application API 관련 개념으로 dedicated worker agents 등이 정의된 agentagent cluster의 형식화도 참고하세요.

Transfer steps에서 MediaSourceHandle 객체는 반드시 다음 단계를 포함해야 합니다:

  1. MediaSourceHandle[[has ever been assigned as srcobject]] 내부 슬롯이 true이면, transfer stepsDataCloneError 예외를 던져야 하며, 실패해야 합니다.

5. SourceBuffer 인터페이스

WebIDLenum AppendMode {
  "segments",
  "sequence",
};
segments
미디어 세그먼트 내 타임스탬프가 코딩된 프레임이 프레젠테이션에서 어디에 배치될지 결정합니다. 미디어 세그먼트는 어떤 순서로든 append할 수 있습니다.
sequence
미디어 세그먼트는 해당 세그먼트 내 타임스탬프와 상관없이 시간상 인접한 것으로 간주됩니다. 새로운 미디어 세그먼트 내 코딩된 프레임은 이전 미디어 세그먼트의 코딩된 프레임 바로 뒤에 배치됩니다. timestampOffset 속성은 새로운 미디어 세그먼트가 이전 세그먼트와 인접하도록 새로운 offset이 필요할 때 업데이트됩니다. "sequence" 모드에서 timestampOffset을 설정하면, 미디어 세그먼트 내 타임스탬프를 몰라도 타임라인의 특정 위치에 배치할 수 있습니다.
WebIDL[Exposed=(Window,DedicatedWorker)]
interface SourceBuffer : EventTarget {
  attribute AppendMode mode;
  readonly  attribute boolean updating;
  readonly  attribute TimeRanges buffered;
  attribute double timestampOffset;
  readonly  attribute AudioTrackList audioTracks;
  readonly  attribute VideoTrackList videoTracks;
  readonly  attribute TextTrackList textTracks;
  attribute double appendWindowStart;
  attribute unrestricted double appendWindowEnd;

  attribute EventHandler onupdatestart;
  attribute EventHandler onupdate;
  attribute EventHandler onupdateend;
  attribute EventHandler onerror;
  attribute EventHandler onabort;

  undefined appendBuffer(BufferSource data);
  undefined abort();
  undefined changeType(DOMString type);
  undefined remove(double start, unrestricted double end);
};
Issue 280: MSE-in-Workers: {Audio,Video,Text}Track{,List} IDL in HTML에 DedicatedWorker가 추가적으로 Exposed 되어야 함 mse-in-workers
[HTML] AudioTrackList, VideoTrackList 그리고 TextTrackList 는 Window+DedicatedWorker에 노출되어야 합니다.

5.1 속성

mode 타입 AppendMode

미디어 세그먼트 시퀀스를 어떻게 처리할지 제어합니다. 이 속성은 객체가 생성된 뒤 addSourceBuffer()로 최초 설정되며, changeType()나 이 속성을 직접 설정해서 변경할 수 있습니다.

get 시, 초기값 또는 마지막으로 성공적으로 설정된 값을 반환합니다.

set 시 다음 단계를 실행합니다:

  1. 이 객체가 sourceBuffers에서 부모 미디어 소스에서 제거되었다면, InvalidStateError 예외를 던지고 단계를 중단합니다.
  2. updating 속성이 true이면, InvalidStateError 예외를 던지고 단계를 중단합니다.
  3. new mode를 이 속성에 할당하려는 새 값으로 합니다.
  4. [[generate timestamps flag]]가 true이고 new mode가 "segments"이면, TypeError 예외를 던지고 단계를 중단합니다.
  5. readyState 속성이 부모 미디어 소스에서 "ended" 상태라면 다음 단계를 실행합니다:

    1. readyState부모 미디어 소스에서 "open"으로 설정
    2. 작업을 큐에 추가하여 이벤트 발생 이름은 sourceopen이고 대상은 부모 미디어 소스
  6. [[append state]]PARSING_MEDIA_SEGMENT이면, InvalidStateError 예외를 던지고 단계를 중단합니다.
  7. new mode가 "sequence"이면, [[group start timestamp]][[group end timestamp]]로 설정
  8. 속성을 new mode로 업데이트
updating 타입 boolean, readonly

비동기 appendBuffer() 또는 remove() 연산이 아직 처리 중인지를 나타냅니다. 객체 생성 시 false로 초기화됩니다.

buffered 타입 TimeRanges, readonly

SourceBuffer에 버퍼링된 TimeRanges가 무엇인지 나타냅니다. 객체 생성 시 빈 TimeRanges 객체로 초기화됩니다.

속성 읽기 시 다음 단계가 반드시 실행되어야 합니다:

  1. 이 객체가 sourceBuffers에서 부모 미디어 소스에서 제거되었다면, InvalidStateError 예외를 던지고 단계를 중단합니다.
  2. highest end time을 이 SourceBuffer가 관리하는 모든 track buffertrack buffer ranges의 최대 종료값으로 한다.
  3. intersection ranges를 0에서 highest end time까지 단일 범위를 가진 TimeRanges 객체로 한다.
  4. SourceBuffer가 관리하는 각 오디오/비디오 track buffer마다 다음 단계를 실행:
    Note

    텍스트 track buffer는 위 highest end time 계산에는 포함되지만, 여기서 버퍼링 범위 계산에는 제외됩니다. 텍스트 트랙은 연속적이지 않을 수 있으며, 이들 내부 불연속이 다른 미디어 트랙이 동일 구간에서 연속일 때 재생 중단을 야기해서는 안 됩니다.

    1. track ranges를 현재 track buffertrack buffer ranges로 한다.
    2. readyState가 "ended"면 track ranges의 마지막 범위 종료를 highest end time으로 설정
    3. new intersection rangesintersection rangestrack ranges의 교집합으로 함
    4. intersection ranges의 범위를 new intersection ranges로 대체
  5. intersection ranges가 현재 이 속성 값과 정확히 같지 않으면, 현재 속성 값을 intersection ranges로 업데이트
  6. 현재 속성 값을 반환
timestampOffset 타입 double

SourceBuffer에 append되는 이후 미디어 세그먼트의 타임스탬프에 적용되는 offset을 제어합니다. timestampOffset은 초기값 0이며, offset이 적용되지 않음을 의미합니다.

get 시, 초기값 또는 마지막으로 성공적으로 설정된 값을 반환합니다.

set 시 다음 단계를 실행합니다:

  1. new timestamp offset을 이 속성에 할당하려는 새 값으로 함
  2. 이 객체가 sourceBuffers에서 부모 미디어 소스에서 제거되었다면, InvalidStateError 예외를 던지고 단계를 중단
  3. updating이 true면 InvalidStateError 예외를 던지고 단계를 중단
  4. readyState부모 미디어 소스에서 "ended" 상태라면 다음 단계를 실행:

    1. readyState부모 미디어 소스에서 "open"으로 설정
    2. 작업을 큐에 추가하여 이벤트 발생 이름은 sourceopen이고 대상은 부모 미디어 소스
  5. [[append state]]PARSING_MEDIA_SEGMENT이면 InvalidStateError 예외를 던지고 중단
  6. mode가 "sequence"이면 [[group start timestamp]]new timestamp offset으로 설정
  7. 속성을 new timestamp offset으로 업데이트
audioTracks 타입 AudioTrackList, readonly
이 객체가 생성한 AudioTrack 객체 목록입니다.
videoTracks 타입 VideoTrackList, readonly
이 객체가 생성한 VideoTrack 객체 목록입니다.
textTracks 타입 TextTrackList, readonly
이 객체가 생성한 TextTrack 객체 목록입니다.
appendWindowStart 타입 double

append window의 시작에 대한 presentation timestamp입니다. 이 속성은 처음에 presentation start time으로 설정됩니다.

get 시, 초기값 또는 마지막으로 성공적으로 설정된 값을 반환합니다.

set 시 다음 단계를 실행합니다:

  1. 이 객체가 sourceBuffers에서 부모 미디어 소스에서 제거되었다면, InvalidStateError 예외를 던지고 단계를 중단
  2. updating이 true면 InvalidStateError 예외를 던지고 중단
  3. 새 값이 0보다 작거나, appendWindowEnd이상이라면, TypeError 예외를 던지고 중단
  4. 속성을 새 값으로 업데이트
appendWindowEnd 타입 unrestricted double

append window의 종료에 대한 presentation timestamp입니다. 이 속성은 처음에 양의 무한대로 설정됩니다.

get 시, 초기값 또는 마지막으로 성공적으로 설정된 값을 반환합니다.

set 시 다음 단계를 실행합니다:

  1. 이 객체가 sourceBuffers에서 부모 미디어 소스에서 제거되었다면, InvalidStateError 예외를 던지고 중단
  2. updating이 true면 InvalidStateError 예외를 던지고 중단
  3. 새 값이 NaN이면 TypeError 예외를 던지고 중단
  4. 새 값이 appendWindowStart 이하이면, TypeError 예외를 던지고 중단
  5. 속성을 새 값으로 업데이트
onupdatestart 타입 EventHandler

updatestart 이벤트의 핸들러입니다.

onupdate 타입 EventHandler

update 이벤트의 핸들러입니다.

onupdateend 타입 EventHandler

updateend 이벤트의 핸들러입니다.

onerror 타입 EventHandler

error 이벤트의 핸들러입니다.

onabort 타입 EventHandler

abort 이벤트의 핸들러입니다.

5.2 메서드

appendBuffer

BufferSource[WEBIDL] 내의 세그먼트 데이터를 SourceBuffer에 추가합니다.

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

  1. prepare append 알고리즘을 실행합니다.
  2. data[[input buffer]] 끝에 추가합니다.
  3. updating 속성을 true로 설정합니다.
  4. 작업을 큐에 추가하여 이벤트를 발생시키는데, 이름은 updatestart이고, 대상은 이 SourceBuffer 객체입니다.
  5. 비동기적으로 buffer append 알고리즘을 실행합니다.
abort

현재 세그먼트를 중단하고 세그먼트 파서를 초기화합니다.

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

  1. 이 객체가 sourceBuffers에서 부모 미디어 소스에서 제거되었다면, InvalidStateError 예외를 던지고 중단합니다.
  2. readyState 속성이 부모 미디어 소스에서 "open" 상태가 아니면, InvalidStateError 예외를 던지고 중단합니다.
  3. range removal 알고리즘이 실행 중이면, InvalidStateError 예외를 던지고 중단합니다.
  4. updating 속성이 true이면, 다음 단계를 실행:
    1. buffer append 알고리즘이 실행 중이면 중단합니다.
    2. updating 속성을 false로 설정합니다.
    3. 작업을 큐에 추가하여 이벤트 이름은 abort이고, 대상은 이 SourceBuffer 객체입니다.
    4. 작업을 큐에 추가하여 이벤트 이름은 updateend이고, 대상은 이 SourceBuffer 객체입니다.
  5. reset parser state 알고리즘을 실행합니다.
  6. appendWindowStartpresentation start time으로 설정합니다.
  7. appendWindowEnd를 양의 무한대로 설정합니다.
changeType

이 객체와 연관된 MIME 타입을 변경합니다. 이후 appendBuffer() 호출은 새로 append되는 바이트가 새 타입을 준수할 것으로 기대합니다.

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

  1. type이 빈 문자열이면 TypeError 예외를 던지고 중단합니다.
  2. 이 객체가 sourceBuffers에서 부모 미디어 소스에서 제거되었다면, InvalidStateError 예외를 던지고 중단합니다.
  3. updating 속성이 true이면, InvalidStateError 예외를 던지고 중단합니다.
  4. type에 지원되지 않는 MIME 타입이 포함되거나, 현재 또는 이전에 SourceBuffer 객체들에서 명시된 타입들과 호환되지 않는 타입이면, NotSupportedError 예외를 던지고 중단합니다.
  5. readyState 속성이 부모 미디어 소스에서 "ended" 상태라면 다음 단계를 실행:

    1. readyState부모 미디어 소스에서 "open"으로 설정합니다.
    2. 작업을 큐에 추가하여 이벤트 발생 이름은 sourceopen이고 대상은 부모 미디어 소스
  6. reset parser state 알고리즘을 실행합니다.
  7. SourceBuffer 객체의 [[generate timestamps flag]]를 byte stream format registry [MSE-REGISTRY] 내 type에 해당하는 "Generate Timestamps Flag" 컬럼 값으로 업데이트합니다.
  8. [[generate timestamps flag]]가 true인 경우:
    mode 속성을 "sequence"로 설정하며, 이 속성 값 변경에 따른 연관 단계를 모두 실행합니다.
    그 외의 경우:
    mode 속성의 이전 값을 그대로 유지하며, 값 변경에 따른 연관 단계는 실행하지 않습니다.
  9. SourceBuffer 객체의 [[pending initialization segment for changeType flag]]를 true로 설정합니다.
remove

특정 시간 범위의 미디어를 제거합니다. 제거 범위의 startpresentation start time 기준 초 단위이고, endpresentation start time 기준 초 단위입니다.

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

  1. 이 객체가 sourceBuffers에서 부모 미디어 소스에서 제거되었다면, InvalidStateError 예외를 던지고 중단합니다.
  2. updating 속성이 true이면, InvalidStateError 예외를 던지고 중단합니다.
  3. duration이 NaN이면 TypeError 예외를 던지고 중단합니다.
  4. start가 0 미만이거나 duration보다 크면 TypeError 예외를 던지고 중단합니다.
  5. endstart 이하이거나, end가 NaN이면 TypeError 예외를 던지고 중단합니다.
  6. readyState 속성이 부모 미디어 소스에서 "ended" 상태라면 다음 단계를 실행:

    1. readyState부모 미디어 소스에서 "open"으로 설정합니다.
    2. 작업을 큐에 추가하여 이벤트 발생 이름은 sourceopen이고 대상은 부모 미디어 소스
  7. range removal 알고리즘을 startend를 제거 범위로 실행합니다.

5.3 트랙 버퍼

트랙 버퍼는 개별 트랙의 트랙 설명코딩된 프레임을 저장합니다. 트랙 버퍼는 초기화 세그먼트미디어 세그먼트SourceBuffer에 append될 때마다 업데이트됩니다.

트랙 버퍼에는 last decode timestamp 변수가 있으며, 현재 코딩된 프레임 그룹에서 마지막으로 append된 코딩된 프레임의 decode timestamp를 저장합니다. 이 변수는 아직 append된 코딩된 프레임이 없음을 나타내기 위해 초기에 설정되지 않은(unset) 상태입니다.

트랙 버퍼에는 last frame duration 변수가 있으며, 현재 코딩된 프레임 그룹에서 마지막으로 append된 코딩된 프레임 duration을 저장합니다. 이 변수도 아직 append된 코딩된 프레임이 없음을 나타내기 위해 초기에 설정되지 않은(unset) 상태입니다.

트랙 버퍼에는 highest end timestamp 변수가 있으며, 현재 코딩된 프레임 그룹에서 이 트랙 버퍼에 append된 모든 코딩된 프레임코딩된 프레임 종료 타임스탬프 중 가장 높은 값을 저장합니다. 이 변수도 아직 append된 코딩된 프레임이 없음을 나타내기 위해 초기에 설정되지 않은(unset) 상태입니다.

트랙 버퍼에는 need random access point flag 변수가 있으며, 해당 트랙 버퍼가 random access point 코딩된 프레임을 기다리고 있는지 판단합니다. 이 변수는 아무 것도 추가되기 전에 random access point 코딩된 프레임이 필요함을 나타내기 위해 true로 초기화됩니다.

트랙 버퍼에는 track buffer ranges 변수가 있으며, 현재 트랙 버퍼에 저장된 코딩된 프레임이 차지하는 프레젠테이션 시간 범위를 나타냅니다.

참고

트랙 버퍼 구간의 경우, 이러한 프리젠테이션 시간 구간은 presentation timestamp, 프레임 지속시간, 그리고 경우에 따라 멀티플렉스된 SourceBuffer의 트랙 버퍼 전체에 걸친 코딩된 프레임 그룹의 시작 시간에 기반합니다.

명세 목적상, 이 정보는 normalized TimeRanges object에 저장된 것처럼 취급됩니다. 교차된 track buffer rangesHTMLMediaElementbuffered 보고에 사용되며, 각 HTMLMediaElementbuffered의 각 범위 내에서 중단 없는 재생을 반드시 지원해야 합니다.

Note

코딩된 프레임 그룹 시작 시간은 coded frame processing 알고리즘에서 언급된 것과는 약간 다르며, 이는 불연속성(discontinuity) 이후 모든 트랙 버퍼 중 가장 이른 presentation timestamp입니다. 불연속성은 coded frame processing 알고리즘 내부에서 발생하거나, coded frame removal 알고리즘에서 발생할 수 있으며, mode와 관계 없습니다. track buffer ranges의 분리(disjointness) 임계값은 구현별입니다. 예를 들어, 예기치 않은 재생 중단을 줄이기 위해 구현체는 coded frame processing 불연속 검출 로직을 근사하여, 이 트랙 버퍼에서 버퍼링된 최대 프레임 duration의 2배 미만인 gap에 의해 인접한 범위를 합칠 수 있습니다. 또한, 구현체는 muxed SourceBuffer 내의 트랙 버퍼 간에 범위 시작 시간으로 코딩된 프레임 그룹 시작 시간을 사용할 수 있습니다 (예기치 않은 재생 중단 감소 목적).

5.4 이벤트 요약

이벤트 이름 인터페이스 언제 디스패치되는가...
updatestart Event SourceBufferupdating이 false에서 true로 전환될 때.
update Event SourceBuffer에 append 또는 remove가 성공적으로 완료됨. SourceBufferupdating이 true에서 false로 전환될 때.
updateend Event SourceBuffer의 append 또는 remove가 끝났을 때.
error Event SourceBuffer에 append 중 오류가 발생함. updating 이 true에서 false로 전환될 때.
abort Event SourceBuffer의 append가 abort() 호출로 중단됨. updating이 true에서 false로 전환될 때.

5.5 알고리즘

5.5.1 세그먼트 파서 루프

SourceBuffer 객체는 세그먼트 파싱 상태를 추적하는 [[append state]] 내부 슬롯을 가집니다. 이 슬롯은 처음에는 WAITING_FOR_SEGMENT로 설정되며, 데이터가 append될 때 다음 상태들로 전이될 수 있습니다.

append 상태 이름 설명
WAITING_FOR_SEGMENT 초기화 세그먼트 또는 미디어 세그먼트의 시작을 append하기를 기다리는 중.
PARSING_INIT_SEGMENT 현재 초기화 세그먼트를 파싱 중.
PARSING_MEDIA_SEGMENT 현재 미디어 세그먼트를 파싱 중.

SourceBuffer 객체는 [[input buffer]] 내부 슬롯을 가지며, 이는 appendBuffer() 호출 사이에서 파싱되지 않은 바이트를 저장하는 바이트 버퍼입니다. 이 버퍼는 SourceBuffer 객체가 생성될 때 비어 있습니다.

SourceBuffer 객체는 [[buffer full flag]] 내부 슬롯을 가지며, appendBuffer()가 더 많은 바이트를 받아들일 수 있는지 추적합니다. 이 슬롯은 SourceBuffer 객체가 생성될 때 false로 설정되고, 데이터가 append되거나 제거될 때 업데이트됩니다.

SourceBuffer 객체는 [[group start timestamp]] 내부 슬롯을 가지며, "sequence" 모드에서 새로운 코딩된 프레임 그룹의 시작 타임스탬프를 추적합니다. 이 슬롯은 SourceBuffer 객체가 생성될 때 미설정 상태(unset)이며, mode 속성이 "sequence"이고 timestampOffset 속성이 설정될 때, 또는 coded frame processing 알고리즘이 실행될 때 업데이트됩니다.

SourceBuffer 객체는 [[group end timestamp]] 내부 슬롯을 가지며, 현재 코딩된 프레임 그룹 내 모든 코딩된 프레임 종료 타임스탬프 중 가장 높은 값을 저장합니다. 이 슬롯은 SourceBuffer 객체가 생성될 때 0으로 설정되며, coded frame processing 알고리즘에 의해 업데이트됩니다.

Note

[[group end timestamp]]SourceBuffer 내의 모든 트랙 버퍼에서 가장 높은 코딩된 프레임 종료 타임스탬프를 저장합니다. 따라서 트랙별 타임스탬프가 맞지 않는 멀티플렉스(muxed) 세그먼트를 append할 때에는 mode 속성 설정에 주의해야 합니다.

SourceBuffer 객체는 [[generate timestamps flag]] 내부 슬롯을 가지며, 이는 코딩된 프레임에 대해 coded frame processing 알고리즘에 전달할 때 타임스탬프 생성이 필요한지 여부를 나타내는 boolean입니다. 이 플래그는 addSourceBuffer()SourceBuffer 객체를 생성할 때 설정되며, changeType()에 의해 업데이트됩니다.

세그먼트 파서 루프 알고리즘이 호출되면, 다음 단계를 실행합니다:

  1. 루프 시작: [[input buffer]]가 비어 있으면, 아래 데이터가 더 필요함 단계로 이동.
  2. [[input buffer]]SourceBuffer 바이트 스트림 포맷 명세를 위반하는 바이트가 있으면, append error 알고리즘을 실행하고 이 알고리즘을 중단.
  3. 바이트 스트림 포맷 명세에서 반드시 무시하라고 한 바이트를 [[input buffer]] 시작에서 제거.
  4. [[append state]]WAITING_FOR_SEGMENT라면, 다음 단계를 실행:

    1. [[input buffer]] 시작이 초기화 세그먼트의 시작을 나타내면, [[append state]]PARSING_INIT_SEGMENT로 설정.
    2. [[input buffer]] 시작이 미디어 세그먼트의 시작을 나타내면, [[append state]]PARSING_MEDIA_SEGMENT로 설정.
    3. 루프 시작 단계로 이동.
  5. [[append state]]PARSING_INIT_SEGMENT라면, 다음 단계를 실행:

    1. [[input buffer]]에 아직 완전한 초기화 세그먼트가 없으면, 아래 데이터가 더 필요함 단계로 이동.
    2. initialization segment received 알고리즘 실행.
    3. 초기화 세그먼트 바이트를 [[input buffer]] 시작에서 제거.
    4. [[append state]]WAITING_FOR_SEGMENT로 설정.
    5. 루프 시작 단계로 이동.
  6. [[append state]]PARSING_MEDIA_SEGMENT라면, 다음 단계를 실행:

    1. [[first initialization segment received flag]]가 false이거나 [[pending initialization segment for changeType flag]]가 true이면, append error 알고리즘 실행 후 중단.
    2. [[input buffer]]에 하나 이상의 완전한 코딩된 프레임이 있으면, coded frame processing 알고리즘 실행.
      Note

      coded frame processing 알고리즘 실행 빈도는 구현별입니다. input buffer에 전체 미디어 세그먼트가 있을 때 호출할 수도 있고, 완전한 코딩된 프레임이 추가될 때마다 여러 번 호출할 수도 있습니다.

    3. SourceBuffer가 가득 차서 더 이상 미디어 데이터를 받아들일 수 없으면, [[buffer full flag]]를 true로 설정.
    4. [[input buffer]]에 완전한 미디어 세그먼트가 없으면, 아래 데이터가 더 필요함 단계로 이동.
    5. 미디어 세그먼트 바이트를 [[input buffer]] 시작에서 제거.
    6. [[append state]]WAITING_FOR_SEGMENT로 설정.
    7. 루프 시작 단계로 이동.
  7. 데이터가 더 필요함: 호출한 알고리즘에 제어를 반환.

5.5.2 파서 상태 재설정

파서 상태를 재설정해야 할 때, 다음 단계를 실행합니다:

  1. [[append state]]PARSING_MEDIA_SEGMENT와 같고, [[input buffer]] 에 완전한 코딩된 프레임이 있다면, 코딩된 프레임 처리 알고리즘을 모든 완전한 코딩된 프레임이 처리될 때까지 실행합니다.
  2. 모든 트랙 버퍼마지막 디코드 타임스탬프를 해제합니다.
  3. 모든 트랙 버퍼마지막 프레임 지속시간을 해제합니다.
  4. 모든 트랙 버퍼최고 종료 타임스탬프를 해제합니다.
  5. 모든 트랙 버퍼랜덤 액세스 포인트 필요 플래그를 true로 설정합니다.
  6. mode 속성이 "sequence"이면, [[group start timestamp]] 값을 [[group end timestamp]]로 설정합니다.
  7. [[input buffer]]의 모든 바이트를 제거합니다.
  8. [[append state]]WAITING_FOR_SEGMENT로 설정합니다.

5.5.3 추가 오류

추가 작업 중 오류가 발생하면 이 알고리즘이 호출됩니다.

  1. 파서 상태 재설정 알고리즘을 실행합니다.
  2. updating 속성을 false로 설정합니다.
  3. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 error입니다. 해당 SourceBuffer 객체에서 발생합니다.
  4. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 updateend입니다. 해당 SourceBuffer 객체에서 발생합니다.
  5. 스트림 종료 알고리즘을 error 파라미터를 "decode"로 설정하여 실행합니다.

5.5.4 추가 준비

추가 작업이 시작될 때, 다음 단계를 실행하여 SourceBuffer를 검증하고 준비합니다.

  1. SourceBuffersourceBuffers 속성에서 제거되었다면, 상위 미디어 소스에서 InvalidStateError 예외를 발생시키고, 이 단계를 중단합니다.
  2. updating 속성이 true라면, InvalidStateError 예외를 발생시키고, 이 단계를 중단합니다.
  3. 최근 요소 오류를 다음과 같이 결정합니다:
    MediaSourceWindow에서 생성된 경우
    HTMLMediaElementerror 속성이 null이 아니면 최근 요소 오류를 true로 합니다. null이면 최근 요소 오류를 false로 합니다.
    그 외의 경우
    Window의 단계에 따라 값을 결정하되, HTMLMediaElementerror 속성 변경 시 [[port to worker]] 암시 메시지를 사용해 통신합니다. 그런 메시지를 아직 받지 못한 경우, 최근 요소 오류를 false로 합니다.
  4. 최근 요소 오류가 true라면, InvalidStateError 예외를 발생시키고, 이 단계를 중단합니다.
  5. readyState 속성이 상위 미디어 소스에서 "ended" 상태라면 다음 단계를 실행합니다:

    1. readyState 속성을 상위 미디어 소스에서 "open"으로 설정합니다.
    2. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 sourceopen입니다. 상위 미디어 소스에서 발생합니다.
  6. 코딩된 프레임 제거 알고리즘을 실행합니다.
  7. [[buffer full flag]]가 true라면, QuotaExceededError 예외를 발생시키고 이 단계를 중단합니다.

    참고

    이는 구현체가 충분한 데이터를 제거하지 못했거나 추가가 너무 큰 경우 신호입니다. 웹 애플리케이션은 SHOULD remove()를 사용하여 명시적으로 공간을 확보하거나 추가 크기를 줄여야 합니다.

5.5.5 버퍼 추가

appendBuffer()가 호출되면, 다음 단계를 실행하여 추가된 데이터를 처리합니다.

  1. 세그먼트 파서 루프 알고리즘을 실행합니다.
  2. 이전 단계의 세그먼트 파서 루프 알고리즘이 중단되었다면, 이 알고리즘을 중단합니다.
  3. updating 속성을 false로 설정합니다.
  4. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 update입니다. 해당 SourceBuffer 객체에서 발생합니다.
  5. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 updateend입니다. 해당 SourceBuffer 객체에서 발생합니다.

5.5.6 범위 제거

호출자가 다른 SourceBuffer 업데이트를 차단하는 JavaScript 표시 범위 제거 작업을 시작해야 할 때 다음 단계를 따릅니다:

  1. start를 제거 범위의 시작 프리젠테이션 타임스탬프로 설정합니다. 이 값은 프리젠테이션 시작 시간으로부터 초 단위입니다.
  2. end를 제거 범위의 종료 프리젠테이션 타임스탬프로 설정합니다. 이 값은 프리젠테이션 시작 시간으로부터 초 단위입니다.
  3. updating 속성을 true로 설정합니다.
  4. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 updatestart입니다. 해당 SourceBuffer 객체에서 발생합니다.
  5. 제어를 호출자에게 반환하고 나머지 단계를 비동기로 실행합니다.
  6. 코딩된 프레임 제거 알고리즘을 startend를 제거 범위의 시작과 종료로 사용하여 실행합니다.
  7. updating 속성을 false로 설정합니다.
  8. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 update입니다. 해당 SourceBuffer 객체에서 발생합니다.
  9. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 updateend입니다. 해당 SourceBuffer 객체에서 발생합니다.

5.5.7 초기화 세그먼트 수신

세그먼트 파서 루프가 완전한 초기화 세그먼트를 성공적으로 파싱했을 때 다음 단계를 실행합니다:

각 SourceBuffer 객체에는 이 알고리즘에 의해 첫 초기화 세그먼트가 추가되어 수신되었는지를 추적하는 [[first initialization segment received flag]] 내부 슬롯이 있습니다. 이 플래그는 SourceBuffer가 생성될 때 false로 설정되며 아래 알고리즘에 의해 업데이트됩니다.

각 SourceBuffer 객체에는 가장 최근 changeType() 이후 초기화 세그먼트가 필요한지 여부를 추적하는 [[pending initialization segment for changeType flag]] 내부 슬롯이 있습니다. 이 플래그는 SourceBuffer가 생성될 때 false로 설정되고, changeType()에 의해 true로 설정되며, 아래 알고리즘에 의해 다시 false로 재설정됩니다.

  1. duration 속성이 현재 NaN과 같다면 업데이트합니다:
    초기화 세그먼트에 지속시간(duration)이 포함된 경우:
    duration change 알고리즘을 new duration을 초기화 세그먼트의 지속시간으로 설정하여 실행합니다.
    그렇지 않은 경우:
    duration change 알고리즘을 new duration을 양의 무한대로 설정하여 실행합니다.
  2. 초기화 세그먼트에 오디오, 비디오 또는 텍스트 트랙이 없다면, append error 알고리즘을 실행하고 이 단계들을 중단합니다.
  3. [[first initialization segment received flag]] 이 true이면, 다음 단계를 실행합니다:
    1. 다음 속성들을 검증합니다. 검사 중 하나라도 실패하면 append error 알고리즘을 실행하고 이 단계들을 중단합니다.
      • 오디오, 비디오, 텍스트 트랙의 개수가 첫 번째 초기화 세그먼트와 일치합니다.
      • 단일 유형에 대해 둘 이상의 트랙(예: 오디오 2개)이 있는 경우, Track IDs가 첫 번째 초기화 세그먼트의 것과 일치합니다.
      • 각 트랙의 코덱이 사용자 에이전트에서 지원됩니다.
        참고

        사용자 에이전트는, 그렇지 않으면 지원될 코덱이라도, 여기에서는 MAY 비지원으로 간주할 수 있습니다. 이는 해당 코덱이 (a) 이 SourceBuffer 객체에서 가장 최근에 성공한 changeType()type 파라미터에 지정되지 않았거나, (b) 이 객체에서 아직 성공한 changeType()가 없다면, 이 SourceBuffer 객체를 생성한 addSourceBuffer()에 지정되지 않았을 때 해당합니다. 예를 들어, 가장 최근에 성공한 changeType()'video/webm' 또는 'video/webm; codecs="vp8"'로 호출되었는데, 초기화 세그먼트에 vp9 비디오 트랙이 나타나는 경우, 다른 두 속성의 검사(위)가 통과하더라도 사용자 에이전트는 이 단계를 사용하여 디코드 오류를 트리거할 수 있습니다(MAY). 구현체는 실제로 코덱이 지원되지 않거나 다른 두 속성 검사가 실패하는 경우에만 이러한 오류를 트리거하는 것이 권장됩니다. 웹 작성자는 사용자 에이전트 지원을 보다 선제적으로 감지하기 위해 정확한 코덱 파라미터와 함께 changeType(), addSourceBuffer()isTypeSupported()를 사용하는 것이 권장됩니다. changeType()SourceBuffer 객체의 바이트스트림 형식이 변경되는 경우에 필요합니다.

    2. 초기화 세그먼트에서 해당하는 트랙 설명을 각 트랙 버퍼에 추가합니다.
    3. 모든 트랙 버퍼의 need random access point flag를 true로 설정합니다.
  4. active track flag를 false로 둡니다.
  5. [[first initialization segment received flag]] 이 false이면, 다음 단계를 실행합니다:

    1. 초기화 세그먼트에 사용자 에이전트가 지원하지 않는 코덱의 트랙이 포함되어 있다면, append error 알고리즘을 실행하고 이 단계들을 중단합니다.
      참고

      사용자 에이전트는, 그렇지 않으면 지원될 코덱이라도, 여기에서는 MAY 비지원으로 간주할 수 있습니다. 이는 해당 코덱이 (a) 이 SourceBuffer 객체에서 가장 최근에 성공한 changeType()type 파라미터에 지정되지 않았거나, (b) 이 객체에서 아직 성공한 changeType()가 없다면, 이 SourceBuffer 객체를 생성한 addSourceBuffer()에 지정되지 않았을 때 해당합니다. 예를 들어, MediaSource.isTypeSupported('video/webm;codecs="vp8,vorbis"') 가 true를 반환하더라도, addSourceBuffer()'video/webm;codecs="vp8"'로 호출되었고 초기화 세그먼트에 Vorbis 트랙이 나타난다면, 사용자 에이전트는 이 단계를 사용해 디코드 오류를 트리거할 수 있습니다(MAY). 구현체는 이러한 경우 실제로 코덱이 지원되지 않을 때에만 오류를 트리거하는 것이 권장됩니다. 웹 작성자는 사용자 에이전트 지원을 보다 선제적으로 감지하기 위해 changeType(), addSourceBuffer()isTypeSupported()를 정확한 코덱 파라미터와 함께 사용하는 것이 권장됩니다. changeType()SourceBuffer 객체의 바이트스트림 형식이 변경되는 경우에 필요합니다.

    2. 초기화 세그먼트의 각 오디오 트랙에 대해 다음 단계를 실행합니다:

      1. audio byte stream track ID를 현재 처리 중인 트랙의 Track ID로 둡니다.
      2. audio language를 이 트랙에 대해 초기화 세그먼트에 지정된 언어의 BCP 47 언어 태그로 설정하고, 언어 정보가 없으면 빈 문자열로 둡니다.
      3. audio language가 BCP 47의 'und' 값과 같다면, audio language에 빈 문자열을 할당합니다.
      4. audio label을 이 트랙에 대해 초기화 세그먼트에 지정된 라벨로 설정하고, 라벨 정보가 없으면 빈 문자열로 둡니다.
      5. audio kinds를 이 트랙에 대해 초기화 세그먼트에 지정된 종류(kind) 문자열의 시퀀스로 설정하고, kind 정보가 없다면 빈 문자열 하나를 원소로 갖는 시퀀스로 둡니다.
      6. audio kinds의 각 값에 대해 다음 단계를 실행합니다:
        1. current audio kind를 이 반복에서의 audio kinds 값으로 둡니다.
        2. new audio track을 새 AudioTrack 객체로 둡니다.
        3. 고유한 ID를 생성하여 id 프로퍼티에 할당합니다(new audio track).
        4. audio languagelanguage 프로퍼티에 할당합니다(new audio track).
        5. audio labellabel 프로퍼티에 할당합니다(new audio track).
        6. current audio kindkind 프로퍼티에 할당합니다(new audio track).
        7. SourceBuffer 객체의 audioTrackslength 가 0이면, 다음 단계를 실행합니다:

          1. new audio trackenabled 프로퍼티를 true로 설정합니다.
          2. active track flag를 true로 설정합니다.
        8. new audio track을 이 audioTracks 속성(이 SourceBuffer 객체)에 추가합니다.
          참고

          이는 AudioTrackList [HTML] 로직이 작업을 큐에 추가하여 이벤트를 발생시키도록 트리거해야 합니다. 이벤트 이름은 addtrack이며, TrackEvent를 사용하고, track 속성은 new audio track으로 초기화됩니다. 이는 이 audioTracks 속성이 참조하는 AudioTrackList 객체에서 발생합니다(이 SourceBuffer 객체의 속성).

        9. 상위 미디어 소스DedicatedWorkerGlobalScope에서 생성된 경우:
          내부 create track mirror 메시지를 [[port to main]]에 게시하고, 그 암시적 핸들러가 Window에서 다음 단계를 실행하도록 합니다:
          1. mirrored audio track을 새 AudioTrack 객체로 둡니다.
          2. mirrored audio track의 프로퍼티 값을 new audio track에 대해 결정된 값과 동일하게 설정합니다.
          3. mirrored audio track을 HTMLMediaElement의 audioTracks 속성에 추가합니다.
          그 외의 경우:
          new audio track을 HTMLMediaElement의 audioTracks 속성에 추가합니다.
          참고

          이는 AudioTrackList [HTML] 로직이 작업을 큐에 추가하여 이벤트를 발생시키도록 트리거해야 합니다. 이벤트 이름은 addtrack이며, TrackEvent를 사용하고, track 속성은 mirrored audio track 또는 new audio track으로 초기화됩니다. 이는 HTMLMediaElement의 audioTracks 속성이 참조하는 AudioTrackList 객체에서 발생합니다.

      7. 이 트랙을 위한 트랙 버퍼를 새로 생성하여 코딩된 프레임을 저장합니다.
      8. 이 트랙의 트랙 설명트랙 버퍼에 추가합니다.
    3. 초기화 세그먼트의 각 비디오 트랙에 대해 다음 단계를 실행합니다:

      1. video byte stream track ID를 현재 처리 중인 트랙의 Track ID로 둡니다.
      2. video language를 이 트랙에 대해 초기화 세그먼트에 지정된 언어의 BCP 47 언어 태그로 설정하고, 언어 정보가 없으면 빈 문자열로 둡니다.
      3. video language가 BCP 47의 'und' 값과 같다면, video language에 빈 문자열을 할당합니다.
      4. video label을 이 트랙에 대해 초기화 세그먼트에 지정된 라벨로 설정하고, 라벨 정보가 없으면 빈 문자열로 둡니다.
      5. video kinds를 이 트랙에 대해 초기화 세그먼트에 지정된 종류(kind) 문자열의 시퀀스로 설정하고, kind 정보가 없다면 빈 문자열 하나를 원소로 갖는 시퀀스로 둡니다.
      6. video kinds의 각 값에 대해 다음 단계를 실행합니다:
        1. current video kind를 이 반복에서의 video kinds 값으로 둡니다.
        2. new video track을 새 VideoTrack 객체로 둡니다.
        3. 고유한 ID를 생성하여 id 프로퍼티에 할당합니다(new video track).
        4. video languagelanguage 프로퍼티에 할당합니다(new video track).
        5. video labellabel 프로퍼티에 할당합니다(new video track).
        6. current video kindkind 프로퍼티에 할당합니다(new video track).
        7. SourceBuffer 객체의 videoTrackslength 가 0이면, 다음 단계를 실행합니다:

          1. new video trackselected 프로퍼티를 true로 설정합니다.
          2. active track flag를 true로 설정합니다.
        8. new video track을 이 videoTracks 속성(이 SourceBuffer 객체)에 추가합니다.
          참고

          이는 VideoTrackList [HTML] 로직이 작업을 큐에 추가하여 이벤트를 발생시키도록 트리거해야 합니다. 이벤트 이름은 addtrack이며, TrackEvent를 사용하고, track 속성은 new video track으로 초기화됩니다. 이는 이 videoTracks 속성이 참조하는 VideoTrackList 객체에서 발생합니다(이 SourceBuffer 객체의 속성).

        9. 상위 미디어 소스DedicatedWorkerGlobalScope에서 생성된 경우:
          내부 create track mirror 메시지를 [[port to main]]에 게시하고, 그 암시적 핸들러가 Window에서 다음 단계를 실행하도록 합니다:
          1. mirrored video track을 새 VideoTrack 객체로 둡니다.
          2. mirrored video track의 프로퍼티 값을 new video track에 대해 결정된 값과 동일하게 설정합니다.
          3. mirrored video track을 HTMLMediaElement의 videoTracks 속성에 추가합니다.
          그 외의 경우:
          new video track을 HTMLMediaElement의 videoTracks 속성에 추가합니다.
          참고

          이는 VideoTrackList [HTML] 로직이 작업을 큐에 추가하여 이벤트를 발생시키도록 트리거해야 합니다. 이벤트 이름은 addtrack이며, TrackEvent를 사용하고, track 속성은 mirrored video track 또는 new video track으로 초기화됩니다. 이는 HTMLMediaElement의 videoTracks 속성이 참조하는 VideoTrackList 객체에서 발생합니다.

      7. 이 트랙을 위한 트랙 버퍼를 새로 생성하여 코딩된 프레임을 저장합니다.
      8. 이 트랙의 트랙 설명트랙 버퍼에 추가합니다.
    4. 초기화 세그먼트의 각 텍스트 트랙에 대해 다음 단계를 실행합니다:

      1. text byte stream track ID를 현재 처리 중인 트랙의 Track ID로 둡니다.
      2. text language를 이 트랙에 대해 초기화 세그먼트에 지정된 언어의 BCP 47 언어 태그로 설정하고, 언어 정보가 없으면 빈 문자열로 둡니다.
      3. text language가 BCP 47의 'und' 값과 같다면, text language에 빈 문자열을 할당합니다.
      4. text label을 이 트랙에 대해 초기화 세그먼트에 지정된 라벨로 설정하고, 라벨 정보가 없으면 빈 문자열로 둡니다.
      5. text kinds를 이 트랙에 대해 초기화 세그먼트에 지정된 종류(kind) 문자열의 시퀀스로 설정하고, kind 정보가 없다면 빈 문자열 하나를 원소로 갖는 시퀀스로 둡니다.
      6. text kinds의 각 값에 대해 다음 단계를 실행합니다:
        1. current text kind를 이 반복에서의 text kinds 값으로 둡니다.
        2. new text track을 새 TextTrack 객체로 둡니다.
        3. 고유한 ID를 생성하여 id 프로퍼티에 할당합니다(new text track).
        4. text languagelanguage 프로퍼티에 할당합니다(new text track).
        5. text labellabel 프로퍼티에 할당합니다(new text track).
        6. current text kindkind 프로퍼티에 할당합니다(new text track).
        7. new text track의 나머지 프로퍼티를 초기화 세그먼트의 적절한 정보로 채웁니다.
        8. new text trackmode 프로퍼티가 "showing" 이거나 "hidden"이면, active track flag를 true로 설정합니다.
        9. new text track을 이 textTracks 속성(이 SourceBuffer 객체)에 추가합니다.
          참고

          이는 TextTrackList [HTML] 로직이 작업을 큐에 추가하여 이벤트를 발생시키도록 트리거해야 합니다. 이벤트 이름은 addtrack이며, TrackEvent를 사용하고, track 속성은 new text track으로 초기화됩니다. 이는 이 textTracks 속성이 참조하는 TextTrackList 객체에서 발생합니다(이 SourceBuffer 객체의 속성).

        10. 상위 미디어 소스DedicatedWorkerGlobalScope에서 생성된 경우:
          내부 create track mirror 메시지를 [[port to main]]에 게시하고, 그 암시적 핸들러가 Window에서 다음 단계를 실행하도록 합니다:
          1. mirrored text track을 새 TextTrack 객체로 둡니다.
          2. mirrored text track의 프로퍼티 값을 new text track에 대해 결정된 값과 동일하게 설정합니다.
          3. mirrored text track을 HTMLMediaElement의 textTracks 속성에 추가합니다.
          그 외의 경우:
          new text track을 HTMLMediaElement의 textTracks 속성에 추가합니다.
          참고

          이는 TextTrackList [HTML] 로직이 작업을 큐에 추가하여 이벤트를 발생시키도록 트리거해야 합니다. 이벤트 이름은 addtrack이며, TrackEvent를 사용하고, track 속성은 mirrored text track 또는 new text track으로 초기화됩니다. 이는 HTMLMediaElement의 textTracks 속성이 참조하는 TextTrackList 객체에서 발생합니다.

      7. 이 트랙을 위한 트랙 버퍼를 새로 생성하여 코딩된 프레임을 저장합니다.
      8. 이 트랙의 트랙 설명트랙 버퍼에 추가합니다.
    5. active track flag가 true이면, 다음 단계를 실행합니다:
      1. SourceBufferactiveSourceBuffers에 추가합니다.
      2. 작업을 큐에 추가하여 이벤트를 발생시키고, 이벤트 이름은 addsourcebuffer입니다. 이는 activeSourceBuffers에서 발생합니다.
    6. [[first initialization segment received flag]] 를 true로 설정합니다.
  6. [[pending initialization segment for changeType flag]] 를 false로 설정합니다.
  7. active track flag가 true이면, 다음 단계를 실행합니다:
  8. 상위 미디어 소스필요 시 미러링 알고리즘을 사용하여 Window에서 다음 단계를 실행합니다:
    1. HTMLMediaElementreadyState 속성이 HAVE_CURRENT_DATA보다 크면, HTMLMediaElementreadyStateHAVE_METADATA로 설정합니다.
      참고

      HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

  9. sourceBuffers의 각 객체(해당 상위 미디어 소스)가 [[first initialization segment received flag]] 가 true와 같다면, 상위 미디어 소스필요 시 미러링 알고리즘을 사용하여 다음 단계를 Window에서 실행합니다:
    1. HTMLMediaElementreadyState 속성이 HAVE_NOTHING이라면, HTMLMediaElementreadyStateHAVE_METADATA로 설정합니다.
      참고

      HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다. 만약 HAVE_NOTHING에서 HAVE_METADATA로 전이되면, 이는 HTMLMediaElement 로직이 작업을 큐에 추가하여 이벤트를 발생시키도록 트리거해야 하며, 이벤트 이름은 loadedmetadata로, 미디어 요소에서 발생합니다.

5.5.8 코딩된 프레임 처리

세그먼트 파서 루프에 의해 완전한 코딩된 프레임이 파싱되면 다음 단계를 실행합니다:

  1. 미디어 세그먼트의 각 코딩된 프레임에 대해 다음 단계를 실행합니다:

    1. Loop Top:
      [[generate timestamps flag]] 가 true와 같다면:
      1. presentation timestamp를 0으로 둡니다.
      2. decode timestamp를 0으로 둡니다.
      그 외의 경우:
      1. presentation timestamp를 초 단위에서 코딩된 프레임의 프리젠테이션 타임스탬프를 배정밀도 부동소수점으로 표현한 값으로 둡니다.
        참고

        타임드 텍스트 프레임의 프리젠테이션/디코드 타임스탬프를 결정하려면 특수한 처리가 필요할 수 있습니다. 이 정보가 기반 포맷에 명시적으로 존재하지 않거나 프레임 순서에 의존할 수 있기 때문입니다. MPEG2-TS PSI 데이터와 같은 일부 메타데이터 텍스트 트랙은 암시적 타임스탬프만 가질 수 있습니다. 이러한 상황에 대한 포맷별 규칙은 바이트 스트림 포맷 명세 또는 별도의 확장 명세에 있어야 합니다(SHOULD).

      2. decode timestamp를 초 단위에서 코딩된 프레임의 디코드 타임스탬프를 배정밀도 부동소수점으로 표현한 값으로 둡니다.
        참고

        구현체는 내부적으로 타임스탬프를 배정밀도 부동소수점 표현으로 저장할 필요는 없습니다. 여기서는 HTML 명세에서 타임스탬프 표현이 그러하기 때문에 이 표현을 사용합니다. 의도는 불필요한 복잡성을 더하지 않으면서 동작을 명확히 하는 것입니다. 바이트 스트림 포맷이 사용하는 기반 타임스탬프 표현에서 timestampOffset을 더하면 타임스탬프 롤오버가 발생할 수 있다는 사실을 다루기 위함입니다. 구현체는 원하는 어떤 내부 타임스탬프 표현을 사용할 수 있지만, timestampOffset의 추가는 배정밀도 부동소수점 표현을 사용했을 때와 유사하게 동작해야 합니다(SHOULD).

    2. frame duration을 초 단위에서 코딩된 프레임의 지속시간을 배정밀도 부동소수점으로 표현한 값으로 둡니다.
    3. mode가 "sequence"와 같고 [[group start timestamp]] 가 설정되어 있다면, 다음 단계를 실행합니다:
      1. timestampOffset[[group start timestamp]] 에서 presentation timestamp를 뺀 값으로 설정합니다.
      2. [[group end timestamp]][[group start timestamp]] 로 설정합니다.
      3. 모든 트랙 버퍼랜덤 액세스 포인트 필요 플래그를 true로 설정합니다.
      4. [[group start timestamp]]를 해제합니다.
    4. timestampOffset 이 0이 아니라면, 다음 단계를 실행합니다:

      1. timestampOffsetpresentation timestamp에 더합니다.
      2. timestampOffsetdecode timestamp에 더합니다.
    5. track buffer를 코딩된 프레임이 추가될 트랙 버퍼로 둡니다.
    6. track buffer마지막 디코드 타임스탬프가 설정되어 있고, decode timestamp마지막 디코드 타임스탬프보다 작은 경우:
      OR
      track buffer마지막 디코드 타임스탬프가 설정되어 있고, decode timestamp마지막 디코드 타임스탬프의 차이가 마지막 프레임 지속시간의 2배보다 큰 경우:
      1. mode 가 "segments"와 같다면:
        [[group end timestamp]]presentation timestamp로 설정합니다.
        mode 가 "sequence"와 같다면:
        [[group start timestamp]][[group end timestamp]] 로 설정합니다.
      2. 모든 트랙 버퍼마지막 디코드 타임스탬프를 해제합니다.
      3. 모든 트랙 버퍼마지막 프레임 지속시간을 해제합니다.
      4. 모든 트랙 버퍼최고 종료 타임스탬프를 해제합니다.
      5. 모든 트랙 버퍼랜덤 액세스 포인트 필요 플래그를 true로 설정합니다.
      6. 현재 코딩된 프레임의 처리를 다시 시작하기 위해 위의 Loop Top 단계로 이동합니다.
      그렇지 않으면:
      계속합니다.
    7. frame end timestamppresentation timestampframe duration의 합으로 둡니다.
    8. presentation timestampappendWindowStart보다 작다면, 랜덤 액세스 포인트 필요 플래그를 true로 설정하고, 코딩된 프레임을 폐기(dropped)한 다음, 루프 상단으로 이동하여 다음 코딩된 프레임 처리를 시작합니다.
      참고

      일부 구현은 appendWindowStart보다 작은 presentation timestamp를 가진 코딩된 프레임을 수집하고, appendWindowStart보다 크거나 같은 프리젠테이션 타임스탬프를 가진 첫 코딩된 프레임에서 스플라이스를 생성하는 데 사용할 수 있습니다(MAY). 해당 프레임이 랜덤 액세스 포인트가 아니더라도 가능합니다. 이를 지원하려면 여러 디코더나 실시간보다 빠른 디코딩이 필요하므로, 현재로서는 이 동작을 규범 요구사항으로 두지 않습니다.

    9. frame end timestampappendWindowEnd보다 크다면, 랜덤 액세스 포인트 필요 플래그를 true로 설정하고, 코딩된 프레임을 폐기한 다음 루프 상단으로 이동하여 다음 코딩된 프레임 처리를 시작합니다.
      참고

      일부 구현은 appendWindowEnd보다 작은 presentation timestampappendWindowEnd보다 큰 frame end timestamp를 가진 코딩된 프레임을 수집하고, 수집 시점의 append window 내에 있는 수집된 코딩된 프레임의 일부 구간과 이후 처리된 프레임의 시작 부분(수집된 코딩된 프레임의 끝과 부분적으로만 겹치는)을 가로질러 스플라이스를 생성하는 데 사용할 수 있습니다(MAY). 이를 지원하려면 여러 디코더나 실시간보다 빠른 디코딩이 필요하므로, 현재로서는 이 동작을 규범 요구사항으로 두지 않습니다. appendWindowStart를 가로지르는 코딩된 프레임 수집과 함께 사용할 경우, 구현은 이로써 갭 없는 오디오 스플라이싱을 지원할 수 있습니다(MAY).

    10. track buffer랜덤 액세스 포인트 필요 플래그가 true와 같다면, 다음 단계를 실행합니다:
      1. 코딩된 프레임이 랜덤 액세스 포인트가 아니라면, 코딩된 프레임을 폐기하고 루프 상단으로 이동하여 다음 코딩된 프레임 처리를 시작합니다.
      2. track buffer랜덤 액세스 포인트 필요 플래그를 false로 설정합니다.
    11. spliced audio frame을 오디오 스플라이스 정보를 보관하기 위한 미설정 변수로 둡니다.
    12. spliced timed text frame을 타임드 텍스트 스플라이스 정보를 보관하기 위한 미설정 변수로 둡니다.
    13. track buffer마지막 디코드 타임스탬프가 미설정이고, presentation timestamp프리젠테이션 구간 내(의) 코딩된 프레임에 속한다면, 다음 단계를 실행합니다:
      1. overlapped frame을 위 조건에 일치하는 track buffer 내의 코딩된 프레임으로 둡니다.
      2. track buffer가 오디오 코딩된 프레임을 포함하는 경우:
        오디오 스플라이스 프레임 알고리즘을 실행하고, 스플라이스 프레임이 반환되면 이를 spliced audio frame에 할당합니다.
        track buffer가 비디오 코딩된 프레임을 포함하는 경우:
        1. remove window timestampoverlapped frame프리젠테이션 타임스탬프에 1마이크로초를 더한 값으로 둡니다.
        2. presentation timestampremove window timestamp보다 작다면, track buffer에서 overlapped frame을 제거합니다.
          참고

          이는 배정밀도 부동소수점과 유리수 사이를 변환할 때 나타날 수 있는 프레임 타임스탬프 계산의 작은 오차를 보정하기 위한 것입니다. 이 허용오차는 기존 프레임의 시작 시간으로부터 1마이크로초 이내에 있으면 프레임이 기존 프레임을 대체할 수 있도록 합니다. 기존 프레임보다 약간 앞선 프레임은 아래의 제거 단계에서 처리됩니다.

        track buffer가 타임드 텍스트 코딩된 프레임을 포함하는 경우:
        텍스트 스플라이스 프레임 알고리즘을 실행하고, 스플라이스 프레임이 반환되면 이를 spliced timed text frame에 할당합니다.
    14. track buffer에서 기존 코딩된 프레임을 제거합니다:
      track buffer최고 종료 타임스탬프가 설정되어 있지 않은 경우:
      track buffer에서 presentation timestamp보다 크거나 같고 frame end timestamp보다 작은 코딩된 프레임을 모두 제거합니다.
      track buffer최고 종료 타임스탬프가 설정되어 있고 presentation timestamp보다 작거나 같은 경우:
      track buffer에서 최고 종료 타임스탬프보다 크거나 같고 frame end timestamp보다 작은 코딩된 프레임을 모두 제거합니다.
    15. 이전 두 단계에서 제거된 코딩된 프레임에 대한 모든 가능한 디코딩 의존성을 제거하기 위해, 이전 두 단계에서 제거된 프레임과 그 이후의 다음 랜덤 액세스 포인트 사이에 있는 track buffer의 모든 코딩된 프레임을 제거합니다.
      참고

      다음 랜덤 액세스 포인트까지 모든 코딩된 프레임을 제거하는 것은 보수적인 디코딩 의존성 추정입니다. 제거된 프레임과 다음 랜덤 액세스 포인트 사이의 모든 프레임이 제거된 프레임에 의존한다고 가정하기 때문입니다.

    16. spliced audio frame이 설정되어 있는 경우:
      spliced audio frametrack buffer에 추가합니다.
      spliced timed text frame이 설정되어 있는 경우:
      spliced timed text frametrack buffer에 추가합니다.
      그렇지 않은 경우:
      presentation timestamp, decode timestamp, frame duration을 가진 코딩된 프레임track buffer에 추가합니다.
    17. track buffer마지막 디코드 타임스탬프decode timestamp로 설정합니다.
    18. track buffer마지막 프레임 지속시간frame duration으로 설정합니다.
    19. track buffer최고 종료 타임스탬프가 미설정이거나 frame end timestamp최고 종료 타임스탬프보다 크다면, track buffer최고 종료 타임스탬프frame end timestamp로 설정합니다.
      참고

      코딩된 프레임 간의 양방향 예측 때문에 디코드 타임스탬프는 단조 증가하더라도 presentation timestamp는 단조 증가하지 않을 수 있으므로, 보다 큼 비교가 필요합니다.

    20. frame end timestamp[[group end timestamp]]보다 크다면, [[group end timestamp]]frame end timestamp로 설정합니다.
    21. [[generate timestamps flag]] 가 true와 같다면, timestampOffsetframe end timestamp로 설정합니다.
  2. HTMLMediaElementreadyState 속성이 HAVE_METADATA 이고, 새 코딩된 프레임으로 인해 HTMLMediaElementbuffered가 현재 재생 위치에 대한 TimeRanges를 갖게 되면, HTMLMediaElementreadyState 속성을 HAVE_CURRENT_DATA로 설정합니다.

    참고

    HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

  3. HTMLMediaElementreadyState 속성이 HAVE_CURRENT_DATA 이고, 새 코딩된 프레임으로 인해 HTMLMediaElementbuffered가 현재 재생 위치를 포함하고 그 이후의 시간까지 포함하는 TimeRanges를 갖게 되면, HTMLMediaElementreadyState 속성을 HAVE_FUTURE_DATA로 설정합니다.

    참고

    HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

  4. HTMLMediaElementreadyState 속성이 HAVE_FUTURE_DATA 이고, 새 코딩된 프레임으로 인해 HTMLMediaElementbuffered가 현재 재생 위치와 중단 없는 재생을 보장하기에 충분한 데이터를 포함하는 TimeRanges를 갖게 되면, HTMLMediaElementreadyState 속성을 HAVE_ENOUGH_DATA로 설정합니다.

    참고

    HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

  5. 미디어 세그먼트가 현재 duration을 넘어서는 데이터를 포함한다면, duration change 알고리즘을 new duration을 현재 duration과 [[group end timestamp]]의 최댓값으로 설정하여 실행합니다.

5.5.9 코딩된 프레임 제거

특정 시간 범위의 코딩된 프레임을 SourceBuffer에서 제거해야 할 때 다음 단계를 따르세요:

  1. start를 제거 범위의 시작 프리젠테이션 타임스탬프로 둡니다.
  2. end를 제거 범위의 종료 프리젠테이션 타임스탬프로 둡니다.
  3. SourceBuffer의 각 트랙 버퍼에 대해 다음 단계를 실행하세요:

    1. remove end timestamp를 현재 duration 값으로 둡니다.
    2. 트랙 버퍼랜덤 액세스 포인트 타임스탬프가 있고, 그 값이 end 이상이면, remove end timestamp를 그 랜덤 액세스 포인트 타임스탬프로 업데이트합니다.

      참고

      트랙마다 랜덤 액세스 포인트 타임스탬프가 다를 수 있습니다. 왜냐하면 트랙 내 코딩된 프레임 간의 의존성이 서로 다르기 때문입니다.

    3. 트랙 버퍼에서 시작 타임스탬프가 start 이상이고 remove end timestamp 미만인 모든 미디어 데이터를 제거합니다.
      1. 제거된 각 프레임에 대해, 해당 프레임의 디코드 타임스탬프가 프레임의 트랙의 마지막 디코드 타임스탬프와 같으면, 다음 단계를 실행합니다:

        mode가 "segments"와 같으면:
        [[group end timestamp]]프리젠테이션 타임스탬프로 설정합니다.
        mode가 "sequence"와 같으면:
        [[group start timestamp]][[group end timestamp]]로 설정합니다.
      2. 모든 트랙 버퍼마지막 디코드 타임스탬프를 해제합니다.
      3. 모든 트랙 버퍼마지막 프레임 지속시간을 해제합니다.
      4. 모든 트랙 버퍼최고 종료 타임스탬프를 해제합니다.
      5. 모든 트랙 버퍼랜덤 액세스 포인트 필요 플래그를 true로 설정합니다.
    4. 이전 단계에서 제거된 코딩된 프레임에 대한 모든 가능한 디코딩 의존성을 제거하기 위해, 이전 단계에서 제거된 프레임과 그 이후의 다음 랜덤 액세스 포인트 사이에 있는 이 트랙 버퍼의 모든 코딩된 프레임을 제거합니다.
      참고

      다음 랜덤 액세스 포인트까지 모든 코딩된 프레임을 제거하는 것은 보수적인 디코딩 의존성 추정입니다. 제거된 프레임과 다음 랜덤 액세스 포인트 사이의 모든 프레임이 제거된 프레임에 의존한다고 가정하기 때문입니다.

    5. 이 객체가 activeSourceBuffers에 있고, 현재 재생 위치start 이상이고 remove end timestamp 미만이며, HTMLMediaElementreadyStateHAVE_METADATA보다 크면, HTMLMediaElementreadyState 속성을 HAVE_METADATA로 설정하고 재생을 정지(stall)합니다.

      참고

      HTMLMediaElement ready states [HTML] 로직에 따라, HTMLMediaElementreadyState 변경은 HTMLMediaElement에서 이벤트를 트리거할 수 있습니다.

      참고

      이 전이는 현재 위치의 미디어 데이터가 제거되었기 때문에 발생합니다. 현재 위치의 미디어가 추가되거나, 3.15.5 선택/활성 트랙 상태 변경가 일어나기 전까지 재생이 진행되지 않습니다.

  4. [[buffer full flag]]가 true이고, 이 객체가 추가 바이트를 받을 준비가 되어 있으면, [[buffer full flag]]를 false로 설정합니다.

5.5.10 코딩된 프레임 퇴출(eviction)

새로운 데이터가 추가될 때 이 SourceBuffer의 공간을 확보하기 위해 이 알고리즘을 실행합니다.

  1. new data를 이 SourceBuffer에 곧 추가될 데이터로 둡니다.
    Issue 289: 편집? 코딩된 프레임 제거 알고리즘은 |new data|에 따라 "buffer full flag"가 즉시 업데이트될 수 있음을 명시해야 함

    구현체는 MAY 여기서 [[buffer full flag]]를 true로 설정할 수 있습니다. 이는 new data와 기존 [[input buffer]]의 바이트를 합산하여 SourceBuffer 용량을 초과한다고 예측되면 발생할 수 있습니다. 이렇게 하면 오버플로우가 예상되는 new data를 수락하기 전에 보다 적극적인 push-back이 가능합니다. 실제로 최소한 하나의 구현체는 이 방식을 사용합니다.

  2. [[buffer full flag]]가 false와 같으면, 이 단계를 중단합니다.
  3. removal rangesnew data를 위한 공간을 만들기 위해 프레젠테이션에서 제거될 수 있는 프리젠테이션 시간 구간들의 리스트로 둡니다.
    참고

    구현체는 MAY removal ranges를 선택하는 다양한 방법을 사용할 수 있으므로, 웹 애플리케이션은 특정 동작에 SHOULD NOT 의존하면 안 됩니다. 웹 애플리케이션은 buffered 속성을 사용해 버퍼된 데이터의 일부가 제거되었는지 관찰할 수 있습니다.

  4. removal ranges의 각 구간에 대해, 코딩된 프레임 제거 알고리즘을 startend를 해당 제거 구간의 시작/종료 타임스탬프로 하여 실행합니다.

5.5.11 오디오 스플라이스 프레임

코딩된 프레임 처리 알고리즘이 두 오버랩된 오디오 코딩된 프레임에 대해 스플라이스 프레임을 생성해야 할 때 다음 단계를 따르세요:

  1. track buffer를 스플라이스가 포함될 트랙 버퍼로 둡니다.
  2. new coded frametrack buffer에 추가되는 새 코딩된 프레임으로 둡니다.
  3. presentation timestampnew coded frame프리젠테이션 타임스탬프로 둡니다.
  4. decode timestampnew coded frame의 디코드 타임스탬프로 둡니다.
  5. frame durationnew coded frame코딩된 프레임 지속시간으로 둡니다.
  6. overlapped framepresentation timestamp를 포함하는 프리젠테이션 구간을 가진 코딩된 프레임으로 둡니다.
  7. presentation timestampdecode timestampoverlapped frame의 오디오 샘플레이트에 따라 가장 가까운 오디오 샘플 타임스탬프로 업데이트합니다. 타임스탬프가 두 샘플 타임스탬프와 동일하게 떨어져 있다면 더 높은 타임스탬프를 사용하세요 (예: floor(x * sample_rate + 0.5) / sample_rate).
    참고

    예시:

    presentation timestampdecode timestamp는 10.0125로 업데이트됩니다. 10.01255는 10 + 100/8000 (10.0125)에 더 가깝기 때문입니다.

  8. 사용자 에이전트가 크로스페이딩을 지원하지 않으면 다음 단계를 실행합니다:
    1. track buffer에서 overlapped frame을 제거합니다.
    2. 다음 속성으로 track buffer에 무음(silence) 프레임을 추가합니다:
      참고

      일부 구현은 MAY 무음 프레임 양쪽의 코딩된 프레임에 페이드 효과를 적용할 수 있습니다. 이를 통해 전이가 덜 거슬릴 수 있습니다.

    3. 스플라이스 프레임을 제공하지 않고 호출자에게 반환합니다.
      참고

      이는 overlapped frametrack buffer에 처음부터 없었던 것처럼 new coded frametrack buffer에 추가할 수 있도록 의도되었습니다.

  9. frame end timestamppresentation timestampframe duration의 합으로 둡니다.
  10. splice end timestamppresentation timestamp와 스플라이스 지속시간(5 밀리초)의 합으로 둡니다.
  11. fade out coded framesoverlapped frame과, presentation timestamp보다 크고 splice end timestamp보다 작은 프리젠테이션 타임스탬프를 가진 track buffer 내 다른 프레임들로 둡니다.
  12. fade out coded frames에 포함된 모든 프레임을 track buffer에서 제거합니다.
  13. 다음 속성으로 스플라이스 프레임을 반환합니다:
    참고

    이 스플라이스 프레임이 어떻게 렌더링되는지에 대한 자세한 내용은 오디오 스플라이스 렌더링 알고리즘을 참고하세요.

5.5.12 오디오 스플라이스 렌더링

audio splice frame 알고리즘이 생성한 스플라이스 프레임을 미디어 요소가 렌더링해야 할 때 다음 단계를 실행합니다:

  1. fade out coded frames를 스플라이스 동안 페이드 아웃되는 코딩된 프레임으로 둡니다.
  2. fade in coded frames를 스플라이스 동안 페이드 인되는 코딩된 프레임으로 둡니다.
  3. presentation timestampfade out coded frames의 첫 번째 코딩된 프레임의 프리젠테이션 타임스탬프로 둡니다.
  4. end timestampfade in coded frames의 마지막 프레임의 프리젠테이션 타임스탬프코딩된 프레임 지속시간의 합으로 둡니다.
  5. splice timestamp를 스플라이스가 시작되는 프리젠테이션 타임스탬프로 둡니다. 이는 fade in coded frames의 첫 번째 프레임의 프리젠테이션 타임스탬프와 일치합니다.
  6. splice end timestampsplice timestamp + 5밀리초로 둡니다.
  7. fade out samplesfade out coded frames를 디코드하여 생성한 샘플로 둡니다.
  8. fade out samplespresentation timestampsplice end timestamp 사이의 샘플만 포함하도록 자릅니다.
  9. fade in samplesfade in coded frames를 디코드하여 생성한 샘플로 둡니다.
  10. fade out samplesfade in samples의 샘플레이트와 채널 레이아웃이 다르면, 둘 모두를 공통 샘플레이트와 채널 레이아웃으로 변환합니다.
  11. output samples를 출력 샘플을 담을 버퍼로 둡니다.
  12. fade out samplessplice timestamp에서 splice end timestamp 사이의 샘플에 대해 시작 gain 1, 종료 gain 0의 선형 게인 페이드 아웃을 적용합니다.
  13. fade in samplessplice timestamp에서 splice end timestamp 사이의 샘플에 대해 시작 gain 0, 종료 gain 1의 선형 게인 페이드 인을 적용합니다.
  14. fade out samples에서 presentation timestamp부터 splice timestamp까지의 샘플을 output samples로 복사합니다.
  15. splice timestamp에서 splice end timestamp까지 각 샘플에 대해, fade out samples의 샘플과 fade in samples의 해당 샘플을 합산하여 output samples에 저장합니다.
  16. fade in samples에서 splice end timestamp부터 end timestamp까지의 샘플을 output samples로 복사합니다.
  17. output samples를 렌더링합니다.
참고

이 알고리즘의 그래픽 표현입니다.

Audio splice diagram

5.5.13 텍스트 스플라이스 프레임

코딩된 프레임 처리 알고리즘이 두 오버랩된 타임드 텍스트 코딩된 프레임에 대해 스플라이스 프레임을 생성해야 할 때 다음 단계를 따르세요:

  1. track buffer를 스플라이스가 포함될 트랙 버퍼로 둡니다.
  2. new coded frametrack buffer에 추가되는 새 코딩된 프레임으로 둡니다.
  3. presentation timestampnew coded frame프리젠테이션 타임스탬프로 둡니다.
  4. decode timestampnew coded frame의 디코드 타임스탬프로 둡니다.
  5. frame durationnew coded frame코딩된 프레임 지속시간으로 둡니다.
  6. frame end timestamppresentation timestampframe duration의 합으로 둡니다.
  7. first overlapped framepresentation timestamp를 포함하는 프리젠테이션 구간을 가진 코딩된 프레임으로 둡니다.
  8. overlapped presentation timestampfirst overlapped frame프리젠테이션 타임스탬프로 둡니다.
  9. overlapped framesfirst overlapped frame과, presentation timestamp보다 크고 frame end timestamp보다 작은 프리젠테이션 타임스탬프를 가진 track buffer 내 다른 프레임들로 둡니다.
  10. overlapped frames에 포함된 모든 프레임을 track buffer에서 제거합니다.
  11. first overlapped frame코딩된 프레임 지속시간presentation timestamp에서 overlapped presentation timestamp를 뺀 값으로 업데이트합니다.
  12. first overlapped frametrack buffer에 추가합니다.
  13. 스플라이스 프레임을 제공하지 않고 호출자에게 반환합니다.
    참고

    이는 new coded frame이 처음부터 track buffer에 오버랩된 프레임이 없었던 것처럼 추가될 수 있도록 의도되었습니다.

6. SourceBufferList 인터페이스

SourceBufferListSourceBuffer 객체들을 담는 단순 컨테이너 객체입니다. 읽기 전용 배열 접근을 제공하며, 리스트가 수정될 때 이벤트를 발생시킵니다.

WebIDL[Exposed=(Window,DedicatedWorker)]
interface SourceBufferList : EventTarget {
  readonly attribute unsigned long length;

  attribute EventHandler onaddsourcebuffer;
  attribute EventHandler onremovesourcebuffer;

  getter SourceBuffer (unsigned long index);
};

6.1 속성

length (unsigned long 타입, 읽기 전용)

리스트에 있는 SourceBuffer 객체의 개수를 나타냅니다.

onaddsourcebuffer (EventHandler 타입)

addsourcebuffer 이벤트의 이벤트 핸들러입니다.

onremovesourcebuffer (EventHandler 타입)

removesourcebuffer 이벤트의 이벤트 핸들러입니다.

6.2 메서드

getter

리스트의 SourceBuffer 객체를 배열 연산자([])로 접근할 수 있게 합니다.

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

  1. indexlength 속성보다 크거나 같으면 undefined를 반환하고 이 단계를 중단합니다.
  2. 리스트의 index번째 SourceBuffer 객체를 반환합니다.

6.3 이벤트 요약

이벤트 이름 인터페이스 언제 디스패치되는지...
addsourcebuffer Event SourceBuffer가 리스트에 추가될 때.
removesourcebuffer Event SourceBuffer가 리스트에서 제거될 때.

7. ManagedMediaSource 인터페이스

ManagedMediaSource는 메모리 콘텐츠를 적극적으로 관리하는 MediaSource입니다. MediaSource와 달리, user agent는 언제든지 memory cleanup 알고리즘을 통해 sourceBuffers (ManagedSourceBuffer로 채움)에서 콘텐츠를 제거할 수 있습니다.

참고: 제거 사유
WebIDL[Exposed=(Window,DedicatedWorker)]
interface ManagedMediaSource : MediaSource {
  constructor();
  readonly attribute boolean streaming;
  attribute EventHandler onstartstreaming;
  attribute EventHandler onendstreaming;
};

7.1 속성

streaming

가져올 때:

  1. 속성의 현재 값을 반환합니다.

7.2 이벤트 요약

이벤트 이름 인터페이스 언제 디스패치되는지...
startstreaming Event ManagedMediaSourcestreaming 속성이 false에서 true로 변경될 때.
endstreaming Event ManagedMediaSourcestreaming 속성이 true에서 false로 변경될 때.

7.3 알고리즘

7.3.1 ManagedSourceBuffer 모니터링

SourceBuffer Monitoring 알고리즘이 주기적으로 실행될 때 다음 단계를 실행합니다.

중단 없는 재생을 보장할 만큼 충분한 관리 데이터가 있는 상태란 사용자 에이전트가 프레젠테이션을 의미 있는 시간 동안 멈추지 않고 재생할 수 있을 만큼 데이터를 충분히 가지고 있다고 판단하는 구현체 정의 조건입니다. 이 조건은 streaming 값 전환 시점을 항상 평가하는 기준이 됩니다. 이러한 전환은 사용자 에이전트가 충분히 버퍼링되었다고 판단하거나, 반대로 더 많은 데이터가 필요하다고 판단하는 시점을 나타냅니다.

데이터를 효율적으로 가져오고 버퍼링할 수 있는 상태란 사용자 에이전트가 원하는 메모리 사용량을 달성하면서 에너지 효율적으로 새 데이터를 가져올 수 있다고 판단하는 구현체 정의 조건입니다.

  1. MediaSourceSourceBuffer Monitoring 알고리즘을 실행합니다.
  2. can play uninterrupted and efficiently 플래그를, buffered 속성이 현재 재생 위치를 포함하고, 중단 없는 재생을 보장할 만큼 충분한 관리 데이터가 있으며, 데이터를 효율적으로 가져오고 버퍼링할 수 있는 상태일 때 true로 둡니다.
    can play uninterrupted and efficientlystreaming과 다르면, 요소 작업 큐에 추가하여 미디어 요소에서 다음 단계를 실행합니다:
    1. thisstreaming 속성을 can play uninterrupted and efficiently로 설정합니다.
    2. can play uninterrupted and efficiently가 false면, 이벤트를 발생시키고 이벤트 이름은 startstreaming이며, ManagedMediaSource에서 발생합니다.
    3. 그 외의 경우, 이벤트를 발생시키고 이벤트 이름은 endstreaming이며, ManagedMediaSource에서 발생합니다.

7.3.2 메모리 정리

  1. thissourceBuffers의 각 buffer에 대해:
    1. buffermemory cleanup 알고리즘을 실행합니다.

8. BufferedChangeEvent 인터페이스

WebIDL[Exposed=(Window,DedicatedWorker)]
interface BufferedChangeEvent : Event {
  constructor(DOMString type, optional BufferedChangeEventInit eventInitDict = {});

  [SameObject] readonly attribute TimeRanges addedRanges;
  [SameObject] readonly attribute TimeRanges removedRanges;
};

dictionary BufferedChangeEventInit : EventInit {
  TimeRanges addedRanges;
  TimeRanges removedRanges;
};

8.1 속성

addedRanges
마지막 updatestart 이벤트와 updateend 이벤트 사이에 추가된 시간 구간입니다 (이는 마지막으로 코딩된 프레임 처리 알고리즘이 실행되는 동안 발생합니다).
removedRanges
마지막 updatestartupdateend 이벤트 사이에 제거된 시간 구간입니다 (이는 마지막으로 코딩된 프레임 제거 또는 코딩된 프레임 축출 알고리즘이 실행되었거나, 사용자 에이전트가 메모리 정리에 응답하여 콘텐츠를 축출한 경우에 해당합니다).

9. ManagedSourceBuffer 인터페이스

WebIDL[Exposed=(Window,DedicatedWorker)]
interface ManagedSourceBuffer : SourceBuffer {
  attribute EventHandler onbufferedchange;
};

9.1 속성

onbufferedchange

이벤트 핸들러 IDL 속성으로서, 해당 이벤트 핸들러 이벤트 타입bufferedchange입니다.

9.2 이벤트 요약

이벤트 이름 인터페이스 언제 디스패치되는지...
bufferedchange BufferedChangeEvent ManagedSourceBuffer의 buffered 범위가 appendBuffer(), remove(), endOfStream() 호출 이후에 변경되었거나, 사용자 에이전트가 메모리 정리 알고리즘을 실행한 결과로 변경되었을 때 디스패치됩니다.

9.3 알고리즘

9.3.1 Buffered 변경

ManagedSourceBuffer buffer에 대해 bufferbuffered가 변경되게 만드는 모든 작업이 완료되었을 때 (즉, appendBuffer(), remove() 또는 메모리 정리 알고리즘이 완료된 직후) 다음 단계를 실행합니다.

  1. previous buffered ranges를 변경이 발생하기 전의 buffered 속성 값으로 둡니다.
  2. new buffered ranges를 새로운 buffered TimeRanges로 둡니다.
  3. addednew buffered ranges에서 previous buffered ranges를 뺀 결과로 둡니다.
  4. removedprevious buffered ranges에서 new buffered ranges를 뺀 결과로 둡니다.
  5. eventInitDict를 새로운 BufferedChangeEventInit 딕셔너리로 두되, addedRangesadded로, removedRangesremoved로 초기화합니다.
  6. 작업을 큐에 추가하여 이벤트를 발생시키되, 이벤트 이름은 bufferedchange이고, buffer에서 BufferedChangeEvent 인터페이스로, eventInitDict로 초기화하여 발생시킵니다.

9.3.2 메모리 정리

  1. thisManagedMediaSource 부모의 activeSourceBuffers에 포함되어 있지 않다면:
    1. 코딩된 프레임 제거 알고리즘을 start는 0, end는 양의 무한대로 하여 실행하고, 이 단계를 중단합니다.
  2. removal ranges를, 프레젠테이션이 다시 가져올 수 있을 때까지 currentTime부터 끊김 없는 재생을 보장하기 위해 프레젠테이션에서 축출할 수 있는 프리젠테이션 시간 구간들의 목록으로 둡니다.
    참고

    구현체는 removal ranges를 선택하는 데 서로 다른 전략을 사용할 수 있으므로, 웹 애플리케이션은 특정 동작에 의존하지 않아야 합니다. 웹 애플리케이션은 bufferedchange 이벤트를 수신하여 버퍼된 데이터의 일부가 축출되었는지 관찰할 수 있습니다.

  3. removal ranges의 각 구간에 대해, 코딩된 프레임 제거 알고리즘을 startend를 각각 해당 제거 구간의 시작 및 종료 타임스탬프로 하여 실행합니다.

10. HTMLMediaElement 확장

본 섹션은, 요소에 MediaSource가 연결되었을 때 기존의 HTMLMediaElementseekableHTMLMediaElementbuffered 속성이 반드시 반환해야 하는 값과, 기존의 HTMLMediaElementsrcObject 속성이 MediaSourceHandle 객체로 설정될 때 반드시 수행해야 하는 동작을 명시합니다.

HTMLMediaElementseekable 속성은 아래 단계에 따라 생성된 새로운 정적 표준화된 TimeRanges 객체를 반환합니다:

  1. MediaSource가 종료되었거나 종료 중인 DedicatedWorkerGlobalScope에서 생성된 경우, 빈 TimeRanges 객체를 반환하고 이 단계를 중단합니다.
    참고

    이 경우는, terminate() 호출이나 사용자 에이전트의 워커 종료 실행으로 인해 DedicatedWorkerGlobalScope가 종료된 MediaSource에서, 버퍼되었거나 탐색 가능한 미디어에 대한 이전 정보를 더 이상 유지하지 않는 구현을 처리하기 위한 것입니다. 예를 들어 이는 close() 실행의 최종 결과로 발생할 수 있습니다.

    Issue 277: MSE-in-Workers: MediaSource의 워커 종료 시 연결된 요소를 에러로 전이할지(그리고 미디어 요소는 무엇을 해야 하는지) 고려 필요 mse-in-workers

    연결된 워커 MediaSource의 컨텍스트가 파기될 때, (궁극적으로) 미디어 요소 에러 전이가 있어야 할까요? 워커 MSE의 실험적 Chromium 구현은, 컨텍스트 파기 이전과 동일하게 요소의 readyState, networkState, error를 유지하지만, seekable과 buffered 속성은 각각 빈 TimeRange를 보고합니다.

  2. recent durationrecent live seekable range를 각각 duration[[live seekable range]]의 최신 값으로 두되, 다음과 같이 결정합니다:
    MediaSourceWindow에서 생성된 경우
    recent durationduration으로, recent live seekable range[[live seekable range]]로 설정합니다.
    그 외의 경우:
    recent durationrecent live seekable range를 각각, duration[[live seekable range]]에 변화가 있을 때마다 해당 MediaSource[[port to main]]으로 게시하는 암시적 메시지를 처리하여 최근 값으로 설정합니다.
  3. recent duration이 NaN과 같은 경우:
    TimeRanges 객체를 반환합니다.
    recent duration이 양의 무한대와 같은 경우:
    1. recent live seekable range가 비어 있지 않다면:
      1. union rangesrecent live seekable rangeHTMLMediaElementbuffered 속성의 합집합으로 둡니다.
      2. union ranges에서 가장 이른 시작 시각과 가장 큰 종료 시각으로 구성된 단일 구간을 반환하고 이 단계를 중단합니다.
    2. HTMLMediaElementbuffered 속성이 빈 TimeRanges 객체를 반환한다면, 빈 TimeRanges 객체를 반환하고 이 단계를 중단합니다.
    3. 시작 시각이 0이고, 종료 시각이 HTMLMediaElementbuffered 속성이 보고하는 가장 큰 종료 시각인 단일 구간을 반환합니다.
    그 외의 경우:
    시작 시각이 0이고, 종료 시각이 recent duration인 단일 구간을 반환합니다.

HTMLMediaElementbuffered 속성은 아래 단계에 기반한 정적인 표준화된 TimeRanges 객체를 반환합니다.

  1. MediaSource가 종료되었거나 종료 중인 DedicatedWorkerGlobalScope에서 생성된 경우, 빈 TimeRanges 객체를 반환하고 이 단계를 중단합니다.
    참고

    이 경우는, terminate() 호출이나 사용자 에이전트의 워커 종료 실행으로 인해 DedicatedWorkerGlobalScope가 종료된 MediaSource에서, 버퍼되었거나 탐색 가능한 미디어에 대한 이전 정보를 더 이상 유지하지 않는 구현을 처리하기 위한 것입니다.

    Issue 277: MSE-in-Workers: MediaSource의 워커 종료 시 연결된 요소를 에러로 전이할지(그리고 미디어 요소는 무엇을 해야 하는지) 고려 필요 mse-in-workers

    연결된 워커 MediaSource의 컨텍스트가 파기될 때, (궁극적으로) 미디어 요소 에러 전이가 있어야 할까요? 워커 MSE의 실험적 Chromium 구현은, 컨텍스트 파기 이전과 동일하게 요소의 readyState, networkState, error를 유지하지만, seekable과 buffered 속성은 각각 빈 TimeRange를 보고합니다.

  2. recent intersection ranges를 다음과 같이 결정합니다:
    MediaSourceWindow에서 생성된 경우
    1. recent intersection ranges를 빈 TimeRanges 객체로 둡니다.
    2. activeSourceBuffers.length가 0과 같지 않다면, 다음 단계를 실행합니다:
      1. active ranges를, activeSourceBuffers에 있는 각 SourceBuffer 객체의 buffered가 반환한 구간들로 둡니다.
      2. highest end timeactive ranges에서 가장 큰 구간 종료 시각으로 둡니다.
      3. recent intersection ranges를 0부터 highest end time까지의 단일 구간을 포함하는 TimeRanges 객체로 둡니다.
      4. SourceBuffer 객체 각각에 대해, activeSourceBuffers에서 다음 단계를 실행합니다:
        1. source ranges를, 현재 buffered가 반환한 구간들로 둡니다.
        2. readyState가 "ended"라면, source ranges의 마지막 구간 종료 시각을 highest end time으로 설정합니다.
        3. new intersection ranges를, recent intersection rangessource ranges의 교집합으로 둡니다.
        4. recent intersection ranges의 구간들을 new intersection ranges로 교체합니다.
    그 외의 경우:
    recent intersection ranges를 Window 경우의 단계를 실행하여 얻어진 TimeRanges로 둡니다. 단, MediaSource와 그 SourceBuffer 객체들이 각각의 DedicatedWorkerGlobalScope에 있는 상태에서, 그리고 [[port to main]]을 사용한 암시적 메시지로 activeSourceBuffers, readyState 또는 각 buffered의 값을 변경하는 버퍼링 상태의 모든 업데이트를 통신합니다.
    참고

    recent intersection ranges를 자주 재계산하고 통신해야 하는 오버헤드는, 컨텍스트 간 통신 모델에서 언급한 공유 메모리와 락 같은 다른 메커니즘을 사용하여 필요 시 온디맨드로 이 정보를 조회하도록 허용하는 구현 유연성을 허용하는 이유 중 하나입니다.

  3. 이 속성의 현재 값이 아직 이 알고리즘에 의해 설정되지 않았거나, recent intersection ranges가 이 속성의 현재 값과 정확히 동일한 구간 정보를 포함하지 않는다면, 이 속성의 현재 값을 recent intersection ranges로 업데이트합니다.
  4. 이 속성의 현재 값을 반환합니다.

HTMLMediaElementsrcObject 속성이 MediaSourceHandle로 할당되면, 요소의 로드 알고리즘을 호출하기 전에 수행되는 확장된 HTMLMediaElementsrcObject 세터의 동기 단계의 일부로, 해당 MediaSourceHandle[[has ever been assigned as srcobject]]를 true로 설정합니다.

참고

이는 해당 MediaSourceHandle 객체를 이후에 다시 전송하는 것을 방지하여, 그러한 시도가 있을 경우 명확한 동기 예외를 가능하게 합니다.

Issue

MediaSourceHandleHTMLMediaElement의 MediaProvider IDL typedef 및 관련 미디어 공급자 객체 텍스트에 추가할 필요가 있습니다.

11. AudioTrack 확장

본 섹션은 [HTML]의 AudioTrack 정의에 대한 확장을 명시합니다.

WebIDL[Exposed=(Window,DedicatedWorker)]
partial interface AudioTrack {
  readonly attribute SourceBuffer? sourceBuffer;
};
Issue 280: MSE-in-Workers: HTML의 {Audio,Video,Text}Track{,List} IDL에 Exposed에 DedicatedWorker 추가 필요 mse-in-workers
[HTML]의 AudioTrack에는 Window+DedicatedWorker 노출이 필요합니다.

속성

sourceBuffer (유형 SourceBuffer, 읽기 전용, null 가능)

가져올 때 다음 단계를 실행합니다:

이 트랙과 동일한 realm에서 생성된 SourceBuffer에 의해 이 트랙이 생성되었고, 해당 SourceBuffer가 그 상위 미디어 소스sourceBuffers 속성에서 제거되지 않았다면:
이 트랙을 생성한 SourceBuffer를 반환합니다.
그렇지 않은 경우:
null을 반환합니다.
참고
예를 들어, DedicatedWorkerGlobalScopeSourceBuffer가 내부 create track mirror 핸들러에 알림을 보내 Window에서 이 트랙을 생성하도록 했다면, 해당 트랙의 Window 사본에서는 이 속성에 대해 null을 반환합니다.

12. VideoTrack 확장

본 섹션은 [HTML]의 VideoTrack 정의에 대한 확장을 명시합니다.

WebIDL[Exposed=(Window,DedicatedWorker)]
partial interface VideoTrack {
  readonly attribute SourceBuffer? sourceBuffer;
};
Issue 280: MSE-in-Workers: HTML의 {Audio,Video,Text}Track{,List} IDL에 Exposed에 DedicatedWorker 추가 필요 mse-in-workers
[HTML]의 VideoTrack에는 Window+DedicatedWorker 노출이 필요합니다.

속성

sourceBuffer (유형 SourceBuffer, 읽기 전용, null 가능)

가져올 때 다음 단계를 실행합니다:

이 트랙과 동일한 realm에서 생성된 SourceBuffer에 의해 이 트랙이 생성되었고, 해당 SourceBuffer가 그 상위 미디어 소스sourceBuffers 속성에서 제거되지 않았다면:
이 트랙을 생성한 SourceBuffer를 반환합니다.
그렇지 않은 경우:
null을 반환합니다.
참고
예를 들어, DedicatedWorkerGlobalScopeSourceBuffer가 내부 create track mirror 핸들러에 알림을 보내 Window에서 이 트랙을 생성하도록 했다면, 해당 트랙의 Window 사본에서는 이 속성에 대해 null을 반환합니다.

13. TextTrack 확장

본 섹션은 [HTML]의 TextTrack 정의에 대한 확장을 명시합니다.

WebIDL[Exposed=(Window,DedicatedWorker)]
partial interface TextTrack {
  readonly attribute SourceBuffer? sourceBuffer;
};
Issue 280: MSE-in-Workers: HTML의 {Audio,Video,Text}Track{,List} IDL에 Exposed에 DedicatedWorker 추가 필요 mse-in-workers
[HTML]의 TextTrack에는 Window+DedicatedWorker 노출이 필요합니다.

속성

sourceBuffer (유형 SourceBuffer, 읽기 전용, null 가능)

가져올 때 다음 단계를 실행합니다:

이 트랙과 동일한 realm에서 생성된 SourceBuffer에 의해 이 트랙이 생성되었고, 해당 SourceBuffer가 그 상위 미디어 소스sourceBuffers 속성에서 제거되지 않았다면:
이 트랙을 생성한 SourceBuffer를 반환합니다.
그렇지 않은 경우:
null을 반환합니다.
참고
예를 들어, DedicatedWorkerGlobalScopeSourceBuffer가 내부 create track mirror 핸들러에 알림을 보내 Window에서 이 트랙을 생성하도록 했다면, 해당 트랙의 Window 사본에서는 이 속성에 대해 null을 반환합니다.

14. 바이트 스트림 포맷

SourceBuffer에 대해 appendBuffer()로 제공되는 바이트는 논리적 바이트 스트림을 형성합니다. 이러한 바이트 스트림의 포맷과 의미는 바이트 스트림 포맷 명세에서 정의됩니다. 바이트 스트림 포맷 레지스트리 [MSE-REGISTRY]는 addSourceBuffer(), isTypeSupported() 또는 changeType()에 전달될 수 있는 MIME 타입과, 해당 MIME 타입을 사용하여 새로 추가된 데이터를 파싱하는 SourceBuffer가 기대하는 바이트 스트림 포맷 간의 매핑을 제공합니다. 구현체가 상호 운용성을 촉진하기 위해 지원하는 바이트 스트림 포맷에 대한 매핑을 등록하는 것이 권장됩니다. 바이트 스트림 포맷 레지스트리 [MSE-REGISTRY]는 이러한 매핑의 권위 있는 출처입니다. 구현체가 레지스트리에 나열된 MIME 타입을 지원한다고 주장하는 경우, 해당 SourceBuffer 구현은 레지스트리 항목에 나열된 바이트 스트림 포맷 명세MUST 준수해야 합니다.

참고

레지스트리의 바이트 스트림 포맷 명세는 새로운 저장 포맷을 정의하려는 것이 아닙니다. 이 명세의 구현이 수용할 기존 저장 포맷 구조의 부분집합을 개괄할 뿐입니다.

참고

바이트 스트림 포맷의 파싱과 검증은 세그먼트 파서 루프 알고리즘에서 구현됩니다.

본 섹션은 모든 바이트 스트림 포맷 명세에 대한 일반 요구사항을 제공합니다:

바이트 스트림 명세는 최소한 위 요구사항이 성립하도록 보장하는 제약을 MUST 정의해야 합니다. 구현 단순화를 위해 추가 제약을 정의할 MAY 있습니다.

15. 적합성

비규범으로 표시된 섹션뿐만 아니라, 이 명세의 모든 제작 지침, 도표, 예제, 그리고 주석은 비규범적입니다. 이 명세의 나머지 모든 내용은 규범적입니다.

이 문서에서 MAY, MUST, MUST NOT, SHOULD, SHOULD NOT 키워드는, 여기에 표시된 것처럼 모두 대문자로 나타날 때에만 BCP 14 [RFC2119] [RFC8174]에 따라 해석되어야 합니다.

16. 예제

16.1 Media Source Extensions 사용

<video id="v" autoplay></video>
<script>
const video = document.getElementById("v");
const mediaSource = new MediaSource();
mediaSource.addEventListener("sourceopen", onSourceOpen);
video.src = window.URL.createObjectURL(mediaSource);

async function onSourceOpen(e) {
  const mediaSource = e.target;

  if (mediaSource.sourceBuffers.length > 0) return;

  const sourceBuffer = mediaSource.addSourceBuffer(
    'video/webm; codecs="vorbis,vp8"',
  );

  video.addEventListener("seeking", (e) => onSeeking(mediaSource, e.target));
  video.addEventListener("progress", () =>
    appendNextMediaSegment(mediaSource),
  );

  try {
    const initSegment = await getInitializationSegment();

    if (initSegment == null) {
      // Error fetching the initialization segment. Signal end of stream with an error.
      mediaSource.endOfStream("network");
      return;
    }

    // Append the initialization segment.
    sourceBuffer.addEventListener("updateend", function firstAppendHandler() {
      sourceBuffer.removeEventListener("updateend", firstAppendHandler);

      // Append some initial media data.
      appendNextMediaSegment(mediaSource);
    });

    sourceBuffer.appendBuffer(initSegment);
  } catch (error) {
    // Handle errors that might occur during initialization segment fetching.
    console.error("Error fetching initialization segment:", error);
    mediaSource.endOfStream("network");
  }
}

async function appendNextMediaSegment(mediaSource) {
  if (
    mediaSource.readyState === "closed" ||
    mediaSource.sourceBuffers[0].updating
  )
    return;

  // If we have run out of stream data, then signal end of stream.
  if (!haveMoreMediaSegments()) {
    mediaSource.endOfStream();
    return;
  }

  try {
    const mediaSegment = await getNextMediaSegment();

    // NOTE: If mediaSource.readyState == "ended", this appendBuffer() call will
    // cause mediaSource.readyState to transition to "open". The web application
    // should be prepared to handle multiple "sourceopen" events.
    mediaSource.sourceBuffers[0].appendBuffer(mediaSegment);
  }
  catch (error) {
    // Handle errors that might occur during media segment fetching.
    console.error("Error fetching media segment:", error);
    mediaSource.endOfStream("network");
  }
}

function onSeeking(mediaSource, video) {
  if (mediaSource.readyState === "open") {
    // Abort current segment append.
    mediaSource.sourceBuffers[0].abort();
  }

  // Notify the media segment loading code to start fetching data at the
  // new playback position.
  seekToMediaSegmentAt(video.currentTime);

  // Append a media segment from the new playback position.
  appendNextMediaSegment(mediaSource);
}

function onProgress(mediaSource, e) {
  appendNextMediaSegment(mediaSource);
}

// Example of async function for getting initialization segment
async function getInitializationSegment() {
  // Implement fetching of the initialization segment
  // This is just a placeholder function
}

// Example function for checking if there are more media segments
function haveMoreMediaSegments() {
  // Implement logic to determine if there are more media segments
  // This is just a placeholder function
}

// Example function for getting the next media segment
async function getNextMediaSegment() {
  // Implement fetching of the next media segment
  // This is just a placeholder function
}

// Example function for seeking to a specific media segment
function seekToMediaSegmentAt(currentTime) {
  // Implement seeking logic
  // This is just a placeholder function
}
</script>

16.2 Managed Media Source 사용

<script>
async function setUpVideoStream() {
  // Specific video format and codec
  const mediaType = 'video/mp4; codecs="mp4a.40.2,avc1.4d4015"';

  // Check if the type of video format / codec is supported.
  if (!window.ManagedMediaSource?.isTypeSupported(mediaType)) {
    return; // Not supported, do something else.
  }

  // Set up video and its managed source.
  const video = document.createElement("video");
  const source = new ManagedMediaSource();

  video.controls = true;

  await new Promise((resolve) => {
    video.src = URL.createObjectURL(source);
    source.addEventListener("sourceopen", resolve, { once: true });
    document.body.appendChild(video);
  });

  const sourceBuffer = source.addSourceBuffer(mediaType);

  // Set up the event handlers
  sourceBuffer.onbufferedchange = (e) => {
    console.log("onbufferedchange event fired.");
    console.log(`Added Ranges: ${timeRangesToString(e.addedRanges)}`);
    console.log(`Removed Ranges: ${timeRangesToString(e.removedRanges)}`);
  };

  source.onstartstreaming = async () => {
    const response = await fetch("./videos/bipbop.mp4");
    const buffer = await response.arrayBuffer();
    await new Promise((resolve) => {
      sourceBuffer.addEventListener("updateend", resolve, { once: true });
      sourceBuffer.appendBuffer(buffer);
    });
  };

  source.onendstreaming = async () => {
    // Stop fetching new segments here
  };
}

// Helper function...
function timeRangesToString(timeRanges) {
  const ranges = [];
  for (let i = 0; i < timeRanges.length; i++) {
    ranges.push([timeRanges.start(i), timeRanges.end(i)]);
  }
  return "[" + ranges.map(([start, end]) => `[${start}, ${end})` ) + "]";     
}
</script>
<body onload="setUpVideoStream()"></body>

17. 감사의 말

편집자들은 이 명세에 기여해주신 Alex Giladi, Bob Lund, Chris Needham, Chris Poole, Chris Wilson, Cyril Concolato, Dale Curtis, David Dorwin, David Singer, Duncan Rowden, François Daoust, Frank Galligan, Glenn Adams, Jer Noble, Joe Steele, John Simmons, Kagami Sascha Rosylight, Kevin Streeter, Marcos Cáceres, Mark Vickers, Matt Ward, Matthew Gregan, Michael(tm) Smith, Michael Thornburgh, Mounir Lamouri, Paul Adenot, Philip Jägenstedt, Philippe Le Hegaret, Pierre Lemieux, Ralph Giles, Steven Robertson, 그리고 Tatsuya Igarashi께 감사드립니다.

A. VideoPlaybackQuality

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

이전 개정판(예: 권고안 후보의 섹션 5와 10)에 설명된 비디오 재생 품질 메트릭은 이제 [MEDIA-PLAYBACK-QUALITY]의 일부로 개발되고 있습니다. 일부 구현체는 이전 초안의 VideoPlaybackQuality 객체와 HTMLVideoElement 확장 메서드 getVideoPlaybackQuality()를 구현했을 수 있습니다.

B. 이슈 요약

C. 참고 문헌

C.1 규범적 참고문헌

[dom]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[FILEAPI]
File API. Marijn Kruisselbrink. W3C. 4 December 2024. W3C Working Draft. URL: https://www.w3.org/TR/FileAPI/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[MSE-REGISTRY]
Media Source Extensions™ Byte Stream Format Registry. Matthew Wolenetz; Jerry Smith; Aaron Colwell. W3C. URL: https://www.w3.org/TR/mse-byte-stream-format-registry/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/

C.2 참고용 참고문헌

[INBANDTRACKS]
Sourcing In-band Media Resource Tracks from Media Containers into HTML. Silvia Pfeiffer; Bob Lund. W3C. 26 April 2015. Unofficial Draft. URL: https://dev.w3.org/html5/html-sourcing-inband-tracks/
[MEDIA-PLAYBACK-QUALITY]
Media Playback Quality. Mounir Lamouri; Chris Cunningham. W3C. W3C Editor's Draft. URL: https://w3c.github.io/media-playback-quality/
[url]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/