前端真的能防录屏?EME(加密媒体扩展)DRM 反录屏原理 + 实战代码
在实际开发中,很多开发者会问:为什么有些视频网站截屏或录屏时画面是黑的?单纯靠 JS 监听用户快捷键往往不够可靠,绕过的方法太多了。要实现真正的防护,必须依赖浏览器原生支持的 API。
这就是 Encrypted Media Extensions (EME)。

什么是 Encrypted Media Extensions(EME)
Encrypted Media Extensions 是 W3C Web API,用于让浏览器播放受 DRM(Digital Rights Management,数字版权保护)加密的媒体。
用通俗的话来说:EME 就是一套 JS API,用来控制浏览器的 DRM 解密模块。
更多详细的介绍可以参考官方文档:https://www.w3.org/TR/encrypted-media/
常见 DRM 方案
| 平台 | DRM |
|---|---|
| Chrome、Android | Google Widevine |
| Edge/Windows | Microsoft PlayReady |
| Safari/iOS/macOS | Apple FairPlay |
EME 是如何实现浏览器防截屏 / 防录屏
在浏览器层面,EME + DRM 可以实现防截屏 / 防录屏,其核心机制如下:
-
媒体文件是加密的 内容本身是加密视频(如 Widevine Modular 加密),没有密钥无法解码。
-
浏览器通过 CDM 模块解密 浏览器内置一个 CDM(Content Decryption Module)。
例如 Chrome 内置 Widevine CDM,CDM 运行在沙箱中,不暴露密钥。
-
禁止系统级截屏(取决于 DRM)
例如在 Chrome 上播放 Netflix 时:
- 用系统截图键 → 图片是黑屏
- 用屏幕录制 → 视频区域是黑色
这是因为 Widevine L1(硬件级)支持防截屏。DRM 解密后的视频帧不会进入 CPU 层,而是直接通过 GPU 的保护路径输出,截屏 API 无法捕获受保护的视频帧。
-
禁止浏览器扩展抓取视频帧 DRM 视频帧在受保护的视频管线(Video Pipeline)中,扩展无法获取。
-
禁止调试工具记录媒体流 媒体解密密钥不会暴露在 JS 中。
EME 播放加密媒体的代码示例
我们知道 EME 是一套 W3C 标准化的 JavaScript API,它在不暴露密钥和明文数据的前提下,充当网页应用、浏览器和底层 DRM 系统(CDM)之间的'安全信使'。
以下示例展示一个使用 EME 播放加密 DASH(mpd)视频的完整流程。
注意:需要服务器提供 License Server 才能真正播放。
创建 video 标签
<video id="video" controls width="600"></video>
JavaScript 初始化 EME
这里我们需要请求支持的 DRM,配置好 initDataTypes 和 videoCapabilities,然后建立 MediaKeys 对象。
const video = document.getElementById("video");
async function initEME() {
// 请求支持的 DRM,如 Widevine
const keySystem = "com.widevine.alpha";
// 配置
const config = [{
initDataTypes: ["cenc"],
videoCapabilities: [{
contentType: 'video/mp4; codecs="avc1.64001E"'
}]
}];
// 请求 DRM 支持
const access = await navigator.requestMediaKeySystemAccess(keySystem, config);
const mediaKeys = await access.createMediaKeys();
await video.setMediaKeys(mediaKeys);
console.log("EME 初始化成功");
}
initEME();
处理 license 请求
当视频开始播放遇到加密内容时,会触发 encrypted 事件。我们需要模拟从许可证服务器获取许可证并喂给 CDM。
video.addEventListener("encrypted", async (event) => {
const session = video.mediaKeys.createSession();
session.addEventListener("message", async (e) => {
// 向授权服务器发送的消息
const license = await fetch("/license", {
method: "POST",
body: e.message
}).then(r => r.arrayBuffer());
// 将 license 喂给 CDM
await session.update(license);
});
// 初始化 CDM
await session.generateRequest(event.initDataType, event.initData);
});
设置加密视频源
最后设置视频源,通常使用 DASH 格式的 mpd 文件。
video.src = "https://example.com/encrypted.mpd"; // 加密视频
如何为你的应用选择方案?
如果你的核心需求是防止用户复制、下载、非法传播视频/音频内容,那么你需要实现 EME DRM。这需要后端准备加密的内容、部署许可证服务器,并前端集成相应的 DRM 厂商(如 Widevine)的 SDK。
如果你的核心需求是防止用户通过截屏、录屏泄露应用界面(如聊天窗口、文档、软件界面),那么你应该寻找操作系统或框架提供的防截屏 API。对于 Web 应用,这通常意味着你需要将应用打包为 Electron 等桌面应用才能实现。
总结
EME 本质是浏览器访问 DRM 的 API,本身不实现防录屏。真正的防录屏能力来自 DRM(Widevine / PlayReady / FairPlay)以及设备硬件。
- 在 L1 级设备上,可完全禁止系统级截屏与录屏;
- 在 PC 浏览器(L3)上基本无法防。
如果你计划构建一个防盗录系统,建议采用以下组合策略:
DRM 加密 → 授权服务器 移动端 App 或支持 L1 的浏览器 加上行为水印 / 动态鉴权等配套策略

