# Screen Capture API（getDisplayMedia）

> getDisplayMedia() 让页面提示用户选择屏幕、窗口或标签页进行捕获，返回一个 MediaStream，用于本地录制或通过 WebRTC 发送。

**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` 的其他方法一样普遍可用。

## 如何使用

```js
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` 是否存在；当它缺失或调用失败时，回退到告知用户
屏幕共享不可用的界面，而不是留下空白：

```js
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` 失败；
  当前的条目已将这两个平台标记为不支持，因此仅检测方法是否存在，并不能作为
  旧版本上是否可用的可靠信号。

## 下一步

- [WebRTC](/zh/reference/capabilities/webrtc/) —— 将捕获的流发送给另一个对端。
- [Web Share API](/zh/reference/capabilities/web-share/)