MediaSource

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

注意:此功能在 專用 Web Workers 中可用。

MediaSource 介面是 Media Source Extensions API 的一部分,它代表了 HTMLMediaElement 物件的媒體資料來源。MediaSource 物件可以附加到 HTMLMediaElement 以在使用者代理中播放。

EventTarget MediaSource

建構函式

MediaSource()

構造並返回一個新的 MediaSource 物件,不關聯任何源緩衝區(source buffers)。

例項屬性

MediaSource.activeSourceBuffers 只讀

返回一個 SourceBufferList 物件,其中包含 MediaSource.sourceBuffers 中的 SourceBuffer 物件的一個子集 — 該列表提供了選定的影片軌道、啟用的音訊軌道以及顯示/隱藏的文字軌道。

MediaSource.duration

獲取並設定當前正在呈現的媒體的時長。

MediaSource.handle 只讀

在專用工作執行緒(dedicated worker)中,返回一個 MediaSourceHandle 物件,它是 MediaSource 的一個代理,可以從工作執行緒傳輸回主執行緒,並透過其 HTMLMediaElement.srcObject 屬性附加到媒體元素。

MediaSource.readyState 只讀

返回一個列舉值,表示當前 MediaSource 的狀態:未附加到媒體元素(closed)、已附加並準備好接收 SourceBuffer 物件(open)、已附加但流已透過 MediaSource.endOfStream() 結束(ended)。

MediaSource.sourceBuffers 只讀

返回一個 SourceBufferList 物件,其中包含與此 MediaSource 關聯的 SourceBuffer 物件列表。

靜態屬性

MediaSource.canConstructInDedicatedWorker 只讀

一個布林值;如果實現了 MediaSource 的工作執行緒支援,則返回 true,提供了一種低延遲的特性檢測機制。

例項方法

繼承其父介面 EventTarget 的方法。

MediaSource.addSourceBuffer()

建立給定 MIME 型別的新 SourceBuffer,並將其新增到 MediaSource.sourceBuffers 列表中。

MediaSource.clearLiveSeekableRange()

清除之前透過呼叫 setLiveSeekableRange() 設定的可搜尋範圍。

MediaSource.endOfStream()

發出流結束的訊號。

MediaSource.removeSourceBuffer()

MediaSource.sourceBuffers 列表中移除給定的 SourceBuffer

MediaSource.setLiveSeekableRange()

設定使用者可以在媒體元素中搜索的範圍。

靜態方法

MediaSource.isTypeSupported()

返回一個布林值,指示當前使用者代理是否支援給定的 MIME 型別 — 即,是否能成功為該 MIME 型別建立 SourceBuffer 物件。

事件

sourceclose

MediaSource 例項不再附加到媒體元素時觸發。

sourceended

MediaSource 例項仍附加到媒體元素,但已呼叫 endOfStream() 時觸發。

sourceopen

MediaSource 例項已由媒體元素開啟,並且可以開始向 SourceBuffer 物件(位於 sourceBuffers 中)追加資料時觸發。

示例

完整的基本示例

以下簡單示例使用 XMLHttpRequest 載入影片,並在可以播放時立即播放。此示例由 Nick Desaulniers 編寫,可在此處 檢視即時演示(您也可以 下載原始碼 進行進一步研究)。函式 getMediaSource()(此處未定義)返回一個 MediaSource

js
const video = document.querySelector("video");

const assetURL = "frag_bunny.mp4";
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
const mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
let mediaSource;

if ("MediaSource" in window && MediaSource.isTypeSupported(mimeCodec)) {
  mediaSource = getMediaSource();
  console.log(mediaSource.readyState); // closed
  video.src = URL.createObjectURL(mediaSource);
  mediaSource.addEventListener("sourceopen", sourceOpen);
} else {
  console.error("Unsupported MIME type or codec: ", mimeCodec);
}

function sourceOpen() {
  console.log(this.readyState); // open
  const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
  fetchAB(assetURL, (buf) => {
    sourceBuffer.addEventListener("updateend", () => {
      mediaSource.endOfStream();
      video.play();
      console.log(mediaSource.readyState); // ended
    });
    sourceBuffer.appendBuffer(buf);
  });
}

function fetchAB(url, cb) {
  console.log(url);
  const xhr = new XMLHttpRequest();
  xhr.open("get", url);
  xhr.responseType = "arraybuffer";
  xhr.onload = () => {
    cb(xhr.response);
  };
  xhr.send();
}

在專用工作執行緒中構造 MediaSource 並將其傳遞給主執行緒

可以在專用工作執行緒中訪問 handle 屬性,然後透過 postMessage() 呼叫將生成的 MediaSourceHandle 物件傳輸回建立工作執行緒的執行緒(在此例中為主執行緒)。

js
// Inside dedicated worker
let mediaSource = new MediaSource();
let handle = mediaSource.handle;
// Transfer the handle to the context that created the worker
postMessage({ arg: handle }, [handle]);

mediaSource.addEventListener("sourceopen", () => {
  // Await sourceopen on MediaSource before creating SourceBuffers
  // and populating them with fetched media — MediaSource won't
  // accept creation of SourceBuffers until it is attached to the
  // HTMLMediaElement and its readyState is "open"
});

在主執行緒中,我們透過 message 事件處理器接收控制代碼,透過其 HTMLMediaElement.srcObject 屬性將其附加到 <video> 元素,然後 play 影片。

js
worker.addEventListener("message", (msg) => {
  let mediaSourceHandle = msg.data.arg;
  video.srcObject = mediaSourceHandle;
  video.play();
});

注意: MediaSourceHandle 無法成功傳輸到共享工作執行緒或服務工作執行緒中,或透過它們進行傳輸。

規範

規範
Media Source Extensions™
# mediasource

瀏覽器相容性

另見