HTMLMediaElement: srcObject 属性

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

HTMLMediaElement 接口的 srcObject 属性用于设置或返回与 HTMLMediaElement 关联的媒体源对象,如果未赋值则为 null

该对象可以是 MediaStreamMediaSourceBlobFile(继承自 Blob)。

注意:截至 2020 年 3 月,只有 Safari 完全支持 srcObject,即支持使用 MediaSourceMediaStreamBlobFile 对象作为值。其他浏览器支持 MediaStream 对象;在它们赶上之前,请考虑回退到使用 URL.createObjectURL() 创建 URL 并将其分配给 HTMLMediaElement.src(示例如下)。此外,截至 Chromium 108 版本,可以通过将专用工作线程 MediaSource 对象的 MediaSourceHandle 实例(从工作线程传输过来)分配给 srcObject 来附加一个专用的工作线程 MediaSource 对象。

一个 MediaStreamMediaSourceBlobFile 对象(但请查看兼容性表格了解实际支持的情况),或者在未赋值时为 null

用法说明

媒体源规范的旧版本要求使用 URL.createObjectURL() 来创建一个对象 URL,然后将 src 设置为该 URL。现在您只需将 srcObject 直接设置为 MediaStream

示例

基本示例

在此示例中,来自摄像头的 MediaStream 被分配给新创建的 <video> 元素。

js
const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true });
const video = document.createElement("video");
video.srcObject = mediaStream;

在此示例中,新的 MediaSource 被分配给新创建的 <video> 元素。

js
const mediaSource = new MediaSource();
const video = document.createElement("video");
video.srcObject = mediaSource;

支持回退到 src 属性

下面的示例支持旧版本浏览器,这些浏览器要求您在 srcObject 不受支持时创建一个对象 URL 并将其分配给 src

首先,来自摄像头的 MediaStream 被分配给新创建的 <video> 元素,并为旧版浏览器提供回退支持。

js
const mediaStream = await navigator.mediaDevices.getUserMedia({ video: true });
const video = document.createElement("video");
if ("srcObject" in video) {
  video.srcObject = mediaStream;
} else {
  // Avoid using this in new browsers, as it is going away.
  video.src = URL.createObjectURL(mediaStream);
}

其次,新的 MediaSource 被分配给新创建的 <video> 元素,并为旧版浏览器以及尚不支持直接分配 MediaSource 的浏览器提供回退支持。

js
const mediaSource = new MediaSource();
const video = document.createElement("video");
// Older browsers may not have srcObject
if ("srcObject" in video) {
  try {
    video.srcObject = mediaSource;
  } catch (err) {
    if (err.name !== "TypeError") {
      throw err;
    }
    // Even if they do, they may only support MediaStream
    video.src = URL.createObjectURL(mediaSource);
  }
} else {
  video.src = URL.createObjectURL(mediaSource);
}

在工作线程中构建 MediaSource 并将其传递到主线程播放

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 无法成功传输到共享工作线程或服务工作线程中,或通过它们进行传输。

规范

规范
HTML
# dom-media-srcobject-dev
Media Source Extensions™
# htmlmediaelement-extensions-srcobject

浏览器兼容性