html无法可靠检测或阻止投屏,因浏览器无标准api感知系统级投屏;唯一有效方案是服务端drm+eme硬件级保护,通过hdcp策略控制输出。

HTML 本身无法可靠检测或阻止投屏行为。浏览器没有提供标准 API 来判断当前页面是否正被镜像、录屏或通过 AirPlay/Chromecast 投射——这是刻意设计的限制,出于隐私与安全考虑。
为什么 navigator.getDisplayMedia 和 screen.orientation 都不适用
有人尝试用 getDisplayMedia 监听屏幕捕获请求,但这只在用户主动调起录屏/共享弹窗时触发(如点击“录制此窗口”),对系统级投屏(比如 macOS 的镜像显示、Windows 的“无线显示器”、iOS 的 AirPlay)完全无感知。而 screen.orientation 或 window.matchMedia("(orientation: landscape)") 只反映设备方向,投屏时手机横屏、电视也横屏,根本无法区分。
-
getDisplayMedia是单次授权行为,无法持续监听;且投屏不经过该 API -
screen.isExtended(实验性)仅表示是否有扩展显示器,但投屏时浏览器常仍报告为单屏 - 任何基于
resize、orientationchange或全屏状态的启发式判断,在多场景下误报率极高(比如用户旋转平板、分屏、PWA 安装后横屏打开)
真正能起作用的只有服务端 + DRM 方案
防投屏的本质是防止未授权的内容复制,不是前端 JS 能解决的问题。可行路径只有一条:使用支持硬件级保护的 DRM 播放流程,把解密和渲染环节交由操作系统可信执行环境(TEE)或 GPU 安全区控制。
- 必须用
MediaKeys+EME接口加载加密视频(如 CENC 格式),并申请widevine/playready/fairplay许可证 - 播放器需配置
videoElement.setSinkId无效,因为投屏目标音频/视频输出不由页面控制;真正起效的是 DRM 策略中设置allowHdcp、minHdcpVersion或outputProtection(如{ "type": "HDCP", "supported": true }) - 即便如此,也不能“禁止投屏”,只能让不满足策略的投屏链路(如非 HDCP 2.2 的 HDMI 延长器、老款 Chromecast)自动降级为黑屏或静音
前端加 JS 干扰的实际效果非常有限
所谓“检测到投屏就暂停视频”“canvas drawImage 后清空”“监听 beforeunload 弹窗阻断”等做法,对现代投屏协议基本无效,反而破坏正常用户体验。
- macOS 屏幕镜像和 iOS AirPlay 是系统级帧缓冲抓取,不经过网页渲染管线,JS 无法注入或拦截
- Chrome 的 Cast SDK 不向页面暴露接收端状态;
chrome.castAPI 只用于发起投屏,不提供反向感知能力 - 试图用
document.hidden或pageVisibility判断,但投屏时页面通常仍为 visible(尤其 PWA 或全屏模式)
真正需要防投屏的业务(如教育平台直播课、付费点播),必须接受:纯前端方案不存在。重点应放在 DRM 集成质量、许可证策略粒度、以及客户端运行环境校验(例如检查 MediaKeyStatusMap 中 key 状态是否为 "usable" 而非 "output-downscaled")——这些细节比写一堆无用的“检测逻辑”重要得多。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











