跳转到内容

Screen Capture API(getDisplayMedia)

发布于 更新于

Screen Capture API 在 Media Capture and Streams 之上扩展了 navigator.mediaDevices.getDisplayMedia(),它会提示用户选择一个屏幕、窗口或标签页, 并返回该显示表面的 MediaStream,用于录制或在网络上发送。

根据 MDN 的 browser-compat-data,getDisplayMedia() 在桌面版 Chrome(自 72 版起)、 Edge(79)、Firefox(66)和 Safari(13)上均受支持。Android 版 Chrome(72–88)和 Android 版 Firefox(66–79)此前曾暴露该方法,但调用总是以 NotAllowedError 失败; 当前的 browser-compat-data 已将这两个平台记录为不支持,iOS 版 Safari 同样不支持该 API。根据 MDN 的说明,该特性属于“有限可用(Limited availability)”,不属于 “Baseline” 广泛可用特性集合,因此在确认目标浏览器确实支持之前,不应假设它与 MediaDevices 的其他方法一样普遍可用。

async function startCapture() {
try {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: { displaySurface: 'browser' },
audio: false,
});
return stream;
} catch (err) {
console.error(`getDisplayMedia failed: ${err.name}`);
return null;
}
}

根据 MDN 的说明,getDisplayMedia() 需要瞬时用户激活(必须从点击等用户手势中调用), 并且每次都会向用户弹出提示——选择的来源既不能持久化,也不能自动完成。video 选项默认值为 true,因此除非你显式传入 video: false,否则总会请求一条视频 轨道——根据 MDN 的说明,显式传入 false 会以 TypeError 拒绝,因为该 API 不 支持仅捕获音频。

在调用前先检测 getDisplayMedia 是否存在;当它缺失或调用失败时,回退到告知用户 屏幕共享不可用的界面,而不是留下空白:

async function captureScreenOrFallback() {
if (!navigator.mediaDevices?.getDisplayMedia) {
// 该浏览器不支持——展示提示信息,而不是空白画面。
return null;
}
try {
return await navigator.mediaDevices.getDisplayMedia({ video: true });
} catch {
// 用户拒绝了提示,或没有可用的捕获来源。
return null;
}
}
  • 根据 MDN 的说明,getDisplayMedia() 仅在安全上下文(HTTPS)中可用,并且需要 display-capture Permissions Policy——其默认允许列表是 self(同源),跨源 嵌入的 iframe 需要显式声明 allow="display-capture" 才能使用该 API。
  • 根据 MDN 指南,捕获来源无法通过 enumerateDevices() 枚举,也从不触发 devicechange 事件,因此应围绕浏览器自带的选择器构建界面,而不是自行列出 来源。
  • 根据 MDN 指南,传入的约束条件不会过滤用户看到的可选项——它们只在用户已经选定 来源之后才应用于该流,因此无法用约束条件来缩小选择器中的候选范围。
  • 根据 MDN 指南,音频轨道是可选的且因浏览器而异:即便请求了 audio: true, 返回的流也可能只包含视频。
  • 根据 browser-compat-data 的记录,Android 版 Chrome(72–88)和 Firefox (66–79)曾暴露 getDisplayMedia,但调用总是以 NotAllowedError 失败; 当前的条目已将这两个平台标记为不支持,因此仅检测方法是否存在,并不能作为 旧版本上是否可用的可靠信号。